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.
 
 
 

250 line
6.3 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include "core.h"
  14. #include "lolgl.h"
  15. #if defined _WIN32 && defined USE_D3D9
  16. # define FAR
  17. # define NEAR
  18. # include <d3d9.h>
  19. #endif
  20. using namespace std;
  21. #if defined USE_D3D9
  22. extern IDirect3DDevice9 *g_d3ddevice;
  23. #elif defined _XBOX
  24. extern D3DDevice *g_d3ddevice;
  25. #endif
  26. namespace lol
  27. {
  28. //
  29. // The TextureData class
  30. // ---------------------
  31. //
  32. class TextureData
  33. {
  34. friend class Texture;
  35. ivec2 m_size;
  36. PixelFormat m_format;
  37. #if defined USE_D3D9
  38. IDirect3DTexture9 *m_texture;
  39. #elif defined _XBOX
  40. D3DTexture *m_texture;
  41. #else
  42. GLuint m_texture;
  43. GLint m_internal_format;
  44. GLenum m_gl_format, m_gl_type;
  45. #endif
  46. int m_bytes_per_elem;
  47. };
  48. //
  49. // The Texture class
  50. // -----------------
  51. //
  52. #define GET_CLAMPED(array, index) \
  53. array[std::max(0, std::min((int)(index), \
  54. (int)sizeof(array) / (int)sizeof(*array)))]
  55. Texture::Texture(ivec2 size, PixelFormat format)
  56. : m_data(new TextureData)
  57. {
  58. m_data->m_size = size;
  59. m_data->m_format = format;
  60. #if defined USE_D3D9 || defined _XBOX
  61. static struct
  62. {
  63. D3DFORMAT format;
  64. int bytes;
  65. }
  66. const d3d_formats[] =
  67. {
  68. /* Unknown */
  69. { D3DFMT_UNKNOWN, 0 },
  70. /* R8G8B8 */
  71. # if defined USE_D3D9
  72. { D3DFMT_R8G8B8, 3 },
  73. # else
  74. { D3DFMT_UNKNOWN, 0 },
  75. # endif
  76. /* A8R8G8B8 */
  77. # if defined USE_D3D9
  78. { D3DFMT_A8R8G8B8, 4 },
  79. # else
  80. /* By default the X360 will swizzle the texture. Ask for linear. */
  81. { D3DFMT_LIN_A8R8G8B8, 4 },
  82. # endif
  83. /* Y8 */
  84. # if defined USE_D3D9
  85. { D3DFMT_L8, 1 },
  86. # else
  87. /* By default the X360 will swizzle the texture. Ask for linear. */
  88. { D3DFMT_LIN_L8, 1 },
  89. # endif
  90. };
  91. D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format).format;
  92. # if defined USE_D3D9
  93. int d3d_usage = D3DUSAGE_DYNAMIC;
  94. # else
  95. int d3d_usage = D3DUSAGE_WRITEONLY;
  96. # endif
  97. g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
  98. d3d_usage, d3d_format,
  99. D3DPOOL_DEFAULT, &m_data->m_texture, NULL);
  100. m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes;
  101. #else
  102. static struct
  103. {
  104. GLint internal_format;
  105. GLenum format, type;
  106. int bytes;
  107. }
  108. const gl_formats[] =
  109. {
  110. { 0, 0, 0, 0 }, /* Unknown */
  111. #if __CELLOS_LV2__
  112. { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 },
  113. { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4 },
  114. { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4 },
  115. { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
  116. #elif defined __native_client__ || defined HAVE_GLES_2X
  117. { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 3 },
  118. { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
  119. /* FIXME: if GL_RGBA is not available, we should advertise
  120. * this format as "not available" on this platform. */
  121. { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
  122. { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
  123. #else
  124. { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */
  125. /* Seems efficient for little endian textures */
  126. { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
  127. { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ABGR_8 */
  128. { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */
  129. #endif
  130. };
  131. m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
  132. m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
  133. m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
  134. m_data->m_bytes_per_elem = GET_CLAMPED(gl_formats, format).bytes;
  135. glGenTextures(1, &m_data->m_texture);
  136. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  137. # if defined __CELLOS_LV2__
  138. /* We need this hint because by default the storage type is
  139. * GL_TEXTURE_SWIZZLED_GPU_SCE. */
  140. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
  141. GL_TEXTURE_TILED_GPU_SCE);
  142. # endif
  143. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  144. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  145. #endif
  146. }
  147. ShaderTexture Texture::GetTexture() const
  148. {
  149. ShaderTexture ret;
  150. #if defined USE_D3D9 || defined _XBOX
  151. ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
  152. #else
  153. ret.m_flags = m_data->m_texture;
  154. #endif
  155. return ret;
  156. }
  157. void Texture::Bind()
  158. {
  159. #if defined _XBOX || defined USE_D3D9
  160. g_d3ddevice->SetTexture(0, m_data->m_texture);
  161. #else
  162. # if !defined HAVE_GLES_2X
  163. glEnable(GL_TEXTURE_2D);
  164. # endif
  165. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  166. #endif
  167. }
  168. void Texture::SetData(void *data)
  169. {
  170. #if defined _XBOX || defined USE_D3D9
  171. D3DLOCKED_RECT rect;
  172. # if defined USE_D3D9
  173. m_data->m_texture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
  174. # else
  175. m_data->m_texture->LockRect(0, &rect, NULL, 0);
  176. # endif
  177. memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y);
  178. m_data->m_texture->UnlockRect(0);
  179. #else
  180. glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
  181. m_data->m_size.x, m_data->m_size.y, 0,
  182. m_data->m_gl_format, m_data->m_gl_type, data);
  183. #endif
  184. }
  185. void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
  186. {
  187. #if defined _XBOX || defined USE_D3D9
  188. D3DLOCKED_RECT rect;
  189. m_data->m_texture->LockRect(0, &rect, NULL, 0);
  190. int stride = size.x * m_data->m_bytes_per_elem;
  191. for (int j = 0; j < size.y; j++)
  192. {
  193. uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
  194. uint8_t *src = (uint8_t *)data + j * stride;
  195. memcpy(dst, src, stride);
  196. }
  197. m_data->m_texture->UnlockRect(0);
  198. #else
  199. glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
  200. m_data->m_gl_format, m_data->m_gl_type, data);
  201. #endif
  202. }
  203. Texture::~Texture()
  204. {
  205. #if defined USE_D3D9 || defined _XBOX
  206. m_data->m_texture->Release();
  207. #else
  208. glDeleteTextures(1, &m_data->m_texture);
  209. #endif
  210. delete m_data;
  211. }
  212. } /* namespace lol */