Texture.h 6.6 KB

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