Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

892 wiersze
26 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 <cstring>
  14. #include <cstdio>
  15. #ifdef WIN32
  16. # define WIN32_LEAN_AND_MEAN
  17. # include <windows.h>
  18. # if defined USE_D3D9
  19. # include <algorithm>
  20. using std::min;
  21. using std::max;
  22. # include <d3d9.h>
  23. # include <d3dx9shader.h>
  24. # endif
  25. #endif
  26. #include "core.h"
  27. #include "lolgl.h"
  28. using namespace std;
  29. #if defined USE_D3D9
  30. extern IDirect3DDevice9 *g_d3ddevice;
  31. #elif defined _XBOX
  32. extern D3DDevice *g_d3ddevice;
  33. #endif
  34. namespace lol
  35. {
  36. /*
  37. * Shader implementation class
  38. */
  39. class ShaderData
  40. {
  41. friend class Shader;
  42. private:
  43. #if defined USE_D3D9
  44. IDirect3DVertexShader9 *vert_shader;
  45. IDirect3DPixelShader9 *frag_shader;
  46. ID3DXConstantTable *vert_table, *frag_table;
  47. #elif defined _XBOX
  48. D3DVertexShader *vert_shader;
  49. D3DPixelShader *frag_shader;
  50. ID3DXConstantTable *vert_table, *frag_table;
  51. #elif !defined __CELLOS_LV2__
  52. GLuint prog_id, vert_id, frag_id;
  53. #else
  54. CGprogram vert_id, frag_id;
  55. #endif
  56. uint32_t vert_crc, frag_crc;
  57. /* Shader patcher */
  58. static int GetVersion();
  59. static void Patch(char *dst, char const *vert, char const *frag);
  60. /* Global shader cache */
  61. static Shader *shaders[];
  62. static Hash<char const *> hash;
  63. static int nshaders;
  64. };
  65. Shader *ShaderData::shaders[256];
  66. Hash<char const *> ShaderData::hash;
  67. int ShaderData::nshaders = 0;
  68. /*
  69. * Public Shader class
  70. */
  71. Shader *Shader::Create(char const *lolfx)
  72. {
  73. char *src = new char[strlen(lolfx) + 2];
  74. memcpy(src + 1, lolfx, strlen(lolfx) + 1);
  75. src[0] = '\n';
  76. /* Parse the crap */
  77. Array<char const *, char const *> sections;
  78. char *key = NULL;
  79. for (char *parser = src; *parser; )
  80. {
  81. if (key == NULL && (parser[0] == '\n' || parser[0] == '\r')
  82. && parser[1] == '[')
  83. {
  84. *parser = '\0';
  85. parser += 2;
  86. key = parser;
  87. }
  88. else if (key && parser[0] == ']')
  89. {
  90. *parser++ = '\0';
  91. }
  92. else if (key && (parser[0] == '\n' || parser[0] == '\r'))
  93. {
  94. sections.Push(key, parser);
  95. parser++;
  96. key = NULL;
  97. }
  98. else
  99. {
  100. parser++;
  101. }
  102. }
  103. char const *vert = NULL, *frag = NULL;
  104. for (int i = 0; i < sections.Count(); i++)
  105. {
  106. #if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
  107. if (!strcmp(sections[i].m1, "vert.glsl"))
  108. vert = sections[i].m2;
  109. if (!strcmp(sections[i].m1, "frag.glsl"))
  110. frag = sections[i].m2;
  111. #else
  112. if (!strcmp(sections[i].m1, "vert.hlsl"))
  113. vert = sections[i].m2;
  114. if (!strcmp(sections[i].m1, "frag.hlsl"))
  115. frag = sections[i].m2;
  116. #endif
  117. }
  118. /* FIXME: we don’t know how to handle these yet. */
  119. if (!vert)
  120. Log::Error("no vertex shader found… sorry, I’m gonna crash now.\n");
  121. if (!frag)
  122. Log::Error("no fragment shader found… sorry, I’m gonna crash now.\n");
  123. uint32_t new_vert_crc = ShaderData::hash(vert);
  124. uint32_t new_frag_crc = ShaderData::hash(frag);
  125. for (int n = 0; n < ShaderData::nshaders; n++)
  126. {
  127. if (ShaderData::shaders[n]->data->vert_crc == new_vert_crc
  128. && ShaderData::shaders[n]->data->frag_crc == new_frag_crc)
  129. {
  130. delete[] src;
  131. return ShaderData::shaders[n];
  132. }
  133. }
  134. Shader *ret = new Shader(vert, frag);
  135. ShaderData::shaders[ShaderData::nshaders] = ret;
  136. ShaderData::nshaders++;
  137. delete[] src;
  138. return ret;
  139. }
  140. void Shader::Destroy(Shader *shader)
  141. {
  142. /* XXX: do nothing! the shader should remain in cache */
  143. (void)shader;
  144. }
  145. Shader::Shader(char const *vert, char const *frag)
  146. : data(new ShaderData())
  147. {
  148. #if defined USE_D3D9 || defined _XBOX
  149. ID3DXBuffer *shader_code, *error_msg;
  150. HRESULT hr;
  151. D3DXMACRO macros[] =
  152. {
  153. #if defined _XBOX
  154. { "_XBOX", "1" },
  155. #endif
  156. { NULL, NULL }
  157. };
  158. #elif !defined __CELLOS_LV2__
  159. char buf[4096], errbuf[4096];
  160. char const *shader = buf;
  161. GLint status;
  162. GLsizei len;
  163. #else
  164. /* Initialise the runtime shader compiler. FIXME: this needs only
  165. * to be done once. */
  166. cgRTCgcInit();
  167. #endif
  168. /* Compile vertex shader */
  169. data->vert_crc = ShaderData::hash(vert);
  170. #if defined USE_D3D9 || defined _XBOX
  171. hr = D3DXCompileShader(vert, (UINT)strlen(vert), macros, NULL, "main",
  172. "vs_3_0", 0, &shader_code, &error_msg,
  173. &data->vert_table);
  174. if (FAILED(hr))
  175. {
  176. Log::Error("failed to compile vertex shader: %s",
  177. error_msg ? error_msg->GetBufferPointer() : "error");
  178. Log::Error("shader source:\n%s\n", vert);
  179. }
  180. g_d3ddevice->CreateVertexShader((DWORD *)shader_code->GetBufferPointer(),
  181. &data->vert_shader);
  182. shader_code->Release();
  183. #elif !defined __CELLOS_LV2__
  184. ShaderData::Patch(buf, vert, NULL);
  185. data->vert_id = glCreateShader(GL_VERTEX_SHADER);
  186. glShaderSource(data->vert_id, 1, &shader, NULL);
  187. glCompileShader(data->vert_id);
  188. glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf);
  189. glGetShaderiv(data->vert_id, GL_COMPILE_STATUS, &status);
  190. if (status != GL_TRUE)
  191. {
  192. Log::Error("failed to compile vertex shader: %s", errbuf);
  193. Log::Error("shader source:\n%s\n", buf);
  194. }
  195. else if (len > 16)
  196. {
  197. Log::Debug("compile log for vertex shader: %s", errbuf);
  198. Log::Debug("shader source:\n%s\n", buf);
  199. }
  200. #else
  201. data->vert_id = cgCreateProgram(cgCreateContext(), CG_SOURCE, vert,
  202. cgGLGetLatestProfile(CG_GL_VERTEX),
  203. NULL, NULL);
  204. if (data->vert_id == NULL)
  205. {
  206. Log::Error("failed to compile vertex shader");
  207. Log::Error("shader source:\n%s\n", vert);
  208. }
  209. #endif
  210. /* Compile fragment shader */
  211. data->frag_crc = ShaderData::hash(frag);
  212. #if defined USE_D3D9 || defined _XBOX
  213. hr = D3DXCompileShader(frag, (UINT)strlen(frag), macros, NULL, "main",
  214. "ps_3_0", 0, &shader_code, &error_msg,
  215. &data->frag_table);
  216. if (FAILED(hr))
  217. {
  218. Log::Error("failed to compile fragment shader: %s",
  219. error_msg ? error_msg->GetBufferPointer() : "error");
  220. Log::Error("shader source:\n%s\n", frag);
  221. }
  222. g_d3ddevice->CreatePixelShader((DWORD *)shader_code->GetBufferPointer(),
  223. &data->frag_shader);
  224. shader_code->Release();
  225. #elif !defined __CELLOS_LV2__
  226. ShaderData::Patch(buf, NULL, frag);
  227. data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
  228. glShaderSource(data->frag_id, 1, &shader, NULL);
  229. glCompileShader(data->frag_id);
  230. glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf);
  231. glGetShaderiv(data->frag_id, GL_COMPILE_STATUS, &status);
  232. if (status != GL_TRUE)
  233. {
  234. Log::Error("failed to compile fragment shader: %s", errbuf);
  235. Log::Error("shader source:\n%s\n", buf);
  236. }
  237. else if (len > 16)
  238. {
  239. Log::Debug("compile log for fragment shader: %s", errbuf);
  240. Log::Debug("shader source:\n%s\n", buf);
  241. }
  242. #else
  243. data->frag_id = cgCreateProgram(cgCreateContext(), CG_SOURCE, frag,
  244. cgGLGetLatestProfile(CG_GL_FRAGMENT),
  245. NULL, NULL);
  246. if (data->frag_id == NULL)
  247. {
  248. Log::Error("failed to compile fragment shader");
  249. Log::Error("shader source:\n%s\n", frag);
  250. }
  251. #endif
  252. #if defined USE_D3D9 || defined _XBOX
  253. /* FIXME: this is only debug code, we don't need it. */
  254. D3DXCONSTANTTABLE_DESC desc;
  255. data->frag_table->GetDesc(&desc);
  256. for (int i = 0; i < desc.Constants; i++)
  257. {
  258. D3DXCONSTANT_DESC cdesc;
  259. UINT count = 1;
  260. D3DXHANDLE h = data->frag_table->GetConstant(NULL, i);
  261. data->frag_table->GetConstantDesc(h, &cdesc, &count);
  262. }
  263. data->vert_table->GetDesc(&desc);
  264. for (int i = 0; i < desc.Constants; i++)
  265. {
  266. D3DXCONSTANT_DESC cdesc;
  267. UINT count = 1;
  268. D3DXHANDLE h = data->vert_table->GetConstant(NULL, i);
  269. data->frag_table->GetConstantDesc(h, &cdesc, &count);
  270. }
  271. #elif !defined __CELLOS_LV2__
  272. /* Create program */
  273. data->prog_id = glCreateProgram();
  274. glAttachShader(data->prog_id, data->vert_id);
  275. glAttachShader(data->prog_id, data->frag_id);
  276. glLinkProgram(data->prog_id);
  277. glGetProgramInfoLog(data->prog_id, sizeof(errbuf), &len, errbuf);
  278. glGetProgramiv(data->prog_id, GL_LINK_STATUS, &status);
  279. if (status != GL_TRUE)
  280. {
  281. Log::Error("failed to link program: %s", errbuf);
  282. }
  283. else if (len > 16)
  284. {
  285. Log::Debug("link log for program: %s", errbuf);
  286. }
  287. glValidateProgram(data->prog_id);
  288. #endif
  289. }
  290. ShaderAttrib Shader::GetAttribLocation(char const *attr,
  291. VertexUsage usage, int index) const
  292. {
  293. ShaderAttrib ret;
  294. ret.m_flags = (uint64_t)(uint16_t)usage << 16;
  295. ret.m_flags |= (uint64_t)(uint16_t)index;
  296. #if defined USE_D3D9 || defined _XBOX
  297. #elif !defined __CELLOS_LV2__
  298. GLint l = glGetAttribLocation(data->prog_id, attr);
  299. if (l < 0)
  300. {
  301. Log::Warn("tried to query invalid attribute: %s\n", attr);
  302. l = 0;
  303. }
  304. ret.m_flags |= (uint64_t)(uint32_t)l << 32;
  305. #else
  306. /* FIXME: can we do this at all on the PS3? */
  307. #endif
  308. return ret;
  309. }
  310. ShaderUniform Shader::GetUniformLocation(char const *uni) const
  311. {
  312. ShaderUniform ret;
  313. #if defined USE_D3D9 || defined _XBOX
  314. /* Global variables are prefixed with "$" */
  315. char tmpname[128];
  316. sprintf(tmpname, "$%s", uni);
  317. D3DXCONSTANT_DESC cdesc;
  318. D3DXHANDLE hr;
  319. UINT count;
  320. count = 0;
  321. hr = data->frag_table->GetConstantByName(NULL, tmpname);
  322. if (hr)
  323. data->frag_table->GetConstantDesc(hr, &cdesc, &count);
  324. if (count)
  325. {
  326. ret.frag = cdesc.RegisterIndex;
  327. ret.flags |= 1;
  328. }
  329. count = 0;
  330. hr = data->vert_table->GetConstantByName(NULL, tmpname);
  331. if (hr)
  332. data->vert_table->GetConstantDesc(hr, &cdesc, &count);
  333. if (count)
  334. {
  335. ret.vert = cdesc.RegisterIndex;
  336. ret.flags |= 2;
  337. }
  338. #elif !defined __CELLOS_LV2__
  339. ret.frag = (uintptr_t)glGetUniformLocation(data->prog_id, uni);
  340. ret.vert = 0;
  341. #else
  342. ret.frag = (uintptr_t)cgGetNamedParameter(data->frag_id, uni);
  343. ret.vert = (uintptr_t)cgGetNamedParameter(data->vert_id, uni);
  344. #endif
  345. return ret;
  346. }
  347. /*
  348. * Uniform setters for scalars
  349. */
  350. void Shader::SetUniform(ShaderUniform const &uni, int i)
  351. {
  352. #if defined USE_D3D9 || defined _XBOX
  353. SetUniform(uni, ivec4(i, 0, 0, 0));
  354. #elif !defined __CELLOS_LV2__
  355. glUniform1i(uni.frag, i);
  356. #else
  357. /* FIXME: does this exist at all? cgGLSetParameter1i doesn't. */
  358. #endif
  359. }
  360. void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v)
  361. {
  362. #if defined USE_D3D9 || defined _XBOX
  363. SetUniform(uni, ivec4(v, 0, 0));
  364. #elif !defined __CELLOS_LV2__
  365. glUniform2i(uni.frag, v.x, v.y);
  366. #else
  367. /* FIXME: does this exist at all? */
  368. #endif
  369. }
  370. void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v)
  371. {
  372. #if defined USE_D3D9 || defined _XBOX
  373. SetUniform(uni, ivec4(v, 0));
  374. #elif !defined __CELLOS_LV2__
  375. glUniform3i(uni.frag, v.x, v.y, v.z);
  376. #else
  377. /* FIXME: does this exist at all? */
  378. #endif
  379. }
  380. void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
  381. {
  382. #if defined USE_D3D9 || defined _XBOX
  383. if (uni.flags & 1)
  384. g_d3ddevice->SetPixelShaderConstantI((UINT)uni.frag, &v[0], 1);
  385. if (uni.flags & 2)
  386. g_d3ddevice->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1);
  387. #elif !defined __CELLOS_LV2__
  388. glUniform4i(uni.frag, v.x, v.y, v.z, v.w);
  389. #else
  390. /* FIXME: does this exist at all? */
  391. #endif
  392. }
  393. void Shader::SetUniform(ShaderUniform const &uni, float f)
  394. {
  395. #if defined USE_D3D9 || defined _XBOX
  396. SetUniform(uni, vec4(f, 0, 0, 0));
  397. #elif !defined __CELLOS_LV2__
  398. glUniform1f(uni.frag, f);
  399. #else
  400. if (uni.frag)
  401. cgGLSetParameter1f((CGparameter)uni.frag, f);
  402. if (uni.vert)
  403. cgGLSetParameter1f((CGparameter)uni.vert, f);
  404. #endif
  405. }
  406. void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v)
  407. {
  408. #if defined USE_D3D9 || defined _XBOX
  409. SetUniform(uni, vec4(v, 0, 0));
  410. #elif !defined __CELLOS_LV2__
  411. glUniform2fv(uni.frag, 1, &v[0]);
  412. #else
  413. if (uni.frag)
  414. cgGLSetParameter2fv((CGparameter)uni.frag, &v[0]);
  415. if (uni.vert)
  416. cgGLSetParameter2fv((CGparameter)uni.vert, &v[0]);
  417. #endif
  418. }
  419. void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v)
  420. {
  421. #if defined USE_D3D9 || defined _XBOX
  422. SetUniform(uni, vec4(v, 0));
  423. #elif !defined __CELLOS_LV2__
  424. glUniform3fv(uni.frag, 1, &v[0]);
  425. #else
  426. if (uni.frag)
  427. cgGLSetParameter3fv((CGparameter)uni.frag, &v[0]);
  428. if (uni.vert)
  429. cgGLSetParameter3fv((CGparameter)uni.vert, &v[0]);
  430. #endif
  431. }
  432. void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v)
  433. {
  434. #if defined USE_D3D9 || defined _XBOX
  435. if (uni.flags & 1)
  436. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &v[0], 1);
  437. if (uni.flags & 2)
  438. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1);
  439. #elif !defined __CELLOS_LV2__
  440. glUniform4fv(uni.frag, 1, &v[0]);
  441. #else
  442. if (uni.frag)
  443. cgGLSetParameter4fv((CGparameter)uni.frag, &v[0]);
  444. if (uni.vert)
  445. cgGLSetParameter4fv((CGparameter)uni.vert, &v[0]);
  446. #endif
  447. }
  448. void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
  449. {
  450. #if defined USE_D3D9 || defined _XBOX
  451. /* FIXME: do we need padding here like for the mat3 version? */
  452. if (uni.flags & 1)
  453. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 1);
  454. if (uni.flags & 2)
  455. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1);
  456. #elif !defined __CELLOS_LV2__
  457. glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  458. #else
  459. mat4 tmp(m, 1.0f, 1.0f);
  460. if (uni.frag)
  461. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  462. if (uni.vert)
  463. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  464. #endif
  465. }
  466. void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
  467. {
  468. #if defined USE_D3D9 || defined _XBOX
  469. /* Padding matrix columns is necessary on DirectX. We need to create
  470. * a new data structure; a 4×4 matrix will do. */
  471. mat4 tmp(m, 1.0f);
  472. if (uni.flags & 1)
  473. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &tmp[0][0], 3);
  474. if (uni.flags & 2)
  475. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3);
  476. #elif !defined __CELLOS_LV2__
  477. glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  478. #else
  479. /* FIXME: check it's the proper way to do this */
  480. mat4 tmp(m, 1.0f);
  481. if (uni.frag)
  482. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  483. if (uni.vert)
  484. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  485. #endif
  486. }
  487. void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
  488. {
  489. #if defined USE_D3D9 || defined _XBOX
  490. if (uni.flags & 1)
  491. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 4);
  492. if (uni.flags & 2)
  493. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4);
  494. #elif !defined __CELLOS_LV2__
  495. glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  496. #else
  497. if (uni.frag)
  498. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  499. if (uni.vert)
  500. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  501. #endif
  502. }
  503. void Shader::SetUniform(ShaderUniform const &uni, ShaderTexture tex, int index)
  504. {
  505. #if defined USE_D3D9 || defined _XBOX
  506. g_d3ddevice->SetTexture(index, (LPDIRECT3DTEXTURE9)tex.m_flags);
  507. #elif !defined __CELLOS_LV2__
  508. glActiveTexture(GL_TEXTURE0 + index);
  509. //glEnable(GL_TEXTURE_2D);
  510. glBindTexture(GL_TEXTURE_2D, (int)tex.m_flags);
  511. SetUniform(uni, index);
  512. #else
  513. /* FIXME: unimplemented */
  514. #endif
  515. }
  516. /*
  517. * Uniform setters for arrays
  518. */
  519. void Shader::SetUniform(ShaderUniform const &uni, Array<float> const &v)
  520. {
  521. #if defined USE_D3D9 || defined _XBOX
  522. /* FIXME: this will not work properly because we don't know how tell DX9
  523. * it's a bunch of floats instead of vec4. */
  524. if (uni.flags & 1)
  525. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
  526. &v[0], v.Count() / 4);
  527. if (uni.flags & 2)
  528. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
  529. &v[0], v.Count() / 4);
  530. #elif !defined __CELLOS_LV2__
  531. glUniform1fv(uni.frag, v.Count(), &v[0]);
  532. #else
  533. if (uni.frag)
  534. cgGLSetParameterArray1fv((CGparameter)uni.frag,
  535. 0, v.Count(), &v[0]);
  536. if (uni.vert)
  537. cgGLSetParameterArray1fv((CGparameter)uni.vert,
  538. 0, v.Count(), &v[0]);
  539. #endif
  540. }
  541. void Shader::SetUniform(ShaderUniform const &uni, Array<vec2> const &v)
  542. {
  543. #if defined USE_D3D9 || defined _XBOX
  544. /* FIXME: this will not work properly because we don't know how tell DX9
  545. * it's a bunch of vec2 instead of vec4. */
  546. if (uni.flags & 1)
  547. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
  548. &v[0][0], v.Count() / 2);
  549. if (uni.flags & 2)
  550. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
  551. &v[0][0], v.Count() / 2);
  552. #elif !defined __CELLOS_LV2__
  553. glUniform2fv(uni.frag, v.Count(), &v[0][0]);
  554. #else
  555. if (uni.frag)
  556. cgGLSetParameterArray2fv((CGparameter)uni.frag,
  557. 0, v.Count(), &v[0][0]);
  558. if (uni.vert)
  559. cgGLSetParameterArray2fv((CGparameter)uni.vert,
  560. 0, v.Count(), &v[0][0]);
  561. #endif
  562. }
  563. void Shader::SetUniform(ShaderUniform const &uni, Array<vec3> const &v)
  564. {
  565. #if defined USE_D3D9 || defined _XBOX
  566. /* FIXME: this will not work properly because we don't know how tell DX9
  567. * it's a bunch of vec3 instead of vec4. */
  568. if (uni.flags & 1)
  569. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
  570. &v[0][0], v.Count());
  571. if (uni.flags & 2)
  572. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
  573. &v[0][0], v.Count());
  574. #elif !defined __CELLOS_LV2__
  575. glUniform3fv(uni.frag, v.Count(), &v[0][0]);
  576. #else
  577. if (uni.frag)
  578. cgGLSetParameterArray3fv((CGparameter)uni.frag,
  579. 0, v.Count(), &v[0][0]);
  580. if (uni.vert)
  581. cgGLSetParameterArray3fv((CGparameter)uni.vert,
  582. 0, v.Count(), &v[0][0]);
  583. #endif
  584. }
  585. void Shader::SetUniform(ShaderUniform const &uni, Array<vec4> const &v)
  586. {
  587. #if defined USE_D3D9 || defined _XBOX
  588. if (uni.flags & 1)
  589. g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
  590. &v[0][0], v.Count());
  591. if (uni.flags & 2)
  592. g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
  593. &v[0][0], v.Count());
  594. #elif !defined __CELLOS_LV2__
  595. glUniform4fv(uni.frag, v.Count(), &v[0][0]);
  596. #else
  597. if (uni.frag)
  598. cgGLSetParameterArray4fv((CGparameter)uni.frag,
  599. 0, v.Count(), &v[0][0]);
  600. if (uni.vert)
  601. cgGLSetParameterArray4fv((CGparameter)uni.vert,
  602. 0, v.Count(), &v[0][0]);
  603. #endif
  604. }
  605. void Shader::Bind() const
  606. {
  607. #if defined USE_D3D9 || defined _XBOX
  608. HRESULT hr;
  609. hr = g_d3ddevice->SetVertexShader(data->vert_shader);
  610. hr = g_d3ddevice->SetPixelShader(data->frag_shader);
  611. #elif !defined __CELLOS_LV2__
  612. glUseProgram(data->prog_id);
  613. #else
  614. cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
  615. cgGLBindProgram(data->vert_id);
  616. cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
  617. cgGLBindProgram(data->frag_id);
  618. #endif
  619. }
  620. void Shader::Unbind() const
  621. {
  622. #if defined USE_D3D9 || defined _XBOX
  623. HRESULT hr;
  624. hr = g_d3ddevice->SetVertexShader(NULL);
  625. hr = g_d3ddevice->SetPixelShader(NULL);
  626. #elif !defined __CELLOS_LV2__
  627. /* FIXME: untested */
  628. glUseProgram(0);
  629. #else
  630. /* FIXME: untested */
  631. cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
  632. cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
  633. #endif
  634. }
  635. Shader::~Shader()
  636. {
  637. #if defined USE_D3D9 || defined _XBOX
  638. data->vert_shader->Release();
  639. data->vert_table->Release();
  640. data->frag_shader->Release();
  641. data->frag_table->Release();
  642. #elif !defined __CELLOS_LV2__
  643. glDetachShader(data->prog_id, data->vert_id);
  644. glDetachShader(data->prog_id, data->frag_id);
  645. glDeleteShader(data->vert_id);
  646. glDeleteShader(data->frag_id);
  647. glDeleteProgram(data->prog_id);
  648. #else
  649. cgDestroyProgram(data->vert_id);
  650. cgDestroyProgram(data->frag_id);
  651. #endif
  652. delete data;
  653. }
  654. /* Try to detect shader compiler features */
  655. int ShaderData::GetVersion()
  656. {
  657. static int version = 0;
  658. #if !defined USE_D3D9 && !defined _XBOX && !defined __CELLOS_LV2__
  659. if (!version)
  660. {
  661. #if defined HAVE_GLES_2X
  662. /* GLES 2.x supports #version 100, that's all. */
  663. return 100;
  664. #else
  665. char buf[4096];
  666. GLsizei len;
  667. int id = glCreateShader(GL_VERTEX_SHADER);
  668. /* Can we compile 1.30 shaders? */
  669. char const *test130 =
  670. "#version 130\n"
  671. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  672. glShaderSource(id, 1, &test130, NULL);
  673. glCompileShader(id);
  674. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  675. if (len <= 0)
  676. version = 130;
  677. /* If not, can we compile 1.20 shaders? */
  678. if (!version)
  679. {
  680. char const *test120 =
  681. "#version 120\n"
  682. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  683. glShaderSource(id, 1, &test120, NULL);
  684. glCompileShader(id);
  685. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  686. if (len <= 0)
  687. version = 120;
  688. }
  689. /* Otherwise, assume we can compile 1.10 shaders. */
  690. if (!version)
  691. version = 110;
  692. glDeleteShader(id);
  693. #endif
  694. }
  695. #endif
  696. return version;
  697. }
  698. /* Simple shader source patching for old GLSL versions.
  699. */
  700. void ShaderData::Patch(char *dst, char const *vert, char const *frag)
  701. {
  702. int ver_driver = GetVersion();
  703. strcpy(dst, vert ? vert : frag);
  704. if (ver_driver >= 130)
  705. return;
  706. int ver_shader = 110;
  707. char *parser = strstr(dst, "#version");
  708. if (parser)
  709. ver_shader = atoi(parser + strlen("#version"));
  710. /* This is GL ES, we only know version 100. */
  711. if (ver_shader > 100 && ver_driver == 100)
  712. {
  713. /* FIXME: this isn't elegant but honestly, we don't care, this
  714. * whole file is going to die soon. */
  715. char *p = strstr(dst, "#version");
  716. if (p)
  717. {
  718. p += 8;
  719. while (*p == ' ')
  720. p++;
  721. if (p[0] == '1' && p[1] && p[2])
  722. p[1] = p[2] = '0';
  723. }
  724. }
  725. if (ver_shader > 120 && ver_driver <= 120)
  726. {
  727. char const *end = dst + strlen(dst) + 1;
  728. /* Find main() */
  729. parser = strstr(dst, "main");
  730. if (!parser) return;
  731. parser = strstr(parser, "(");
  732. if (!parser) return;
  733. parser = strstr(parser, ")");
  734. if (!parser) return;
  735. parser = strstr(parser, "{");
  736. if (!parser) return;
  737. char *main = parser + 1;
  738. /* Perform main() replaces */
  739. char const * const main_replaces[] =
  740. {
  741. #if 0
  742. "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;",
  743. "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;",
  744. "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;",
  745. "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;",
  746. "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;",
  747. "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;",
  748. "in vec2 in_MultiTexCoord0;",
  749. "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;",
  750. "in vec2 in_MultiTexCoord1;",
  751. "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;",
  752. "in vec2 in_MultiTexCoord2;",
  753. "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;",
  754. "in vec2 in_MultiTexCoord3;",
  755. "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;",
  756. "in vec2 in_MultiTexCoord4;",
  757. "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;",
  758. "in vec2 in_MultiTexCoord5;",
  759. "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;",
  760. "in vec2 in_MultiTexCoord6;",
  761. "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;",
  762. "in vec2 in_MultiTexCoord7;",
  763. "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;",
  764. #endif
  765. NULL
  766. };
  767. for (char const * const *rep = main_replaces; rep[0]; rep += 2)
  768. {
  769. char *match = strstr(dst, rep[0]);
  770. if (match && match < main)
  771. {
  772. size_t l0 = strlen(rep[0]);
  773. size_t l1 = strlen(rep[1]);
  774. memmove(main + l1, main, end - main);
  775. memcpy(main, rep[1], l1);
  776. memset(match, ' ', l0);
  777. main += l1;
  778. end += l1;
  779. }
  780. }
  781. /* Perform small replaces */
  782. char const * const fast_replaces[] =
  783. {
  784. "#version 130", "#version 120",
  785. "in vec2", vert ? "attribute vec2" : "varying vec2",
  786. "in vec3", vert ? "attribute vec3" : "varying vec3",
  787. "in vec4", vert ? "attribute vec4" : "varying vec4",
  788. "in mat4", vert ? "attribute mat4" : "varying mat4",
  789. "out vec2", "varying vec2",
  790. "out vec3", "varying vec3",
  791. "out vec4", "varying vec4",
  792. "out mat4", "varying mat4",
  793. NULL
  794. };
  795. for (char const * const *rep = fast_replaces; rep[0]; rep += 2)
  796. {
  797. char *match;
  798. while ((match = strstr(dst, rep[0])))
  799. {
  800. size_t l0 = strlen(rep[0]);
  801. size_t l1 = strlen(rep[1]);
  802. if (l1 > l0)
  803. memmove(match + l1, match + l0, (end - match) - l0);
  804. memcpy(match, rep[1], l1);
  805. if (l1 < l0)
  806. memset(match + l0, ' ', l1 - l0);
  807. end += l1 - l0;
  808. }
  809. }
  810. }
  811. }
  812. } /* namespace lol */