Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

247 строки
6.6 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. /* FIXME: this is all mixed up for the RGBA/ARGB combinations */
  71. # if defined USE_D3D9
  72. { D3DFMT_R8G8B8, 3 }, /* RGB_8 */
  73. { D3DFMT_UNKNOWN, 0 }, /* RGBA_8 */
  74. { D3DFMT_A8R8G8B8, 4 }, /* ARGB_8 */
  75. { D3DFMT_UNKNOWN, 0 }, /* ABGR_8 */
  76. { D3DFMT_L8, 1 }, /* Y8 */
  77. # else
  78. { D3DFMT_UNKNOWN, 0 },
  79. { D3DFMT_UNKNOWN, 0 },
  80. /* By default the X360 will swizzle the texture. Ask for linear. */
  81. { D3DFMT_LIN_A8R8G8B8, 4 },
  82. { D3DFMT_UNKNOWN, 0 },
  83. { D3DFMT_LIN_L8, 1 },
  84. # endif
  85. };
  86. D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format).format;
  87. # if defined USE_D3D9
  88. int d3d_usage = D3DUSAGE_DYNAMIC;
  89. # else
  90. int d3d_usage = D3DUSAGE_WRITEONLY;
  91. # endif
  92. g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
  93. d3d_usage, d3d_format,
  94. D3DPOOL_DEFAULT, &m_data->m_texture, nullptr);
  95. m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes;
  96. #else
  97. static struct
  98. {
  99. GLint internal_format;
  100. GLenum format, type;
  101. int bytes;
  102. }
  103. const gl_formats[] =
  104. {
  105. { 0, 0, 0, 0 }, /* Unknown */
  106. /* FIXME: this is all mixed up for the RGBA/ARGB combinations */
  107. #if __CELLOS_LV2__
  108. { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 },
  109. { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4 },
  110. { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4 },
  111. { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4 },
  112. { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
  113. #elif defined __native_client__ || defined HAVE_GLES_2X
  114. { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 3 },
  115. { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
  116. { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
  117. /* FIXME: if GL_RGBA is not available, we should advertise
  118. * this format as "not available" on this platform. */
  119. { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
  120. { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
  121. #else
  122. { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */
  123. /* Seems efficient for little endian textures */
  124. { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
  125. { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
  126. { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ABGR_8 */
  127. { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */
  128. #endif
  129. };
  130. m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
  131. m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
  132. m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
  133. m_data->m_bytes_per_elem = GET_CLAMPED(gl_formats, format).bytes;
  134. glGenTextures(1, &m_data->m_texture);
  135. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  136. # if defined __CELLOS_LV2__
  137. /* We need this hint because by default the storage type is
  138. * GL_TEXTURE_SWIZZLED_GPU_SCE. */
  139. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
  140. GL_TEXTURE_TILED_GPU_SCE);
  141. # endif
  142. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  143. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  144. #endif
  145. }
  146. ShaderTexture Texture::GetTexture() const
  147. {
  148. ShaderTexture ret;
  149. #if defined USE_D3D9 || defined _XBOX
  150. ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
  151. #else
  152. ret.m_flags = m_data->m_texture;
  153. #endif
  154. return ret;
  155. }
  156. void Texture::Bind()
  157. {
  158. #if defined _XBOX || defined USE_D3D9
  159. g_d3ddevice->SetTexture(0, m_data->m_texture);
  160. #else
  161. # if !defined HAVE_GLES_2X
  162. glEnable(GL_TEXTURE_2D);
  163. # endif
  164. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  165. #endif
  166. }
  167. void Texture::SetData(void *data)
  168. {
  169. #if defined _XBOX || defined USE_D3D9
  170. D3DLOCKED_RECT rect;
  171. # if defined USE_D3D9
  172. m_data->m_texture->LockRect(0, &rect, nullptr, D3DLOCK_DISCARD);
  173. # else
  174. m_data->m_texture->LockRect(0, &rect, nullptr, 0);
  175. # endif
  176. memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y);
  177. m_data->m_texture->UnlockRect(0);
  178. #else
  179. glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
  180. m_data->m_size.x, m_data->m_size.y, 0,
  181. m_data->m_gl_format, m_data->m_gl_type, data);
  182. #endif
  183. }
  184. void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
  185. {
  186. #if defined _XBOX || defined USE_D3D9
  187. D3DLOCKED_RECT rect;
  188. m_data->m_texture->LockRect(0, &rect, nullptr, 0);
  189. int stride = size.x * m_data->m_bytes_per_elem;
  190. for (int j = 0; j < size.y; j++)
  191. {
  192. uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
  193. uint8_t *src = (uint8_t *)data + j * stride;
  194. memcpy(dst, src, stride);
  195. }
  196. m_data->m_texture->UnlockRect(0);
  197. #else
  198. glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
  199. m_data->m_gl_format, m_data->m_gl_type, data);
  200. #endif
  201. }
  202. Texture::~Texture()
  203. {
  204. #if defined USE_D3D9 || defined _XBOX
  205. m_data->m_texture->Release();
  206. #else
  207. glDeleteTextures(1, &m_data->m_texture);
  208. #endif
  209. delete m_data;
  210. }
  211. } /* namespace lol */