526 rader
15 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 FramebufferFormat struct
  48. // ----------------------
  49. //
  50. uint32_t FramebufferFormat::GetFormat()
  51. {
  52. switch (m_format)
  53. {
  54. #if defined USE_D3D9 || defined _XBOX
  55. case R_16_F: return D3DFMT_R16F;
  56. case R_32_F: return D3DFMT_R32F;
  57. case RG_16:
  58. case RG_16_I:
  59. case RG_16_UI: return D3DFMT_G16R16;
  60. case RG_16_F: return D3DFMT_G16R16F;
  61. case RG_32_F: return D3DFMT_G32R32F;
  62. case RGB_8:
  63. case RGB_8_I:
  64. case RGB_8_UI: return D3DFMT_R8G8B8;
  65. case RGBA_8:
  66. case RGBA_8_I:
  67. case RGBA_8_UI: return D3DFMT_A8R8G8B8;
  68. case RGBA_16:
  69. case RGBA_16_I:
  70. case RGBA_16_UI: return D3DFMT_A16B16G16R16;
  71. case RGBA_16_F: return D3DFMT_A16B16G16R16F;
  72. case RGBA_32_F: return D3DFMT_A32B32G32R32F;
  73. default: ASSERT(false, "not supported by DirectX");
  74. return 0;
  75. #elif defined __CELLOS_LV2__
  76. /* Supported drawable formats on the PS3: GL_ARGB_SCE, GL_RGB16F_ARB,
  77. * GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB. */
  78. case RGB_16_F: return GL_RGB16F_ARB;
  79. case RGB_32_F: return GL_RGB32F_ARB;
  80. case RGBA_8: return GL_ARGB_SCE;
  81. case RGBA_16_F: return GL_RGBA16F_ARB;
  82. case RGBA_32_F: return GL_RGBA32F_ARB;
  83. default: ASSERT(false, "not supported by the PS3");
  84. return 0;
  85. #elif defined HAVE_GLES_2X
  86. /* FIXME: not implemented at all */
  87. default: ASSERT(false, "not implemented");
  88. return 0;
  89. #elif defined __APPLE__ && defined __MACH__
  90. case R_8:
  91. case RG_8:
  92. case RGB_8:
  93. case RGBA_8:
  94. case R_8_I:
  95. case RG_8_I:
  96. case RGB_8_I:
  97. case RGBA_8_I: return GL_BYTE;
  98. case R_8_UI:
  99. case RG_8_UI:
  100. case RGB_8_UI:
  101. case RGBA_8_UI: return GL_UNSIGNED_BYTE;
  102. case R_16:
  103. case RG_16:
  104. case RGB_16:
  105. case RGBA_16:
  106. case R_16_I:
  107. case RG_16_I:
  108. case RGB_16_I:
  109. case RGBA_16_I: return GL_SHORT;
  110. case R_16_UI:
  111. case RG_16_UI:
  112. case RGB_16_UI:
  113. case RGBA_16_UI: return GL_UNSIGNED_SHORT;
  114. case R_16_F:
  115. case RG_16_F:
  116. case RGB_16_F:
  117. case RGBA_16_F: ASSERT(false, "not supported by IOS:OGL:ES");
  118. return 0;
  119. case R_32_I:
  120. case RG_32_I:
  121. case RGB_32_I:
  122. case RGBA_32_I: return GL_INT;
  123. case R_32_UI:
  124. case RG_32_UI:
  125. case RGB_32_UI:
  126. case RGBA_32_UI: return GL_UNSIGNED_INT;
  127. case R_32_F:
  128. case RG_32_F:
  129. case RGB_32_F:
  130. case RGBA_32_F: return GL_FLOAT;
  131. #else
  132. case R_8: return GL_R8;
  133. case R_8_I: return GL_R8I;
  134. case R_8_UI: return GL_R8UI;
  135. case R_16: return GL_R16;
  136. case R_16_I: return GL_R16I;
  137. case R_16_UI: return GL_R16UI;
  138. case R_16_F: return GL_R16F;
  139. case R_32_I: return GL_R32I;
  140. case R_32_UI: return GL_R32UI;
  141. case R_32_F: return GL_R32F;
  142. case RG_8: return GL_RG8;
  143. case RG_8_I: return GL_RG8I;
  144. case RG_8_UI: return GL_RG8UI;
  145. case RG_16: return GL_RG16;
  146. case RG_16_I: return GL_RG16I;
  147. case RG_16_UI: return GL_RG16UI;
  148. case RG_16_F: return GL_RG16F;
  149. case RG_32_I: return GL_RG32I;
  150. case RG_32_UI: return GL_RG32UI;
  151. case RG_32_F: return GL_RG32F;
  152. case RGB_8: return GL_RGB8;
  153. case RGB_8_I: return GL_RGB8I;
  154. case RGB_8_UI: return GL_RGB8UI;
  155. case RGB_16: return GL_RGB16;
  156. case RGB_16_I: return GL_RGB16I;
  157. case RGB_16_UI: return GL_RGB16UI;
  158. case RGB_16_F: return GL_RGB16F;
  159. case RGB_32_I: return GL_RGB32I;
  160. case RGB_32_UI: return GL_RGB32UI;
  161. case RGB_32_F: return GL_RGB32F;
  162. case RGBA_8: return GL_RGBA8;
  163. case RGBA_8_I: return GL_RGBA8I;
  164. case RGBA_8_UI: return GL_RGBA8UI;
  165. case RGBA_16: return GL_RGBA16;
  166. case RGBA_16_I: return GL_RGBA16I;
  167. case RGBA_16_UI: return GL_RGBA16UI;
  168. case RGBA_16_F: return GL_RGBA16F;
  169. case RGBA_32_I: return GL_RGBA32I;
  170. case RGBA_32_UI: return GL_RGBA32UI;
  171. case RGBA_32_F: return GL_RGBA32F;
  172. default: ASSERT(false, "not supported by OpenGL");
  173. return 0;
  174. #endif
  175. };
  176. ASSERT(false, "not implemented");
  177. return 0;
  178. }
  179. uint32_t FramebufferFormat::GetFormatOrder()
  180. {
  181. switch (m_format)
  182. {
  183. #if defined USE_D3D9 || defined _XBOX
  184. /* FIXME: not implemented at all */
  185. default: ASSERT(false, "not implemented");
  186. return 0;
  187. #elif defined __CELLOS_LV2__
  188. /* FIXME: not implemented at all */
  189. default: ASSERT(false, "not implemented");
  190. return 0;
  191. #elif defined HAVE_GLES_2X
  192. /* FIXME: not implemented at all */
  193. default: ASSERT(false, "not implemented");
  194. return 0;
  195. #elif defined __APPLE__ && defined __MACH__
  196. case R_8:
  197. case R_8_I:
  198. case R_8_UI:
  199. case R_8_F:
  200. case R_16:
  201. case R_16_I:
  202. case R_16_UI:
  203. case R_16_F:
  204. case R_32_I:
  205. case R_32:
  206. case R_32_UI:
  207. case R_32_F:
  208. case RG_8:
  209. case RG_8_I:
  210. case RG_8_UI:
  211. case RG_8_F:
  212. case RG_16:
  213. case RG_16_I:
  214. case RG_16_UI:
  215. case RG_16_F:
  216. case RG_32:
  217. case RG_32_I:
  218. case RG_32_UI:
  219. case RG_32_F:
  220. case RGB_8:
  221. case RGB_8_I:
  222. case RGB_8_UI:
  223. case RGB_8_F:
  224. case RGB_16:
  225. case RGB_16_I:
  226. case RGB_16_UI:
  227. case RGB_16_F:
  228. case RGB_32:
  229. case RGB_32_I:
  230. case RGB_32_UI:
  231. case RGB_32_F:
  232. case RGBA_8:
  233. case RGBA_8_I:
  234. case RGBA_8_UI:
  235. case RGBA_8_F:
  236. case RGBA_16:
  237. case RGBA_16_I:
  238. case RGBA_16_UI:
  239. case RGBA_16_F:
  240. case RGBA_32:
  241. case RGBA_32_I:
  242. case RGBA_32_UI:
  243. case RGBA_32_F:
  244. #else
  245. case R_8:
  246. case R_8_I:
  247. case R_8_UI:
  248. case R_8_F:
  249. case R_16:
  250. case R_16_I:
  251. case R_16_UI:
  252. case R_16_F:
  253. case R_32_I:
  254. case R_32:
  255. case R_32_UI:
  256. case R_32_F: return GL_RED;
  257. case RG_8:
  258. case RG_8_I:
  259. case RG_8_UI:
  260. case RG_8_F:
  261. case RG_16:
  262. case RG_16_I:
  263. case RG_16_UI:
  264. case RG_16_F:
  265. case RG_32:
  266. case RG_32_I:
  267. case RG_32_UI:
  268. case RG_32_F: return GL_RG;
  269. case RGB_8:
  270. case RGB_8_I:
  271. case RGB_8_UI:
  272. case RGB_8_F:
  273. case RGB_16:
  274. case RGB_16_I:
  275. case RGB_16_UI:
  276. case RGB_16_F:
  277. case RGB_32:
  278. case RGB_32_I:
  279. case RGB_32_UI:
  280. case RGB_32_F: return (m_invert_rgb)?(GL_BGR):(GL_RGB);
  281. case RGBA_8:
  282. case RGBA_8_I:
  283. case RGBA_8_UI:
  284. case RGBA_8_F:
  285. case RGBA_16:
  286. case RGBA_16_I:
  287. case RGBA_16_UI:
  288. case RGBA_16_F:
  289. case RGBA_32:
  290. case RGBA_32_I:
  291. case RGBA_32_UI:
  292. case RGBA_32_F: return (m_invert_rgb)?(GL_BGRA):(GL_RGBA);
  293. #endif
  294. }
  295. ASSERT(false, "unknown pixel format");
  296. return 0;
  297. }
  298. //
  299. // The Framebuffer class
  300. // ----------------------
  301. //
  302. Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format)
  303. : m_data(new FramebufferData)
  304. {
  305. m_data->m_size = size;
  306. #if defined USE_D3D9
  307. if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1,
  308. D3DUSAGE_RENDERTARGET,
  309. fbo_format.GetFormat(), D3DPOOL_DEFAULT,
  310. &m_data->m_texture, nullptr)))
  311. Abort();
  312. if (FAILED(m_data->m_texture->GetSurfaceLevel(0, &m_data->m_surface)))
  313. Abort();
  314. #elif defined _XBOX
  315. if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, 0,
  316. fbo_format.GetFormat(), D3DPOOL_DEFAULT,
  317. &m_data->m_texture, nullptr)))
  318. Abort();
  319. if (FAILED(g_d3ddevice->CreateRenderTarget(size.x, size.y,
  320. fbo_format.GetFormat(),
  321. D3DMULTISAMPLE_NONE, 0, 0,
  322. &m_data->m_surface, nullptr)))
  323. Abort();
  324. #else
  325. # if GL_VERSION_1_1
  326. GLenum internal_format = fbo_format.GetFormat();
  327. GLenum format = fbo_format.GetFormatOrder();
  328. GLenum depth = GL_DEPTH_COMPONENT;
  329. # elif defined __CELLOS_LV2__
  330. /* Supported drawable formats on the PS3: GL_ARGB_SCE, GL_RGB16F_ARB,
  331. * GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB. */
  332. GLenum internal_format = fbo_format.GetFormat();
  333. GLenum format = fbo_format.GetFormatOrder();
  334. # else
  335. GLenum internal_format = fbo_format.GetFormat();
  336. GLenum format = fbo_format.GetFormatOrder();
  337. # endif
  338. GLenum wrapmode = GL_REPEAT;
  339. GLenum filtering = GL_NEAREST;
  340. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  341. glGenFramebuffers(1, &m_data->m_fbo);
  342. glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo);
  343. # else
  344. glGenFramebuffersOES(1, &m_data->m_fbo);
  345. glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo);
  346. # endif
  347. glGenTextures(1, &m_data->m_texture);
  348. glActiveTexture(GL_TEXTURE0);
  349. glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
  350. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLenum)wrapmode);
  351. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLenum)wrapmode);
  352. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLenum)filtering);
  353. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLenum)filtering);
  354. glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size.x, size.y, 0,
  355. format, GL_UNSIGNED_BYTE, nullptr);
  356. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  357. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  358. GL_TEXTURE_2D, m_data->m_texture, 0);
  359. # else
  360. glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT,
  361. GL_TEXTURE_2D, m_data->m_texture, 0);
  362. # endif
  363. m_data->m_depth = GL_INVALID_ENUM;
  364. # if GL_VERSION_1_1
  365. /* FIXME: not implemented on GL ES, see
  366. * http://stackoverflow.com/q/4041682/111461 */
  367. if (depth != GL_INVALID_ENUM)
  368. {
  369. glGenRenderbuffers(1, &m_data->m_depth);
  370. glBindRenderbuffer(GL_RENDERBUFFER, m_data->m_depth);
  371. glRenderbufferStorage(GL_RENDERBUFFER, depth, size.x, size.y);
  372. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  373. GL_RENDERBUFFER, m_data->m_depth);
  374. }
  375. # endif
  376. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  377. glCheckFramebufferStatus(GL_FRAMEBUFFER);
  378. # endif
  379. Unbind();
  380. #endif
  381. }
  382. Framebuffer::~Framebuffer()
  383. {
  384. #if defined USE_D3D9 || defined _XBOX
  385. m_data->m_surface->Release();
  386. m_data->m_texture->Release();
  387. #else
  388. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  389. glDeleteFramebuffers(1, &m_data->m_fbo);
  390. # else
  391. glDeleteFramebuffersOES(1, &m_data->m_fbo);
  392. # endif
  393. glDeleteTextures(1, &m_data->m_texture);
  394. # if GL_VERSION_1_1
  395. if (m_data->m_depth != GL_INVALID_ENUM)
  396. glDeleteRenderbuffers(1, &m_data->m_depth);
  397. # endif
  398. #endif
  399. delete m_data;
  400. }
  401. ShaderTexture Framebuffer::GetTexture() const
  402. {
  403. ShaderTexture ret;
  404. #if defined USE_D3D9 || defined _XBOX
  405. ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
  406. #else
  407. ret.m_flags = m_data->m_texture;
  408. #endif
  409. return ret;
  410. }
  411. ivec2 Framebuffer::GetSize() const
  412. {
  413. return m_data->m_size;
  414. }
  415. void Framebuffer::Bind()
  416. {
  417. #if defined USE_D3D9 || defined _XBOX
  418. if (FAILED(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface)))
  419. Abort();
  420. if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_surface)))
  421. Abort();
  422. #else
  423. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  424. glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo);
  425. # else
  426. glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo);
  427. # endif
  428. //change viewport draw size
  429. Video::SetCustomSize(m_data->m_size);
  430. #endif
  431. }
  432. void Framebuffer::Unbind()
  433. {
  434. #if defined USE_D3D9
  435. if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
  436. Abort();
  437. m_data->m_back_surface->Release();
  438. #elif defined _XBOX
  439. if (FAILED(g_d3ddevice->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr,
  440. m_data->m_texture, nullptr, 0, 0, nullptr,
  441. 0, 0, nullptr)))
  442. Abort();
  443. if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
  444. Abort();
  445. m_data->m_back_surface->Release();
  446. #else
  447. //Restore viewport draw size
  448. Video::RestoreSize();
  449. # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
  450. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  451. # else
  452. glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
  453. # endif
  454. #endif
  455. }
  456. } /* namespace lol */