You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

186 lines
5.0 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include "lolgl.h"
  14. // FIXME: fine-tune this define
  15. #if defined LOL_USE_GLEW || defined HAVE_GL_2X || defined HAVE_GLES_2X
  16. namespace lol
  17. {
  18. //
  19. // The TextureData class
  20. // ---------------------
  21. //
  22. class TextureData
  23. {
  24. friend class Texture;
  25. ivec2 m_size;
  26. PixelFormat m_format;
  27. GLuint m_texture;
  28. GLint m_internal_format;
  29. GLenum m_gl_format, m_gl_type;
  30. int m_bytes_per_elem;
  31. };
  32. //
  33. // The Texture class
  34. // -----------------
  35. //
  36. #define GET_CLAMPED(array, index) \
  37. array[std::max(0, std::min((int)(index), \
  38. (int)sizeof(array) / (int)sizeof(*array)))]
  39. Texture::Texture(ivec2 size, PixelFormat format)
  40. : m_data(new TextureData)
  41. {
  42. m_data->m_size = size;
  43. m_data->m_format = format;
  44. static struct
  45. {
  46. GLint internal_format;
  47. GLenum format, type;
  48. int bytes;
  49. }
  50. const gl_formats[] =
  51. {
  52. { 0, 0, 0, 0 }, /* Unknown */
  53. /* FIXME: this is all mixed up for the RGBA/ARGB combinations */
  54. #if defined __native_client__ || defined HAVE_GLES_2X
  55. { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
  56. { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 3 },
  57. { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
  58. /* FIXME: if GL_RGBA is not available, we should advertise
  59. * this format as "not available" on this platform. */
  60. #else
  61. { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */
  62. { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */
  63. /* Seems efficient for little endian textures */
  64. { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
  65. #endif
  66. { 0, 0, 0, 0 }, /* Y_F32 */
  67. { 0, 0, 0, 0 }, /* RGB_F32 */
  68. { 0, 0, 0, 0 }, /* RGBA_F32 */
  69. };
  70. m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
  71. m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
  72. m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
  73. m_data->m_bytes_per_elem = GET_CLAMPED(gl_formats, format).bytes;
  74. glGenTextures(1, &m_data->m_texture);
  75. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  76. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  77. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  78. }
  79. TextureUniform Texture::GetTextureUniform() const
  80. {
  81. TextureUniform ret;
  82. ret.m_flags = m_data->m_texture;
  83. return ret;
  84. }
  85. void Texture::Bind()
  86. {
  87. #if !defined HAVE_GLES_2X
  88. glEnable(GL_TEXTURE_2D);
  89. #endif
  90. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  91. }
  92. void Texture::SetData(void *data)
  93. {
  94. glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
  95. m_data->m_size.x, m_data->m_size.y, 0,
  96. m_data->m_gl_format, m_data->m_gl_type, data);
  97. }
  98. void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
  99. {
  100. glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
  101. m_data->m_gl_format, m_data->m_gl_type, data);
  102. }
  103. void Texture::SetMagFiltering(TextureMagFilter filter)
  104. {
  105. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  106. GLenum gl_filter;
  107. switch (filter)
  108. {
  109. case TextureMagFilter::LINEAR_TEXEL:
  110. gl_filter = GL_LINEAR;
  111. break;
  112. case TextureMagFilter::NEAREST_TEXEL:
  113. default:
  114. gl_filter = GL_NEAREST;
  115. break;
  116. }
  117. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter);
  118. }
  119. void Texture::SetMinFiltering(TextureMinFilter filter)
  120. {
  121. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  122. GLenum gl_filter;
  123. switch (filter)
  124. {
  125. case TextureMinFilter::LINEAR_TEXEL_NO_MIPMAP:
  126. gl_filter = GL_LINEAR;
  127. break;
  128. case TextureMinFilter::NEAREST_TEXEL_NEAREST_MIPMAP:
  129. gl_filter = GL_NEAREST_MIPMAP_NEAREST;
  130. break;
  131. case TextureMinFilter::NEAREST_TEXEL_LINEAR_MIPMAP:
  132. gl_filter = GL_NEAREST_MIPMAP_LINEAR;
  133. break;
  134. case TextureMinFilter::LINEAR_TEXEL_NEAREST_MIPMAP:
  135. gl_filter = GL_LINEAR_MIPMAP_NEAREST;
  136. break;
  137. case TextureMinFilter::LINEAR_TEXEL_LINEAR_MIPMAP:
  138. gl_filter = GL_LINEAR_MIPMAP_LINEAR;
  139. break;
  140. case TextureMinFilter::NEAREST_TEXEL_NO_MIPMAP:
  141. default:
  142. gl_filter = GL_NEAREST;
  143. break;
  144. }
  145. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter);
  146. }
  147. void Texture::GenerateMipmaps()
  148. {
  149. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  150. glGenerateMipmap(GL_TEXTURE_2D);
  151. }
  152. Texture::~Texture()
  153. {
  154. glDeleteTextures(1, &m_data->m_texture);
  155. delete m_data;
  156. }
  157. } /* namespace lol */
  158. #endif