221 linhas
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 FrameBufferData class
  30. // -------------------------
  31. //
  32. class FrameBufferData
  33. {
  34. friend class FrameBuffer;
  35. ivec2 m_size;
  36. #if defined USE_D3D9
  37. IDirect3DTexture9 *m_texture;
  38. IDirect3DSurface9 *m_surface, *m_back_surface;
  39. #elif defined _XBOX
  40. D3DTexture *m_texture;
  41. D3DSurface *m_surface, *m_back_surface;
  42. #else
  43. GLuint m_fbo, m_texture, m_depth;
  44. #endif
  45. };
  46. //
  47. // The FrameBuffer class
  48. // ----------------------
  49. //
  50. FrameBuffer::FrameBuffer(ivec2 size)
  51. : m_data(new FrameBufferData)
  52. {
  53. m_data->m_size = size;
  54. #if defined USE_D3D9
  55. if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1,
  56. D3DUSAGE_RENDERTARGET,
  57. D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
  58. &m_data->m_texture, nullptr)))
  59. Abort();
  60. if (FAILED(m_data->m_texture->GetSurfaceLevel(0, &m_data->m_surface)))
  61. Abort();
  62. #elif defined _XBOX
  63. if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, 0,
  64. D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
  65. &m_data->m_texture, nullptr)))
  66. Abort();
  67. if (FAILED(g_d3ddevice->CreateRenderTarget(size.x, size.y,
  68. D3DFMT_A8R8G8B8,
  69. D3DMULTISAMPLE_NONE, 0, 0,
  70. &m_data->m_surface, nullptr)))
  71. Abort();
  72. #else
  73. # if GL_VERSION_1_1
  74. GLenum internal_format = GL_RGBA8;
  75. GLenum format = GL_BGRA;
  76. GLenum depth = GL_DEPTH_COMPONENT;
  77. # elif defined __CELLOS_LV2__
  78. /* Supported drawable formats on the PS3: GL_ARGB_SCE, GL_RGB16F_ARB,
  79. * GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB. */
  80. GLenum internal_format = GL_ARGB_SCE;
  81. GLenum format = GL_RGBA;
  82. # else
  83. GLenum internal_format = GL_RGBA;
  84. GLenum format = GL_RGBA;
  85. # endif
  86. GLenum wrapmode = GL_REPEAT;
  87. GLenum filtering = GL_NEAREST;
  88. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  89. glGenFramebuffers(1, &m_data->m_fbo);
  90. glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo);
  91. # else
  92. glGenFramebuffersOES(1, &m_data->m_fbo);
  93. glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo);
  94. # endif
  95. glGenTextures(1, &m_data->m_texture);
  96. glActiveTexture(GL_TEXTURE0);
  97. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  98. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLenum)wrapmode);
  99. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLenum)wrapmode);
  100. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLenum)filtering);
  101. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLenum)filtering);
  102. glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size.x, size.y, 0,
  103. format, GL_UNSIGNED_BYTE, nullptr);
  104. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  105. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  106. GL_TEXTURE_2D, m_data->m_texture, 0);
  107. # else
  108. glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT,
  109. GL_TEXTURE_2D, m_data->m_texture, 0);
  110. # endif
  111. m_data->m_depth = GL_INVALID_ENUM;
  112. # if GL_VERSION_1_1
  113. /* FIXME: not implemented on GL ES, see
  114. * http://stackoverflow.com/q/4041682/111461 */
  115. if (depth != GL_INVALID_ENUM)
  116. {
  117. glGenRenderbuffers(1, &m_data->m_depth);
  118. glBindRenderbuffer(GL_RENDERBUFFER, m_data->m_depth);
  119. glRenderbufferStorage(GL_RENDERBUFFER, depth, size.x, size.y);
  120. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  121. GL_RENDERBUFFER, m_data->m_depth);
  122. }
  123. # endif
  124. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  125. glCheckFramebufferStatus(GL_FRAMEBUFFER);
  126. # endif
  127. Unbind();
  128. #endif
  129. }
  130. FrameBuffer::~FrameBuffer()
  131. {
  132. #if defined USE_D3D9 || defined _XBOX
  133. m_data->m_surface->Release();
  134. m_data->m_texture->Release();
  135. #else
  136. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  137. glDeleteFramebuffers(1, &m_data->m_fbo);
  138. # else
  139. glDeleteFramebuffersOES(1, &m_data->m_fbo);
  140. # endif
  141. glDeleteTextures(1, &m_data->m_texture);
  142. # if GL_VERSION_1_1
  143. if (m_data->m_depth != GL_INVALID_ENUM)
  144. glDeleteRenderbuffers(1, &m_data->m_depth);
  145. # endif
  146. #endif
  147. delete m_data;
  148. }
  149. ShaderTexture FrameBuffer::GetTexture() const
  150. {
  151. ShaderTexture ret;
  152. #if defined USE_D3D9 || defined _XBOX
  153. ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
  154. #else
  155. ret.m_flags = m_data->m_texture;
  156. #endif
  157. return ret;
  158. }
  159. void FrameBuffer::Bind()
  160. {
  161. #if defined USE_D3D9 || defined _XBOX
  162. if (FAILED(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface)))
  163. Abort();
  164. if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_surface)))
  165. Abort();
  166. #else
  167. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  168. glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo);
  169. # else
  170. glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo);
  171. # endif
  172. #endif
  173. }
  174. void FrameBuffer::Unbind()
  175. {
  176. #if defined USE_D3D9
  177. if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
  178. Abort();
  179. m_data->m_back_surface->Release();
  180. #elif defined _XBOX
  181. if (FAILED(g_d3ddevice->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr,
  182. m_data->m_texture, nullptr, 0, 0, nullptr,
  183. 0, 0, nullptr)))
  184. Abort();
  185. if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
  186. Abort();
  187. m_data->m_back_surface->Release();
  188. #else
  189. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  190. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  191. # else
  192. glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
  193. # endif
  194. #endif
  195. }
  196. } /* namespace lol */