Texture.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #ifndef ANKI_GL_TEXTURE_H
  2. #define ANKI_GL_TEXTURE_H
  3. #include "anki/util/Assert.h"
  4. #include "anki/util/Singleton.h"
  5. #include "anki/gl/Ogl.h"
  6. #include "anki/util/Vector.h"
  7. #include "anki/util/StdTypes.h"
  8. #include <cstdlib>
  9. #include <limits>
  10. #include <thread>
  11. namespace anki {
  12. class Texture;
  13. /// @addtogroup OpenGL
  14. /// @{
  15. /// The absolute limit of textures
  16. const U MAX_TEXTURES = 512;
  17. /// Contains a few hints on how to crate textures
  18. class TextureManager
  19. {
  20. public:
  21. TextureManager();
  22. /// @name Accessors
  23. /// @{
  24. U getAnisotropyLevel() const
  25. {
  26. return anisotropyLevel;
  27. }
  28. void setAnisotropyLevel(U x)
  29. {
  30. anisotropyLevel = x;
  31. }
  32. Bool getMipmappingEnabled() const
  33. {
  34. return mipmapping;
  35. }
  36. void setMipmappingEnabled(Bool x)
  37. {
  38. mipmapping = x;
  39. }
  40. Bool getCompressionEnabled() const
  41. {
  42. return compression;
  43. }
  44. void setCompressionEnabled(Bool x)
  45. {
  46. compression = x;
  47. }
  48. U getMaxUnitsCount() const
  49. {
  50. return unitsCount;
  51. }
  52. /// @}
  53. private:
  54. /// @name Hints
  55. /// Hints when creating new textures. The implementation may try to ignore
  56. /// them
  57. /// @{
  58. U anisotropyLevel;
  59. Bool mipmapping;
  60. /// If true the new textures will be compressed if not already
  61. Bool compression;
  62. /// @}
  63. U unitsCount;
  64. };
  65. /// The global texture manager
  66. typedef Singleton<TextureManager> TextureManagerSingleton;
  67. /// Class for effective binding of textures
  68. ///
  69. /// @note GL has some nonsense where you can bind different texture targets in
  70. /// the same unit. This class doesn't support that
  71. class TextureUnits
  72. {
  73. public:
  74. TextureUnits();
  75. /// Alias for glActiveTexture
  76. void activateUnit(U unit);
  77. /// Bind the texture to a unit. It's not sure that it will activate the unit
  78. /// @return The texture unit index
  79. U bindTexture(const Texture& tex);
  80. /// Like bindTexture but ensure that the unit is active
  81. void bindTextureAndActivateUnit(const Texture& tex);
  82. /// Unbind a texture from it's unit
  83. void unbindTexture(const Texture& tex);
  84. /// Get the number of the texture unit the @a tex is binded. Returns -1 if
  85. /// not binded to any unit
  86. I whichUnit(const Texture& tex);
  87. private:
  88. /// Texture unit representation
  89. struct Unit
  90. {
  91. /// Have the GL ID to save memory. 0 if no tex is binded to that unit
  92. GLuint tex;
  93. /// Born time. The bigger the value the latter the unit has been
  94. /// accessed. This practically means that if the @a born is low the
  95. /// unit is a candidate for replacement
  96. U64 born;
  97. };
  98. /// Texture units
  99. Vector<Unit> units;
  100. /// XXX
  101. Vector<I8> texIdToUnitId;
  102. /// The active texture unit
  103. I activeUnit;
  104. /// How many times the @a choseUnit has been called. Used to set the
  105. /// Unit::born
  106. U64 choseUnitTimes;
  107. /// Helper method. It returns the texture unit where the @a tex can be
  108. /// binded
  109. U choseUnit(const Texture& tex, Bool& allreadyBinded);
  110. };
  111. /// The global texture units manager. Its per thread
  112. typedef SingletonThreadSafe<TextureUnits> TextureUnitsSingleton;
  113. /// Texture class.
  114. /// Generally its thread safe as long as you have a shared context and the
  115. /// driver supports it
  116. class Texture
  117. {
  118. friend class TextureManager;
  119. public:
  120. /// Texture filtering type
  121. enum TextureFilteringType
  122. {
  123. TFT_NEAREST,
  124. TFT_LINEAR,
  125. TFT_TRILINEAR
  126. };
  127. /// Texture initializer struct
  128. struct Initializer
  129. {
  130. U width = 0;
  131. U height = 0;
  132. U depth = 0;
  133. GLenum target = GL_TEXTURE_2D;
  134. GLenum internalFormat = GL_NONE;
  135. GLenum format = GL_NONE;
  136. /// The type of the data. Not relevant if data is zero
  137. GLenum type = GL_NONE;
  138. const void* data = nullptr;
  139. Bool mipmapping = false;
  140. TextureFilteringType filteringType = TFT_NEAREST;
  141. Bool repeat = true;
  142. I anisotropyLevel = 0;
  143. PtrSize dataSize = 0; ///< For compressed textures
  144. };
  145. /// @name Constructors/Destructor
  146. /// @{
  147. /// Default constructor
  148. Texture()
  149. {}
  150. Texture(const Initializer& init)
  151. {
  152. create(init);
  153. }
  154. /// Desrcuctor
  155. ~Texture();
  156. /// @}
  157. /// @name Accessors
  158. /// Thread safe
  159. /// @{
  160. GLuint getGlId() const
  161. {
  162. ANKI_ASSERT(isCreated());
  163. return glId;
  164. }
  165. GLenum getInternalFormat() const
  166. {
  167. ANKI_ASSERT(isCreated());
  168. return internalFormat;
  169. }
  170. GLenum getFormat() const
  171. {
  172. ANKI_ASSERT(isCreated());
  173. return format;
  174. }
  175. GLenum getTarget() const
  176. {
  177. ANKI_ASSERT(isCreated());
  178. return target;
  179. }
  180. GLenum getType() const
  181. {
  182. ANKI_ASSERT(isCreated());
  183. return type;
  184. }
  185. I getUnit() const
  186. {
  187. ANKI_ASSERT(isCreated());
  188. return TextureUnitsSingleton::get().whichUnit(*this);
  189. }
  190. GLuint getWidth() const
  191. {
  192. ANKI_ASSERT(isCreated());
  193. return width;
  194. }
  195. GLuint getHeight() const
  196. {
  197. ANKI_ASSERT(isCreated());
  198. return height;
  199. }
  200. GLuint getDepth() const
  201. {
  202. ANKI_ASSERT(isCreated());
  203. return depth;
  204. }
  205. /// @}
  206. /// Create a texture
  207. void create(const Initializer& init);
  208. /// Bind the texture to a unit that the texture unit system will decide
  209. /// @return The texture init
  210. U bind() const;
  211. /// Change the filtering type
  212. void setFiltering(const TextureFilteringType filterType)
  213. {
  214. TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);
  215. setFilteringNoBind(filterType);
  216. }
  217. TextureFilteringType getFiltering() const
  218. {
  219. return filtering;
  220. }
  221. /// Set texture parameter
  222. void setParameter(GLenum param, GLint value)
  223. {
  224. TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);
  225. glTexParameteri(target, param, value);
  226. }
  227. /// Generate new mipmaps
  228. void genMipmap();
  229. /// Read the data from the texture. Available only in GL desktop
  230. void readPixels(void* data, U level = 0) const;
  231. private:
  232. GLuint glId = 0; ///< Identification for OGL
  233. GLenum target = GL_NONE; ///< GL_TEXTURE_2D, GL_TEXTURE_3D... etc
  234. GLenum internalFormat = GL_NONE; ///< GL_COMPRESSED_RED, GL_RGB16 etc
  235. GLenum format = GL_NONE; ///< GL_RED, GL_RG, GL_RGB etc
  236. GLenum type = GL_NONE; ///< GL_UNSIGNED_BYTE, GL_BYTE etc
  237. GLuint width = 0, height = 0, depth = 0;
  238. TextureFilteringType filtering;
  239. Bool isCreated() const
  240. {
  241. return glId != 0;
  242. }
  243. void setFilteringNoBind(TextureFilteringType filterType);
  244. };
  245. /// @}
  246. } // end namespace anki
  247. #endif