1 // -*- C++ -*- 2 /* GG is a GUI for OpenGL. 3 Copyright (C) 2003-2008 T. Zachary Laine 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public License 7 as published by the Free Software Foundation; either version 2.1 8 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free 17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA 19 20 If you do not wish to comply with the terms of the LGPL please 21 contact the author as other terms are available for a fee. 22 23 Zach Laine 24 whatwasthataddress@gmail.com */ 25 26 /** \file Texture.h \brief Contains the Texture class, which encapsulates an 27 OpenGL texture object; the SubTexture class, which represents a portion of 28 an OpenGL texture object; and the TextureManager class, which provides 29 GUI-wide management of Texture objects. */ 30 31 #ifndef _GG_Texture_h_ 32 #define _GG_Texture_h_ 33 34 #include <GG/Base.h> 35 #include <GG/Exception.h> 36 37 #include <boost/filesystem/path.hpp> 38 39 namespace GG { 40 41 /** \brief This class encapsulates an OpenGL texture object. 42 43 If the dimensions of the image used to initialize the texture are not both 44 powers of two, the texture is created with dimensions of the next largest 45 (or equal) powers of two. The original image occupies the region near the 46 texture's origin, and the rest is zero-initialized. This is done to 47 prevent the image from being scaled, since textures used in a GUI almost 48 always must maintain pixel accuracy. The original image size and 49 corresponding texture coords are saved, and can be accessed through 50 DefaultWidth(), DefaultHeight(), and DefaultTexCoords(), respectively. 51 These are kept so that only the originally-loaded-image part of the 52 texture can be used, if desired. All initialization functions first free 53 the OpenGL texture currently in use by the texture (if any) and create a 54 new one. When the load filename is "" or the image parameter is 0, all 55 initialization functions fail silently, performing no initialization and 56 allocating no memory or OpenGL texture. Serialized Textures save the 57 filename associated with the texture when available, so the originally 58 loaded file can be reloaded again later. If no such file exists, such as 59 when a Texture is created from in-memory image data, the contents of the 60 Texture are read from video memory and saved as binary data. A 61 default-constructed Texture will have niether a filename nor raw image 62 data. */ 63 class GG_API Texture 64 { 65 public: 66 /** \name Structors */ ///@{ 67 Texture(); 68 69 virtual ~Texture(); 70 //@} 71 72 /** \name Accessors */ ///@{ 73 const boost::filesystem::path& Path() const; ///< returns the file path from which this texture was loaded (default / empty if this texture was not loaded from a file) 74 75 GLenum WrapS() const; ///< returns S-wrap mode associated with this opengl texture 76 GLenum WrapT() const; ///< returns T-wrap mode associated with this opengl texture 77 GLenum MinFilter() const; ///< returns minimization filter modes associated with this opengl texture 78 GLenum MagFilter() const; ///< returns maximization filter modes associated with this opengl texture 79 unsigned int BytesPP() const; ///< returns the image's color depth in bytes 80 X Width() const; ///< returns width of entire texture 81 Y Height() const; ///< returns height of entire texture 82 bool MipMapped() const; ///< returns true if the texture has mipmaps 83 GLuint OpenGLId() const; ///< GLuint "name" of the opengl texture object associated with this object 84 const GLfloat* DefaultTexCoords() const; ///< texture coordinates to use by default when blitting this texture 85 X DefaultWidth() const; ///< returns width in pixels, based on initial image (0 if texture was not loaded) 86 Y DefaultHeight() const; ///< returns height in pixels, based on initial image (0 if texture was not loaded) 87 88 /** Blit any portion of texture to any place on screen, scaling as 89 necessary*/ 90 void OrthoBlit(const Pt& pt1, const Pt& pt2, const GLfloat* tex_coords = nullptr) const; 91 92 /** Blit default portion of texture unscaled to \a pt (upper left 93 corner)*/ 94 void OrthoBlit(const Pt& pt) const; 95 //@} 96 97 /** \name Mutators */ ///@{ 98 // intialization functions 99 /** Frees any currently-held memory and loads a texture from file \a 100 path. \throw GG::Texture::BadFile Throws if the texture creation 101 fails. */ 102 void Load(const boost::filesystem::path& path, bool mipmap = false); 103 104 /** Frees any currently-held memory and creates a texture from supplied 105 array \a image. \throw GG::Texture::Exception Throws applicable 106 subclass if the texture creation fails in one of the specified 107 ways. */ 108 void Init(X width, Y height, const unsigned char* image, GLenum format, GLenum type, 109 unsigned bytes_per_pixel, bool mipmap = false); 110 111 void SetFilters(GLenum min, GLenum mag); ///< sets the opengl min/mag filter modes associated with opengl texture m_opengl_id 112 void Clear(); ///< frees the opengl texture object associated with this object 113 //@} 114 115 /** \name Exceptions */ ///@{ 116 /** The base class for Texture exceptions. */ 117 GG_ABSTRACT_EXCEPTION(Exception); 118 119 /** Thrown when valid texture data cannot be read from a file. */ 120 GG_CONCRETE_EXCEPTION(BadFile, GG::Texture, Exception); 121 122 /** Thrown when an unsupported number of color channels is requested. */ 123 GG_CONCRETE_EXCEPTION(InvalidColorChannels, GG::Texture, Exception); 124 125 /** Thrown when GL fails to provide a requested texture object. */ 126 GG_CONCRETE_EXCEPTION(InsufficientResources, GG::Texture, Exception); 127 //@} 128 129 private: 130 Texture(const Texture& rhs); ///< disabled 131 Texture& operator=(const Texture& rhs); ///< disabled 132 void InitFromRawData(X width, Y height, const unsigned char* image, GLenum format, GLenum type, 133 unsigned int bytes_per_pixel, bool mipmap); 134 unsigned char* GetRawBytes(); 135 136 boost::filesystem::path m_path; ///< file path from which this Texture was constructed 137 138 unsigned int m_bytes_pp = 0; 139 X m_width = GG::X0; 140 Y m_height = GG::Y0; 141 142 GLenum m_wrap_s = GL_REPEAT; 143 GLenum m_wrap_t = GL_REPEAT; 144 GLenum m_min_filter = GL_LINEAR_MIPMAP_LINEAR; 145 GLenum m_mag_filter = GL_LINEAR; 146 147 bool m_mipmaps = false; 148 GLuint m_opengl_id = 0; ///< OpenGL texture ID 149 GLenum m_format = GL_INVALID_ENUM; 150 GLenum m_type = GL_INVALID_ENUM; 151 152 /// each of these is used for a non-power-of-two-sized graphic loaded into a power-of-two-sized texture 153 GLfloat m_tex_coords[4] = {0.0f, 0.0f, 0.0f, 0.0f}; ///< the texture coords used to blit from this texture by default (reflecting original image width and height) 154 X m_default_width = GG::X0; ///< the original width and height of this texture to be used in blitting 155 Y m_default_height = GG::Y0; 156 }; 157 158 /** \brief This class is a convenient way to store the info needed to use a 159 portion of an OpenGL texture. */ 160 class GG_API SubTexture 161 { 162 public: 163 /** \name Structors */ ///@{ 164 SubTexture(); 165 166 /** Creates a SubTexture from a GG::Texture and coordinates into it. 167 \throw GG::SubTexture::BadTexture Throws if the given Texture is null. 168 \throw GG::SubTexture::InvalidTextureCoordinates Throws if the texture 169 coordinates are not well formed.*/ 170 SubTexture(const std::shared_ptr<const Texture>& texture, X x1, Y y1, X x2, Y y2); 171 172 /** Creates a SubTexture from a GG::Texture and uses coordinates to cover 173 the whole texture. 174 \throw GG::SubTexture::BadTexture Throws if the given Texture is null.*/ 175 SubTexture(const std::shared_ptr<const Texture>& texture); 176 177 SubTexture(const SubTexture& rhs); 178 179 const SubTexture& operator=(const SubTexture& rhs); 180 181 virtual ~SubTexture(); 182 //@} 183 184 /** \name Accessors */ ///@{ 185 bool Empty() const; ///< returns true if this object has no associated GG::Texture 186 const GLfloat* TexCoords() const; ///< texture coordinates to use when blitting this sub-texture 187 X Width() const; ///< width of sub-texture in pixels 188 Y Height() const; ///< height of sub-texture in pixels 189 const Texture* GetTexture() const;///< returns the texture the SubTexture is a part of 190 191 /** Blit sub-texture to any place on screen, scaling as necessary \see 192 GG::Texture::OrthoBlit*/ 193 void OrthoBlit(const Pt& pt1, const Pt& pt2) const; 194 195 /** Blit sub-texture unscaled to \a pt (upper left corner) \see 196 GG::Texture::OrthoBlit*/ 197 void OrthoBlit(const Pt& pt) const; 198 //@} 199 200 /** \name Mutators */ ///@{ 201 void Clear(); 202 //@} 203 204 /** \name Exceptions */ ///@{ 205 /** The base class for SubTexture exceptions. */ 206 GG_ABSTRACT_EXCEPTION(Exception); 207 208 /** Thrown when an attempt is made to create a SubTexture using a null 209 texture. */ 210 GG_CONCRETE_EXCEPTION(BadTexture, GG::SubTexture, Exception); 211 212 /** Thrown when invalid or out-of-order texture coordinates are 213 supplied.*/ 214 GG_CONCRETE_EXCEPTION(InvalidTextureCoordinates, GG::SubTexture, Exception); 215 //@} 216 217 private: 218 /** shared_ptr to texture object with entire image. */ 219 std::shared_ptr<const Texture> m_texture; 220 X m_width; 221 Y m_height; 222 GLfloat m_tex_coords[4]; ///< position of element within containing texture 223 }; 224 225 /** \brief A singleton that loads and stores textures for use by GG. 226 227 This class is essentially a very thin wrapper around a map of Texture 228 smart pointers, keyed on std::string texture names. The user need only 229 request a texture through GetTexture(); if the texture is not already 230 resident, it will be loaded. If the user would like to create her own 231 images and store them in the manager, that can be accomplished via 232 StoreTexture() calls.*/ 233 class GG_API TextureManager 234 { 235 public: 236 /** \name Accessors */ ///@{ 237 const std::map<std::string, std::shared_ptr<Texture>>& Textures() const; 238 //@} 239 240 /** \name Mutators */ ///@{ 241 /** Stores a pre-existing GG::Texture in the manager's texture pool, and 242 returns a shared_ptr to it. \warning Calling code <b>must not</b> 243 delete \a texture; \a texture becomes the property of the manager, 244 which will eventually delete it. */ 245 std::shared_ptr<Texture> StoreTexture(Texture* texture, const std::string& texture_name); 246 247 /** Stores a pre-existing GG::Texture in the manager's texture pool, and 248 returns a shared_ptr to it. \warning Calling code <b>must not</b> 249 delete \a texture; \a texture becomes the property of the manager, 250 which will eventually delete it. */ 251 std::shared_ptr<Texture> StoreTexture(const std::shared_ptr<Texture>& texture, const std::string& texture_name); 252 253 /** Returns a shared_ptr to the texture created from image file \a path. 254 If the texture is not present in the manager's pool, it will be loaded 255 from disk. */ 256 std::shared_ptr<Texture> GetTexture(const boost::filesystem::path& path, bool mipmap = false); 257 258 /** Removes the manager's shared_ptr to the texture created from image 259 file \a path, if it exists. \note Due to shared_ptr semantics, the 260 texture may not be deleted until much later. */ 261 void FreeTexture(const boost::filesystem::path& path); 262 263 /** Removes the manager's shared_ptr to the texture stored with the name 264 \a name, if it exists. \note Due to shared_ptr semantics, the 265 texture may not be deleted until much later. */ 266 void FreeTexture(const std::string& name); 267 //@} 268 269 private: 270 TextureManager(); 271 std::shared_ptr<Texture> LoadTexture(const boost::filesystem::path& path, bool mipmap); 272 273 /** Indexed by string, not path, because some textures may be stored by a 274 name and not loaded from a path. */ 275 std::map<std::string, std::shared_ptr<Texture>> m_textures; 276 277 friend GG_API TextureManager& GetTextureManager(); 278 }; 279 280 /** Returns the singleton TextureManager instance. */ 281 GG_API TextureManager& GetTextureManager(); 282 283 } // namespace GG 284 285 #endif 286