732 rader
19 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 <cstdlib>
  14. #if defined _XBOX
  15. # include <xtl.h>
  16. # undef near /* Fuck Microsoft */
  17. # undef far /* Fuck Microsoft again */
  18. #elif defined _WIN32
  19. # if defined USE_D3D9
  20. # include <d3d9.h>
  21. # endif
  22. # define WIN32_LEAN_AND_MEAN
  23. # include <windows.h>
  24. # undef near /* Fuck Microsoft */
  25. # undef far /* Fuck Microsoft again */
  26. #endif
  27. #include "core.h"
  28. #include "lolgl.h"
  29. /* FIXME: find a way to pass g_hwnd from the windowing system */
  30. #if defined USE_D3D9
  31. extern HWND g_hwnd;
  32. #elif defined _XBOX
  33. HWND g_hwnd = 0;
  34. #endif
  35. namespace lol
  36. {
  37. /*
  38. * The global g_renderer object, initialised by Video::Init
  39. */
  40. Renderer *g_renderer = nullptr;
  41. /*
  42. * Private RendererData class
  43. */
  44. class RendererData
  45. {
  46. friend class Renderer;
  47. private:
  48. ibox2 m_viewport;
  49. vec4 m_clear_color;
  50. float m_clear_depth;
  51. AlphaFunc m_alpha_func;
  52. float m_alpha_value;
  53. BlendFunc m_blend_src, m_blend_dst;
  54. DepthFunc m_depth_func;
  55. DepthMask m_depth_mask;
  56. CullMode m_cull_mode;
  57. PolygonMode m_polygon_mode;
  58. private:
  59. #if defined USE_D3D9
  60. IDirect3D9 *m_d3d_ctx;
  61. IDirect3DDevice9 *m_d3d_dev;
  62. #elif defined _XBOX
  63. Direct3D *m_d3d_ctx;
  64. D3DDevice *m_d3d_dev;
  65. #endif
  66. };
  67. /*
  68. * Public Renderer class
  69. */
  70. Renderer::Renderer(ivec2 size)
  71. : m_data(new RendererData())
  72. {
  73. #if defined USE_D3D9 || defined _XBOX
  74. /* Create Direct3D context */
  75. m_data->m_d3d_ctx = Direct3DCreate9(D3D_SDK_VERSION);
  76. if (!m_data->m_d3d_ctx)
  77. {
  78. Log::Error("cannot initialise D3D\n");
  79. exit(EXIT_FAILURE);
  80. }
  81. /* Create Direct3D device */
  82. # if defined _XBOX
  83. XVIDEO_MODE VideoMode;
  84. XGetVideoMode(&VideoMode);
  85. size = lol::min(size, ivec2(VideoMode.dwDisplayWidth,
  86. VideoMode.dwDisplayHeight));
  87. # endif
  88. D3DPRESENT_PARAMETERS d3dpp;
  89. memset(&d3dpp, 0, sizeof(d3dpp));
  90. d3dpp.BackBufferWidth = size.x;
  91. d3dpp.BackBufferHeight = size.y;
  92. d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
  93. d3dpp.BackBufferCount = 1;
  94. d3dpp.hDeviceWindow = g_hwnd;
  95. # if defined USE_SDL
  96. d3dpp.Windowed = TRUE;
  97. # endif
  98. d3dpp.EnableAutoDepthStencil = TRUE;
  99. d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
  100. d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  101. d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  102. HRESULT hr = m_data->m_d3d_ctx->CreateDevice(0, D3DDEVTYPE_HAL, g_hwnd,
  103. D3DCREATE_HARDWARE_VERTEXPROCESSING,
  104. &d3dpp, &m_data->m_d3d_dev);
  105. if (FAILED(hr))
  106. {
  107. Log::Error("cannot create D3D device\n");
  108. exit(EXIT_FAILURE);
  109. }
  110. #else
  111. # if defined USE_GLEW && !defined __APPLE__
  112. /* Initialise GLEW if necessary */
  113. GLenum glerr = glewInit();
  114. if (glerr != GLEW_OK)
  115. {
  116. Log::Error("cannot initialise GLEW: %s\n", glewGetErrorString(glerr));
  117. exit(EXIT_FAILURE);
  118. }
  119. # endif
  120. #endif
  121. /* Initialise rendering states */
  122. m_data->m_viewport = ibox2(0, 0, 0, 0);
  123. SetViewport(ibox2(vec2(0), size));
  124. m_data->m_clear_color = vec4(-1.f);
  125. SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f));
  126. m_data->m_clear_depth = -1.f;
  127. SetClearDepth(1.f);
  128. m_data->m_alpha_func = AlphaFunc::Never;
  129. m_data->m_alpha_value = -1.0f;
  130. SetAlphaFunc(AlphaFunc::Disabled, 0.0f);
  131. m_data->m_blend_src = BlendFunc::Disabled;
  132. m_data->m_blend_dst = BlendFunc::Disabled;
  133. SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
  134. m_data->m_depth_func = DepthFunc::Disabled;
  135. SetDepthFunc(DepthFunc::LessOrEqual);
  136. m_data->m_depth_mask = DepthMask::Disabled;
  137. SetDepthMask(DepthMask::Enabled);
  138. m_data->m_cull_mode = CullMode::Disabled;
  139. SetCullMode(CullMode::Clockwise);
  140. m_data->m_polygon_mode = PolygonMode::Point;
  141. SetPolygonMode(PolygonMode::Fill);
  142. /* Add some rendering states that we don't export to the user */
  143. #if defined USE_D3D9 || defined _XBOX
  144. /* TODO */
  145. #else
  146. # if defined HAVE_GL_2X && !defined __APPLE__
  147. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  148. # endif
  149. #endif
  150. }
  151. Renderer::~Renderer()
  152. {
  153. delete m_data;
  154. }
  155. void *Renderer::GetDevice()
  156. {
  157. #if defined USE_D3D9 || defined _XBOX
  158. return m_data->m_d3d_dev;
  159. #else
  160. return nullptr;
  161. #endif
  162. }
  163. /*
  164. * Buffer clearing
  165. */
  166. void Renderer::Clear(ClearMask mask)
  167. {
  168. #if defined USE_D3D9 || defined _XBOX
  169. int m = 0;
  170. if (mask & ClearMask::Color)
  171. m |= D3DCLEAR_TARGET;
  172. if (mask & ClearMask::Depth)
  173. m |= D3DCLEAR_ZBUFFER;
  174. if (mask & ClearMask::Stencil)
  175. m |= D3DCLEAR_STENCIL;
  176. vec3 tmp = 255.999f * GetClearColor().rgb;
  177. D3DCOLOR clear_color = D3DCOLOR_XRGB((int)tmp.r, (int)tmp.g, (int)tmp.b);
  178. if (FAILED(m_data->m_d3d_dev->Clear(0, nullptr, m, clear_color,
  179. GetClearDepth(), 0)))
  180. Abort();
  181. #else
  182. GLbitfield m = 0;
  183. if (mask & ClearMask::Color)
  184. m |= GL_COLOR_BUFFER_BIT;
  185. if (mask & ClearMask::Depth)
  186. m |= GL_DEPTH_BUFFER_BIT;
  187. if (mask & ClearMask::Stencil)
  188. m |= GL_STENCIL_BUFFER_BIT;
  189. glClear(m);
  190. #endif
  191. }
  192. /*
  193. * Viewport dimensions
  194. */
  195. void Renderer::SetViewport(ibox2 viewport)
  196. {
  197. if (m_data->m_viewport == viewport)
  198. return;
  199. #if defined USE_D3D9 || defined _XBOX
  200. D3DVIEWPORT9 vp = { viewport.A.x, viewport.A.y,
  201. viewport.B.x, viewport.B.y,
  202. 0.0f, 1.0f };
  203. m_data->m_d3d_dev->SetViewport(&vp);
  204. #else
  205. glViewport(viewport.A.x, viewport.A.y, viewport.B.x, viewport.B.y);
  206. #endif
  207. m_data->m_viewport = viewport;
  208. }
  209. ibox2 Renderer::GetViewport() const
  210. {
  211. return m_data->m_viewport;
  212. }
  213. /*
  214. * Clear color
  215. */
  216. void Renderer::SetClearColor(vec4 color)
  217. {
  218. if (m_data->m_clear_color == color)
  219. return;
  220. #if defined USE_D3D9 || defined _XBOX
  221. /* Nothing to do */
  222. #else
  223. glClearColor(color.r, color.g, color.b, color.a);
  224. #endif
  225. m_data->m_clear_color = color;
  226. }
  227. vec4 Renderer::GetClearColor() const
  228. {
  229. return m_data->m_clear_color;
  230. }
  231. /*
  232. * Clear depth
  233. */
  234. void Renderer::SetClearDepth(float depth)
  235. {
  236. if (m_data->m_clear_depth == depth)
  237. return;
  238. #if defined USE_D3D9 || defined _XBOX
  239. /* Nothing to do */
  240. #elif defined HAVE_GLES_2X
  241. glClearDepthf(depth);
  242. #else
  243. glClearDepth(depth);
  244. #endif
  245. m_data->m_clear_depth = depth;
  246. }
  247. float Renderer::GetClearDepth() const
  248. {
  249. return m_data->m_clear_depth;
  250. }
  251. /*
  252. * Alpha testing
  253. */
  254. void Renderer::SetAlphaFunc(AlphaFunc func, float alpha)
  255. {
  256. if (m_data->m_alpha_func == func && m_data->m_alpha_value == alpha)
  257. return;
  258. #if defined USE_D3D9 || defined _XBOX
  259. switch (func)
  260. {
  261. case AlphaFunc::Disabled:
  262. break; /* Nothing to do */
  263. case AlphaFunc::Never:
  264. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NEVER);
  265. break;
  266. case AlphaFunc::Less:
  267. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);
  268. break;
  269. case AlphaFunc::Equal:
  270. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_EQUAL);
  271. break;
  272. case AlphaFunc::LessOrEqual:
  273. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESSEQUAL);
  274. break;
  275. case AlphaFunc::Greater:
  276. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
  277. break;
  278. case AlphaFunc::NotEqual:
  279. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
  280. break;
  281. case AlphaFunc::GreaterOrEqual:
  282. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
  283. break;
  284. case AlphaFunc::Always:
  285. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
  286. break;
  287. }
  288. if (func == AlphaFunc::Disabled)
  289. {
  290. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  291. }
  292. else
  293. {
  294. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
  295. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAREF,
  296. (DWORD)(alpha * 255.999f));
  297. }
  298. #elif defined GL_VERSION_1_1
  299. switch (func)
  300. {
  301. case AlphaFunc::Disabled:
  302. break; /* Nothing to do */
  303. case AlphaFunc::Never:
  304. glAlphaFunc(GL_NEVER, alpha); break;
  305. case AlphaFunc::Less:
  306. glAlphaFunc(GL_LESS, alpha); break;
  307. case AlphaFunc::Equal:
  308. glAlphaFunc(GL_EQUAL, alpha); break;
  309. case AlphaFunc::LessOrEqual:
  310. glAlphaFunc(GL_LEQUAL, alpha); break;
  311. case AlphaFunc::Greater:
  312. glAlphaFunc(GL_GREATER, alpha); break;
  313. case AlphaFunc::NotEqual:
  314. glAlphaFunc(GL_NOTEQUAL, alpha); break;
  315. case AlphaFunc::GreaterOrEqual:
  316. glAlphaFunc(GL_GEQUAL, alpha); break;
  317. case AlphaFunc::Always:
  318. glAlphaFunc(GL_ALWAYS, alpha); break;
  319. }
  320. if (func == AlphaFunc::Disabled)
  321. glDisable(GL_ALPHA_TEST);
  322. else
  323. glEnable(GL_ALPHA_TEST);
  324. #else
  325. /* XXX: alpha test not available in GL ES and deprecated anyway. */
  326. #endif
  327. m_data->m_alpha_func = func;
  328. m_data->m_alpha_value = alpha;
  329. }
  330. AlphaFunc Renderer::GetAlphaFunc() const
  331. {
  332. return m_data->m_alpha_func;
  333. }
  334. float Renderer::GetAlphaValue() const
  335. {
  336. return m_data->m_alpha_value;
  337. }
  338. /*
  339. * Blend function
  340. */
  341. void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst)
  342. {
  343. if (m_data->m_blend_src == src && m_data->m_blend_dst == dst)
  344. return;
  345. #if defined USE_D3D9 || defined _XBOX
  346. D3DBLEND s1[2] = { D3DBLEND_ONE, D3DBLEND_ZERO };
  347. BlendFunc s2[2] = { src, dst };
  348. for (int i = 0; i < 2; ++i)
  349. {
  350. switch (s2[i])
  351. {
  352. case BlendFunc::Disabled:
  353. break; /* Nothing to do */
  354. case BlendFunc::Zero:
  355. s1[i] = D3DBLEND_ZERO; break;
  356. case BlendFunc::One:
  357. s1[i] = D3DBLEND_ONE; break;
  358. case BlendFunc::SrcColor:
  359. s1[i] = D3DBLEND_SRCCOLOR; break;
  360. case BlendFunc::OneMinusSrcColor:
  361. s1[i] = D3DBLEND_INVSRCCOLOR; break;
  362. case BlendFunc::DstColor:
  363. s1[i] = D3DBLEND_DESTCOLOR; break;
  364. case BlendFunc::OneMinusDstColor:
  365. s1[i] = D3DBLEND_INVDESTCOLOR; break;
  366. case BlendFunc::SrcAlpha:
  367. s1[i] = D3DBLEND_SRCALPHA; break;
  368. case BlendFunc::OneMinusSrcAlpha:
  369. s1[i] = D3DBLEND_INVSRCALPHA; break;
  370. case BlendFunc::DstAlpha:
  371. s1[i] = D3DBLEND_DESTALPHA; break;
  372. case BlendFunc::OneMinusDstAlpha:
  373. s1[i] = D3DBLEND_INVDESTALPHA; break;
  374. /* FiXME: these can be supported using D3DPBLENDCAPS_BLENDFACTOR */
  375. case BlendFunc::ConstantColor:
  376. ASSERT(0, "BlendFunc::ConstantColor not supported");
  377. break;
  378. case BlendFunc::OneMinusConstantColor:
  379. ASSERT(0, "BlendFunc::OneMinusConstantColor not supported");
  380. break;
  381. case BlendFunc::ConstantAlpha:
  382. ASSERT(0, "BlendFunc::ConstantAlpha not supported");
  383. break;
  384. case BlendFunc::OneMinusConstantAlpha:
  385. ASSERT(0, "BlendFunc::OneMinusConstantAlpha not supported");
  386. break;
  387. }
  388. }
  389. if (src == BlendFunc::Disabled)
  390. {
  391. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
  392. }
  393. else
  394. {
  395. m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  396. m_data->m_d3d_dev->SetRenderState(D3DRS_SRCBLEND, s1[0]);
  397. m_data->m_d3d_dev->SetRenderState(D3DRS_DESTBLEND, s1[1]);
  398. }
  399. #else
  400. GLenum s1[2] = { GL_ONE, GL_ZERO };
  401. BlendFunc s2[2] = { src, dst };
  402. for (int i = 0; i < 2; ++i)
  403. {
  404. switch (s2[i])
  405. {
  406. case BlendFunc::Disabled:
  407. break; /* Nothing to do */
  408. case BlendFunc::Zero:
  409. s1[i] = GL_ZERO; break;
  410. case BlendFunc::One:
  411. s1[i] = GL_ONE; break;
  412. case BlendFunc::SrcColor:
  413. s1[i] = GL_SRC_COLOR; break;
  414. case BlendFunc::OneMinusSrcColor:
  415. s1[i] = GL_ONE_MINUS_SRC_COLOR; break;
  416. case BlendFunc::DstColor:
  417. s1[i] = GL_DST_COLOR; break;
  418. case BlendFunc::OneMinusDstColor:
  419. s1[i] = GL_ONE_MINUS_DST_COLOR; break;
  420. case BlendFunc::SrcAlpha:
  421. s1[i] = GL_SRC_ALPHA; break;
  422. case BlendFunc::OneMinusSrcAlpha:
  423. s1[i] = GL_ONE_MINUS_SRC_ALPHA; break;
  424. case BlendFunc::DstAlpha:
  425. s1[i] = GL_DST_ALPHA; break;
  426. case BlendFunc::OneMinusDstAlpha:
  427. s1[i] = GL_ONE_MINUS_DST_ALPHA; break;
  428. case BlendFunc::ConstantColor:
  429. s1[i] = GL_CONSTANT_COLOR; break;
  430. case BlendFunc::OneMinusConstantColor:
  431. s1[i] = GL_ONE_MINUS_CONSTANT_COLOR; break;
  432. case BlendFunc::ConstantAlpha:
  433. s1[i] = GL_CONSTANT_ALPHA; break;
  434. case BlendFunc::OneMinusConstantAlpha:
  435. s1[i] = GL_ONE_MINUS_CONSTANT_ALPHA; break;
  436. }
  437. }
  438. if (src == BlendFunc::Disabled)
  439. {
  440. glDisable(GL_BLEND);
  441. }
  442. else
  443. {
  444. glEnable(GL_BLEND);
  445. glBlendFunc(s1[0], s1[1]);
  446. }
  447. #endif
  448. m_data->m_blend_src = src;
  449. m_data->m_blend_dst = dst;
  450. }
  451. BlendFunc Renderer::GetBlendFuncSrc() const
  452. {
  453. return m_data->m_blend_src;
  454. }
  455. BlendFunc Renderer::GetBlendFuncDst() const
  456. {
  457. return m_data->m_blend_dst;
  458. }
  459. /*
  460. * Depth test
  461. */
  462. void Renderer::SetDepthFunc(DepthFunc func)
  463. {
  464. if (m_data->m_depth_func == func)
  465. return;
  466. #if defined USE_D3D9 || defined _XBOX
  467. switch (func)
  468. {
  469. case DepthFunc::Disabled:
  470. break; /* Nothing to do */
  471. case DepthFunc::Never:
  472. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_NEVER);
  473. break;
  474. case DepthFunc::Less:
  475. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
  476. break;
  477. case DepthFunc::Equal:
  478. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
  479. break;
  480. case DepthFunc::LessOrEqual:
  481. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  482. break;
  483. case DepthFunc::Greater:
  484. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER);
  485. break;
  486. case DepthFunc::NotEqual:
  487. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL);
  488. break;
  489. case DepthFunc::GreaterOrEqual:
  490. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
  491. break;
  492. case DepthFunc::Always:
  493. m_data->m_d3d_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  494. break;
  495. }
  496. if (func == DepthFunc::Disabled)
  497. m_data->m_d3d_dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
  498. else
  499. m_data->m_d3d_dev->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
  500. #else
  501. switch (func)
  502. {
  503. case DepthFunc::Disabled:
  504. break; /* Nothing to do */
  505. case DepthFunc::Never:
  506. glDepthFunc(GL_NEVER); break;
  507. case DepthFunc::Less:
  508. glDepthFunc(GL_LESS); break;
  509. case DepthFunc::Equal:
  510. glDepthFunc(GL_EQUAL); break;
  511. case DepthFunc::LessOrEqual:
  512. glDepthFunc(GL_LEQUAL); break;
  513. case DepthFunc::Greater:
  514. glDepthFunc(GL_GREATER); break;
  515. case DepthFunc::NotEqual:
  516. glDepthFunc(GL_NOTEQUAL); break;
  517. case DepthFunc::GreaterOrEqual:
  518. glDepthFunc(GL_GEQUAL); break;
  519. case DepthFunc::Always:
  520. glDepthFunc(GL_ALWAYS); break;
  521. }
  522. if (func == DepthFunc::Disabled)
  523. glDisable(GL_DEPTH_TEST);
  524. else
  525. glEnable(GL_DEPTH_TEST);
  526. #endif
  527. m_data->m_depth_func = func;
  528. }
  529. DepthFunc Renderer::GetDepthFunc() const
  530. {
  531. return m_data->m_depth_func;
  532. }
  533. /*
  534. * Depth mask
  535. */
  536. void Renderer::SetDepthMask(DepthMask mask)
  537. {
  538. if (m_data->m_depth_mask == mask)
  539. return;
  540. #if defined USE_D3D9 || defined _XBOX
  541. if (mask == DepthMask::Disabled)
  542. m_data->m_d3d_dev->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
  543. else
  544. m_data->m_d3d_dev->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE);
  545. #else
  546. if (mask == DepthMask::Disabled)
  547. glDepthMask(GL_FALSE);
  548. else
  549. glDepthMask(GL_TRUE);
  550. #endif
  551. m_data->m_depth_mask = mask;
  552. }
  553. DepthMask Renderer::GetDepthMask() const
  554. {
  555. return m_data->m_depth_mask;
  556. }
  557. /*
  558. * Face culling
  559. */
  560. void Renderer::SetCullMode(CullMode mode)
  561. {
  562. if (m_data->m_cull_mode == mode)
  563. return;
  564. #if defined USE_D3D9 || defined _XBOX
  565. switch (mode)
  566. {
  567. case CullMode::Disabled:
  568. m_data->m_d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  569. break;
  570. case CullMode::Clockwise:
  571. m_data->m_d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
  572. break;
  573. case CullMode::CounterClockwise:
  574. m_data->m_d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  575. break;
  576. }
  577. #else
  578. switch (mode)
  579. {
  580. case CullMode::Disabled:
  581. glDisable(GL_CULL_FACE);
  582. break;
  583. case CullMode::Clockwise:
  584. glEnable(GL_CULL_FACE);
  585. glCullFace(GL_FRONT);
  586. glFrontFace(GL_CW);
  587. break;
  588. case CullMode::CounterClockwise:
  589. glEnable(GL_CULL_FACE);
  590. glCullFace(GL_FRONT);
  591. glFrontFace(GL_CCW);
  592. break;
  593. }
  594. #endif
  595. m_data->m_cull_mode = mode;
  596. }
  597. CullMode Renderer::GetCullMode() const
  598. {
  599. return m_data->m_cull_mode;
  600. }
  601. /*
  602. * Polygon rendering mode
  603. */
  604. void Renderer::SetPolygonMode(PolygonMode mode)
  605. {
  606. if (m_data->m_polygon_mode == mode)
  607. return;
  608. #if defined USE_D3D9 || defined _XBOX
  609. switch (mode)
  610. {
  611. case PolygonMode::Point:
  612. m_data->m_d3d_dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT);
  613. break;
  614. case PolygonMode::Line:
  615. m_data->m_d3d_dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
  616. break;
  617. case PolygonMode::Fill:
  618. m_data->m_d3d_dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  619. break;
  620. }
  621. #elif defined __CELLOS_LV2__ || defined GL_VERSION_1_1
  622. switch (mode)
  623. {
  624. case PolygonMode::Point:
  625. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  626. break;
  627. case PolygonMode::Line:
  628. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  629. break;
  630. case PolygonMode::Fill:
  631. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  632. break;
  633. }
  634. #endif
  635. m_data->m_polygon_mode = mode;
  636. }
  637. PolygonMode Renderer::GetPolygonMode() const
  638. {
  639. return m_data->m_polygon_mode;
  640. }
  641. } /* namespace lol */