You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

849 lines
25KB

  1. //
  2. // Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
  3. //
  4. // This software is provided 'as-is', without any express or implied
  5. // warranty. In no event will the authors be held liable for any damages
  6. // arising from the use of this software.
  7. // Permission is granted to anyone to use this software for any purpose,
  8. // including commercial applications, and to alter it and redistribute it
  9. // freely, subject to the following restrictions:
  10. // 1. The origin of this software must not be misrepresented; you must not
  11. // claim that you wrote the original software. If you use this software
  12. // in a product, an acknowledgment in the product documentation would be
  13. // appreciated but is not required.
  14. // 2. Altered source versions must be plainly marked as such, and must not be
  15. // misrepresented as being the original software.
  16. // 3. This notice may not be removed or altered from any source distribution.
  17. //
  18. #ifndef NANOVG_GL3_H
  19. #define NANOVG_GL3_H
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. struct NVGcontext* nvgCreateGL3();
  24. void nvgDeleteGL3(struct NVGcontext* ctx);
  25. #ifdef __cplusplus
  26. }
  27. #endif
  28. #endif
  29. #ifdef NANOVG_GL3_IMPLEMENTATION
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include "nanovg.h"
  33. enum GLNVGuniformLoc {
  34. GLNVG_LOC_VIEWPOS,
  35. GLNVG_LOC_VIEWSIZE,
  36. GLNVG_LOC_SCISSORMAT,
  37. GLNVG_LOC_SCISSOREXT,
  38. GLNVG_LOC_PAINTMAT,
  39. GLNVG_LOC_EXTENT,
  40. GLNVG_LOC_RADIUS,
  41. GLNVG_LOC_FEATHER,
  42. GLNVG_LOC_INNERCOL,
  43. GLNVG_LOC_OUTERCOL,
  44. GLNVG_LOC_STROKEMULT,
  45. GLNVG_LOC_TEX,
  46. GLNVG_LOC_TEXTYPE,
  47. GLNVG_MAX_LOCS
  48. };
  49. struct GLNVGshader {
  50. GLuint prog;
  51. GLuint frag;
  52. GLuint vert;
  53. GLint loc[GLNVG_MAX_LOCS];
  54. };
  55. struct GLNVGtexture {
  56. int id;
  57. GLuint tex;
  58. int width, height;
  59. int type;
  60. };
  61. struct GLNVGcontext {
  62. struct GLNVGshader gradShader;
  63. struct GLNVGshader imgShader;
  64. struct GLNVGshader solidShader;
  65. struct GLNVGshader solidImgShader;
  66. struct GLNVGtexture* textures;
  67. float viewWidth, viewHeight;
  68. int ntextures;
  69. int ctextures;
  70. int textureId;
  71. GLuint vertArr;
  72. GLuint vertBuf;
  73. int vertArrSize;
  74. };
  75. static struct GLNVGtexture* glnvg__allocTexture(struct GLNVGcontext* gl)
  76. {
  77. struct GLNVGtexture* tex = NULL;
  78. int i;
  79. for (i = 0; i < gl->ntextures; i++) {
  80. if (gl->textures[i].id == 0) {
  81. tex = &gl->textures[i];
  82. break;
  83. }
  84. }
  85. if (tex == NULL) {
  86. if (gl->ntextures+1 > gl->ctextures) {
  87. gl->ctextures = (gl->ctextures == 0) ? 2 : gl->ctextures*2;
  88. gl->textures = (struct GLNVGtexture*)realloc(gl->textures, sizeof(struct GLNVGtexture)*gl->ctextures);
  89. if (gl->textures == NULL) return NULL;
  90. }
  91. tex = &gl->textures[gl->ntextures++];
  92. }
  93. memset(tex, 0, sizeof(*tex));
  94. tex->id = ++gl->textureId;
  95. return tex;
  96. }
  97. static struct GLNVGtexture* glnvg__findTexture(struct GLNVGcontext* gl, int id)
  98. {
  99. int i;
  100. for (i = 0; i < gl->ntextures; i++)
  101. if (gl->textures[i].id == id)
  102. return &gl->textures[i];
  103. return NULL;
  104. }
  105. static int glnvg__deleteTexture(struct GLNVGcontext* gl, int id)
  106. {
  107. int i;
  108. for (i = 0; i < gl->ntextures; i++) {
  109. if (gl->textures[i].id == id) {
  110. if (gl->textures[i].tex != 0)
  111. glDeleteTextures(1, &gl->textures[i].tex);
  112. memset(&gl->textures[i], 0, sizeof(gl->textures[i]));
  113. return 1;
  114. }
  115. }
  116. return 0;
  117. }
  118. static void glnvg__dumpShaderError(GLuint shader, const char* name, const char* type)
  119. {
  120. char str[512+1];
  121. int len = 0;
  122. glGetShaderInfoLog(shader, 512, &len, str);
  123. if (len > 512) len = 512;
  124. str[len] = '\0';
  125. printf("Shader %s/%s error:\n%s\n", name, type, str);
  126. }
  127. static void glnvg__dumpProgramError(GLuint prog, const char* name)
  128. {
  129. char str[512+1];
  130. int len = 0;
  131. glGetProgramInfoLog(prog, 512, &len, str);
  132. if (len > 512) len = 512;
  133. str[len] = '\0';
  134. printf("Program %s error:\n%s\n", name, str);
  135. }
  136. static int glnvg__checkError(const char* str)
  137. {
  138. GLenum err = glGetError();
  139. if (err != GL_NO_ERROR) {
  140. printf("Error %08x after %s\n", err, str);
  141. return 1;
  142. }
  143. return 0;
  144. }
  145. static int glnvg__createShader(struct GLNVGshader* shader, const char* name, const char* vshader, const char* fshader)
  146. {
  147. GLint status;
  148. GLuint prog, vert, frag;
  149. memset(shader, 0, sizeof(*shader));
  150. prog = glCreateProgram();
  151. vert = glCreateShader(GL_VERTEX_SHADER);
  152. frag = glCreateShader(GL_FRAGMENT_SHADER);
  153. glShaderSource(vert, 1, &vshader, 0);
  154. glShaderSource(frag, 1, &fshader, 0);
  155. glCompileShader(vert);
  156. glGetShaderiv(vert, GL_COMPILE_STATUS, &status);
  157. if (status != GL_TRUE) {
  158. glnvg__dumpShaderError(vert, name, "vert");
  159. return 0;
  160. }
  161. glCompileShader(frag);
  162. glGetShaderiv(frag, GL_COMPILE_STATUS, &status);
  163. if (status != GL_TRUE) {
  164. glnvg__dumpShaderError(frag, name, "frag");
  165. return 0;
  166. }
  167. glAttachShader(prog, vert);
  168. glAttachShader(prog, frag);
  169. glBindAttribLocation(prog, 0, "vertex");
  170. glBindAttribLocation(prog, 1, "tcoord");
  171. glBindAttribLocation(prog, 2, "color");
  172. glLinkProgram(prog);
  173. glGetProgramiv(prog, GL_LINK_STATUS, &status);
  174. if (status != GL_TRUE) {
  175. glnvg__dumpProgramError(prog, name);
  176. return 0;
  177. }
  178. shader->prog = prog;
  179. shader->vert = vert;
  180. shader->frag = frag;
  181. return 1;
  182. }
  183. static void glnvg__deleteShader(struct GLNVGshader* shader)
  184. {
  185. if (shader->prog != 0)
  186. glDeleteProgram(shader->prog);
  187. if (shader->vert != 0)
  188. glDeleteShader(shader->vert);
  189. if (shader->frag != 0)
  190. glDeleteShader(shader->frag);
  191. }
  192. static void glnvg__getUniforms(struct GLNVGshader* shader)
  193. {
  194. shader->loc[GLNVG_LOC_VIEWPOS] = glGetUniformLocation(shader->prog, "viewPos");
  195. shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize");
  196. shader->loc[GLNVG_LOC_SCISSORMAT] = glGetUniformLocation(shader->prog, "scissorMat");
  197. shader->loc[GLNVG_LOC_SCISSOREXT] = glGetUniformLocation(shader->prog, "scissorExt");
  198. shader->loc[GLNVG_LOC_PAINTMAT] = glGetUniformLocation(shader->prog, "paintMat");
  199. shader->loc[GLNVG_LOC_EXTENT] = glGetUniformLocation(shader->prog, "extent");
  200. shader->loc[GLNVG_LOC_RADIUS] = glGetUniformLocation(shader->prog, "radius");
  201. shader->loc[GLNVG_LOC_FEATHER] = glGetUniformLocation(shader->prog, "feather");
  202. shader->loc[GLNVG_LOC_INNERCOL] = glGetUniformLocation(shader->prog, "innerCol");
  203. shader->loc[GLNVG_LOC_OUTERCOL] = glGetUniformLocation(shader->prog, "outerCol");
  204. shader->loc[GLNVG_LOC_STROKEMULT] = glGetUniformLocation(shader->prog, "strokeMult");
  205. shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex");
  206. shader->loc[GLNVG_LOC_TEXTYPE] = glGetUniformLocation(shader->prog, "texType");
  207. }
  208. static int glnvg__renderCreate(void* uptr)
  209. {
  210. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  211. static const char* fillVertShader =
  212. "#version 150 core\n"
  213. "uniform vec2 viewPos;\n"
  214. "uniform vec2 viewSize;\n"
  215. "in vec2 vertex;\n"
  216. "in vec2 tcoord;\n"
  217. "in vec4 color;\n"
  218. "out vec2 ftcoord;\n"
  219. "out vec4 fcolor;\n"
  220. "out vec2 fpos;\n"
  221. "void main(void) {\n"
  222. " ftcoord = tcoord;\n"
  223. " fcolor = color;\n"
  224. " fpos = vertex;\n"
  225. " gl_Position = vec4(2.0*(vertex.x+viewPos.x)/viewSize.x - 1.0, 1.0 - 2.0*(vertex.y+viewPos.y)/viewSize.y, 0, 1);\n"
  226. "}\n";
  227. static const char* fillFragGradShader =
  228. "#version 150 core\n"
  229. "uniform mat3 scissorMat;\n"
  230. "uniform vec2 scissorExt;\n"
  231. "uniform mat3 paintMat;\n"
  232. "uniform vec2 extent;\n"
  233. "uniform float radius;\n"
  234. "uniform float feather;\n"
  235. "uniform vec4 innerCol;\n"
  236. "uniform vec4 outerCol;\n"
  237. "uniform float strokeMult;\n"
  238. "in vec2 ftcoord;\n"
  239. "in vec4 fcolor;\n"
  240. "in vec2 fpos;\n"
  241. "out vec4 outColor;\n"
  242. "float sdroundrect(vec2 pt, vec2 ext, float rad) {\n"
  243. " vec2 ext2 = ext - vec2(rad,rad);\n"
  244. " vec2 d = abs(pt) - ext2;\n"
  245. " return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n"
  246. "}\n"
  247. "void main(void) {\n"
  248. " // Scissoring\n"
  249. " vec2 sc = vec2(0.5,0.5) - (abs((scissorMat * vec3(fpos,1.0)).xy) - scissorExt);\n"
  250. " float scissor = clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
  251. // " if (scissor < 0.001) discard;\n"
  252. " // Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n"
  253. " float strokeAlpha = min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * ftcoord.y;\n"
  254. " // Calculate gradient color using box gradient\n"
  255. " vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
  256. " float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
  257. " vec4 color = mix(innerCol,outerCol,d);\n"
  258. " // Combine alpha\n"
  259. " color.w *= strokeAlpha * scissor;\n"
  260. " outColor = color;\n"
  261. "}\n";
  262. static const char* fillFragImgShader =
  263. "#version 150 core\n"
  264. "uniform mat3 scissorMat;\n"
  265. "uniform vec2 scissorExt;\n"
  266. "uniform mat3 paintMat;\n"
  267. "uniform vec2 extent;\n"
  268. "uniform float strokeMult;\n"
  269. "uniform sampler2D tex;\n"
  270. "uniform int texType;\n"
  271. "in vec2 ftcoord;\n"
  272. "in vec4 fcolor;\n"
  273. "in vec2 fpos;\n"
  274. "out vec4 outColor;\n"
  275. "void main(void) {\n"
  276. " // Scissoring\n"
  277. " vec2 sc = vec2(0.5,0.5) - (abs((scissorMat * vec3(fpos,1.0)).xy) - scissorExt);\n"
  278. " float scissor = clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
  279. // " if (scissor < 0.001) discard;\n"
  280. " // Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n"
  281. " float strokeAlpha = min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * ftcoord.y;\n"
  282. " // Calculate color fron texture\n"
  283. " vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
  284. " pt /= extent;\n"
  285. " vec4 color = texture(tex, pt);\n"
  286. " color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
  287. " // Combine alpha\n"
  288. " color.w *= strokeAlpha * scissor;\n"
  289. " outColor = color;\n"
  290. "}\n";
  291. static const char* fillFragSolidShader =
  292. "#version 150 core\n"
  293. "in vec2 ftcoord;\n"
  294. "in vec4 fcolor;\n"
  295. "in vec2 fpos;\n"
  296. "out vec4 outColor;\n"
  297. "void main(void) {\n"
  298. " outColor = vec4(1,1,1,1);\n"
  299. "}\n";
  300. static const char* fillFragSolidImgShader =
  301. "#version 150 core\n"
  302. "uniform sampler2D tex;\n"
  303. "uniform int texType;\n"
  304. "in vec2 ftcoord;\n"
  305. "in vec4 fcolor;\n"
  306. "in vec2 fpos;\n"
  307. "out vec4 outColor;\n"
  308. "void main(void) {\n"
  309. " vec4 color = texture(tex, ftcoord);\n"
  310. " color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
  311. " outColor = color * fcolor;\n"
  312. "}\n";
  313. glnvg__checkError("init");
  314. if (glnvg__createShader(&gl->gradShader, "grad", fillVertShader, fillFragGradShader) == 0)
  315. return 0;
  316. if (glnvg__createShader(&gl->imgShader, "image", fillVertShader, fillFragImgShader) == 0)
  317. return 0;
  318. if (glnvg__createShader(&gl->solidShader, "solid", fillVertShader, fillFragSolidShader) == 0)
  319. return 0;
  320. if (glnvg__createShader(&gl->solidImgShader, "solid-img", fillVertShader, fillFragSolidImgShader) == 0)
  321. return 0;
  322. glnvg__checkError("uniform locations");
  323. glnvg__getUniforms(&gl->gradShader);
  324. glnvg__getUniforms(&gl->imgShader);
  325. glnvg__getUniforms(&gl->solidShader);
  326. glnvg__getUniforms(&gl->solidImgShader);
  327. // Create dynamic vertex array
  328. glGenVertexArrays(1, &gl->vertArr);
  329. glGenBuffers(1, &gl->vertBuf);
  330. gl->vertArrSize = 0;
  331. glnvg__checkError("done");
  332. return 1;
  333. }
  334. static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, const unsigned char* data)
  335. {
  336. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  337. struct GLNVGtexture* tex = glnvg__allocTexture(gl);
  338. if (tex == NULL) return 0;
  339. glGenTextures(1, &tex->tex);
  340. tex->width = w;
  341. tex->height = h;
  342. tex->type = type;
  343. glBindTexture(GL_TEXTURE_2D, tex->tex);
  344. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  345. glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
  346. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  347. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  348. if (type == NVG_TEXTURE_RGBA)
  349. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  350. else
  351. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
  352. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  353. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  354. if (glnvg__checkError("create tex"))
  355. return 0;
  356. return tex->id;
  357. }
  358. static int glnvg__renderDeleteTexture(void* uptr, int image)
  359. {
  360. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  361. return glnvg__deleteTexture(gl, image);
  362. }
  363. static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data)
  364. {
  365. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  366. struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
  367. if (tex == NULL) return 0;
  368. glBindTexture(GL_TEXTURE_2D, tex->tex);
  369. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  370. glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
  371. glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
  372. glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
  373. if (tex->type == NVG_TEXTURE_RGBA)
  374. glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data);
  375. else
  376. glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data);
  377. return 1;
  378. }
  379. static int glnvg__renderGetTextureSize(void* uptr, int image, int* w, int* h)
  380. {
  381. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  382. struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
  383. if (tex == NULL) return 0;
  384. *w = tex->width;
  385. *h = tex->height;
  386. return 1;
  387. }
  388. static void glnvg__toFloatColor(float* fc, unsigned int c)
  389. {
  390. fc[0] = ((c) & 0xff) / 255.0f;
  391. fc[1] = ((c>>8) & 0xff) / 255.0f;
  392. fc[2] = ((c>>16) & 0xff) / 255.0f;
  393. fc[3] = ((c>>24) & 0xff) / 255.0f;
  394. }
  395. static void glnvg__xformIdentity(float* t)
  396. {
  397. t[0] = 1.0f; t[1] = 0.0f;
  398. t[2] = 0.0f; t[3] = 1.0f;
  399. t[4] = 0.0f; t[5] = 0.0f;
  400. }
  401. static void glnvg__xformInverse(float* inv, float* t)
  402. {
  403. double det = (double)t[0] * t[3] - (double)t[2] * t[1];
  404. if (det > -1e-6 && det < 1e-6) {
  405. glnvg__xformIdentity(t);
  406. return;
  407. }
  408. double invdet = 1.0 / det;
  409. inv[0] = (float)(t[3] * invdet);
  410. inv[2] = (float)(-t[2] * invdet);
  411. inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
  412. inv[1] = (float)(-t[1] * invdet);
  413. inv[3] = (float)(t[0] * invdet);
  414. inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
  415. }
  416. static void glnvg__xformToMat3x3(float* m3, float* t)
  417. {
  418. m3[0] = t[0];
  419. m3[1] = t[1];
  420. m3[2] = 0.0f;
  421. m3[3] = t[2];
  422. m3[4] = t[3];
  423. m3[5] = 0.0f;
  424. m3[6] = t[4];
  425. m3[7] = t[5];
  426. m3[8] = 1.0f;
  427. }
  428. static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor,
  429. float width, float aasize)
  430. {
  431. float innerCol[4];
  432. float outerCol[4];
  433. glnvg__toFloatColor(innerCol, paint->innerColor);
  434. glnvg__toFloatColor(outerCol, paint->outerColor);
  435. struct GLNVGtexture* tex = NULL;
  436. float invxform[6], paintMat[9], scissorMat[9];
  437. float scissorx = 0, scissory = 0;
  438. glnvg__xformInverse(invxform, paint->xform);
  439. glnvg__xformToMat3x3(paintMat, invxform);
  440. if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) {
  441. memset(scissorMat, 0, sizeof(scissorMat));
  442. scissorx = 1.0f;
  443. scissory = 1.0f;
  444. } else {
  445. glnvg__xformInverse(invxform, scissor->xform);
  446. glnvg__xformToMat3x3(scissorMat, invxform);
  447. scissorx = scissor->extent[0];
  448. scissory = scissor->extent[1];
  449. }
  450. if (paint->image != 0) {
  451. tex = glnvg__findTexture(gl, paint->image);
  452. if (tex == NULL) return 0;
  453. glUseProgram(gl->imgShader.prog);
  454. glUniform2f(gl->imgShader.loc[GLNVG_LOC_VIEWPOS], 0, 0);
  455. glUniform2f(gl->imgShader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
  456. glUniformMatrix3fv(gl->imgShader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat);
  457. glUniform2f(gl->imgShader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory);
  458. glUniformMatrix3fv(gl->imgShader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat);
  459. glUniform2f(gl->imgShader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]);
  460. glUniform1f(gl->imgShader.loc[GLNVG_LOC_STROKEMULT], width*0.5f + aasize*0.5f);
  461. glUniform1i(gl->imgShader.loc[GLNVG_LOC_TEX], 0);
  462. glUniform1i(gl->imgShader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1);
  463. glnvg__checkError("tex paint loc");
  464. glBindTexture(GL_TEXTURE_2D, tex->tex);
  465. glnvg__checkError("tex paint tex");
  466. } else {
  467. glUseProgram(gl->gradShader.prog);
  468. glUniform2f(gl->gradShader.loc[GLNVG_LOC_VIEWPOS], 0, 0);
  469. glUniform2f(gl->gradShader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
  470. glUniformMatrix3fv(gl->gradShader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat);
  471. glUniform2f(gl->gradShader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory);
  472. glUniformMatrix3fv(gl->gradShader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat);
  473. glUniform2f(gl->gradShader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]);
  474. glUniform1f(gl->gradShader.loc[GLNVG_LOC_RADIUS], paint->radius);
  475. glUniform1f(gl->gradShader.loc[GLNVG_LOC_FEATHER], paint->feather);
  476. glUniform4fv(gl->gradShader.loc[GLNVG_LOC_INNERCOL], 1, innerCol);
  477. glUniform4fv(gl->gradShader.loc[GLNVG_LOC_OUTERCOL], 1, outerCol);
  478. glUniform1f(gl->gradShader.loc[GLNVG_LOC_STROKEMULT], width*0.5f + aasize*0.5f);
  479. glnvg__checkError("grad paint loc");
  480. }
  481. return 1;
  482. }
  483. static void glnvg__renderViewport(void* uptr, int width, int height)
  484. {
  485. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  486. gl->viewWidth = width;
  487. gl->viewHeight = height;
  488. }
  489. static int glnvg__maxVertCount(const struct NVGpath* paths, int npaths)
  490. {
  491. int i, count = 0;
  492. for (i = 0; i < npaths; i++) {
  493. count += paths[i].nfill;
  494. count += paths[i].nstroke;
  495. }
  496. return count;
  497. }
  498. static void glnvg__uploadPaths(const struct NVGpath* paths, int npaths)
  499. {
  500. const struct NVGpath* path;
  501. int i, n = 0;
  502. for (i = 0; i < npaths; i++) {
  503. path = &paths[i];
  504. if (path->nfill > 0) {
  505. glBufferSubData(GL_ARRAY_BUFFER, n*sizeof(struct NVGvertex), path->nfill * sizeof(struct NVGvertex), &path->fill[0].x);
  506. n += path->nfill;
  507. }
  508. if (path->nstroke > 0) {
  509. glBufferSubData(GL_ARRAY_BUFFER, n*sizeof(struct NVGvertex), path->nstroke * sizeof(struct NVGvertex), &path->stroke[0].x);
  510. n += path->nstroke;
  511. }
  512. }
  513. }
  514. static void glnvg__renderFill(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float aasize,
  515. const float* bounds, const struct NVGpath* paths, int npaths)
  516. {
  517. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  518. const struct NVGpath* path;
  519. int i, n, offset, maxCount;
  520. if (gl->gradShader.prog == 0)
  521. return;
  522. maxCount = glnvg__maxVertCount(paths, npaths);
  523. glBindVertexArray(gl->vertArr);
  524. glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
  525. glBufferData(GL_ARRAY_BUFFER, maxCount * sizeof(struct NVGvertex), NULL, GL_STREAM_DRAW);
  526. glnvg__uploadPaths(paths, npaths);
  527. if (npaths == 1 && paths[0].convex) {
  528. glEnable(GL_CULL_FACE);
  529. glEnableVertexAttribArray(0);
  530. glEnableVertexAttribArray(1);
  531. glnvg__setupPaint(gl, paint, scissor, 1.0001f, aasize);
  532. glDisable(GL_CULL_FACE);
  533. n = 0;
  534. for (i = 0; i < npaths; i++) {
  535. path = &paths[i];
  536. offset = n * sizeof(struct NVGvertex);
  537. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
  538. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
  539. glDrawArrays(GL_TRIANGLE_FAN, 0, path->nfill);
  540. n += path->nfill + path->nstroke;
  541. }
  542. glEnable(GL_CULL_FACE);
  543. // Draw fringes
  544. n = 0;
  545. for (i = 0; i < npaths; i++) {
  546. path = &paths[i];
  547. offset = (n + path->nfill) * sizeof(struct NVGvertex);
  548. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
  549. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
  550. glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
  551. n += path->nfill + path->nstroke;
  552. }
  553. glUseProgram(0);
  554. glDisableVertexAttribArray(0);
  555. glDisableVertexAttribArray(1);
  556. } else {
  557. glEnable(GL_CULL_FACE);
  558. glBindVertexArray(gl->vertArr);
  559. glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
  560. // Draw shapes
  561. glDisable(GL_BLEND);
  562. glEnable(GL_STENCIL_TEST);
  563. glStencilMask(0xff);
  564. glStencilFunc(GL_ALWAYS, 0, ~0);
  565. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  566. glUseProgram(gl->solidShader.prog);
  567. glUniform2f(gl->solidShader.loc[GLNVG_LOC_VIEWPOS], 0, 0);
  568. glUniform2f(gl->solidShader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
  569. glnvg__checkError("fill solid loc");
  570. glEnableVertexAttribArray(0);
  571. glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
  572. glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
  573. glDisable(GL_CULL_FACE);
  574. n = 0;
  575. for (i = 0; i < npaths; i++) {
  576. path = &paths[i];
  577. offset = n * sizeof(struct NVGvertex);
  578. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
  579. glDrawArrays(GL_TRIANGLE_FAN, 0, path->nfill);
  580. n += path->nfill + path->nstroke;
  581. }
  582. glEnable(GL_CULL_FACE);
  583. // Draw aliased off-pixels
  584. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  585. glEnable(GL_BLEND);
  586. glStencilFunc(GL_EQUAL, 0x00, 0xff);
  587. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  588. glEnableVertexAttribArray(1);
  589. glnvg__setupPaint(gl, paint, scissor, 1.0001f, aasize);
  590. // Draw fringes
  591. n = 0;
  592. for (i = 0; i < npaths; i++) {
  593. path = &paths[i];
  594. offset = (n + path->nfill) * sizeof(struct NVGvertex);
  595. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
  596. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
  597. glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
  598. n += path->nfill + path->nstroke;
  599. }
  600. // Draw fill
  601. glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
  602. glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
  603. glDisableVertexAttribArray(1);
  604. float quad[6*2] = {
  605. bounds[0], bounds[3], bounds[2], bounds[3], bounds[2], bounds[1],
  606. bounds[0], bounds[3], bounds[2], bounds[1], bounds[0], bounds[1],
  607. };
  608. glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * 2*sizeof(float), quad);
  609. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (const GLvoid*)0);
  610. glVertexAttrib2f(1, 0.5f, 1.0f);
  611. glDrawArrays(GL_TRIANGLES, 0, 6);
  612. glUseProgram(0);
  613. glDisableVertexAttribArray(0);
  614. glDisable(GL_STENCIL_TEST);
  615. }
  616. }
  617. static void glnvg__renderStroke(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float aasize,
  618. float width, const struct NVGpath* paths, int npaths)
  619. {
  620. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  621. const struct NVGpath* path;
  622. int i, n, offset, maxCount;
  623. if (gl->gradShader.prog == 0)
  624. return;
  625. glnvg__setupPaint(gl, paint, scissor, width, aasize);
  626. glEnable(GL_CULL_FACE);
  627. maxCount = glnvg__maxVertCount(paths, npaths);
  628. glBindVertexArray(gl->vertArr);
  629. glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
  630. glBufferData(GL_ARRAY_BUFFER, maxCount * sizeof(struct NVGvertex), NULL, GL_STREAM_DRAW);
  631. glnvg__uploadPaths(paths, npaths);
  632. glEnableVertexAttribArray(0);
  633. glEnableVertexAttribArray(1);
  634. // Draw Strokes
  635. n = 0;
  636. for (i = 0; i < npaths; i++) {
  637. path = &paths[i];
  638. offset = (n + path->nfill) * sizeof(struct NVGvertex);
  639. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
  640. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
  641. glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
  642. n += path->nfill + path->nstroke;
  643. }
  644. glDisableVertexAttribArray(0);
  645. glDisableVertexAttribArray(1);
  646. glUseProgram(0);
  647. }
  648. static void glnvg__renderTriangles(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, int image,
  649. const struct NVGvertex* verts, int nverts)
  650. {
  651. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  652. struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
  653. float color[4];
  654. if (tex != NULL) {
  655. glBindTexture(GL_TEXTURE_2D, tex->tex);
  656. }
  657. glUseProgram(gl->solidImgShader.prog);
  658. glUniform2f(gl->solidImgShader.loc[GLNVG_LOC_VIEWPOS], 0, 0);
  659. glUniform2f(gl->solidImgShader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
  660. glUniform1i(gl->solidImgShader.loc[GLNVG_LOC_TEX], 0);
  661. glUniform1i(gl->solidImgShader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1);
  662. glnvg__checkError("tris solid img loc");
  663. glBindVertexArray(gl->vertArr);
  664. glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
  665. glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(struct NVGvertex), verts, GL_STREAM_DRAW);
  666. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)0);
  667. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(2 * sizeof(float)));
  668. glEnableVertexAttribArray(0);
  669. glEnableVertexAttribArray(1);
  670. glnvg__toFloatColor(color, paint->innerColor);
  671. glVertexAttrib4fv(2, color);
  672. glDrawArrays(GL_TRIANGLES, 0, nverts);
  673. glDisableVertexAttribArray(0);
  674. glDisableVertexAttribArray(1);
  675. }
  676. static void glnvg__renderDelete(void* uptr)
  677. {
  678. struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
  679. int i;
  680. if (gl == NULL) return;
  681. glnvg__deleteShader(&gl->gradShader);
  682. glnvg__deleteShader(&gl->imgShader);
  683. for (i = 0; i < gl->ntextures; i++) {
  684. if (gl->textures[i].tex != 0)
  685. glDeleteTextures(1, &gl->textures[i].tex);
  686. }
  687. free(gl->textures);
  688. free(gl);
  689. }
  690. struct NVGcontext* nvgCreateGL3(int atlasw, int atlash)
  691. {
  692. struct NVGparams params;
  693. struct NVGcontext* ctx = NULL;
  694. struct GLNVGcontext* gl = (struct GLNVGcontext*)malloc(sizeof(struct GLNVGcontext));
  695. if (gl == NULL) goto error;
  696. memset(gl, 0, sizeof(struct GLNVGcontext));
  697. memset(&params, 0, sizeof(params));
  698. params.renderCreate = glnvg__renderCreate;
  699. params.renderCreateTexture = glnvg__renderCreateTexture;
  700. params.renderDeleteTexture = glnvg__renderDeleteTexture;
  701. params.renderUpdateTexture = glnvg__renderUpdateTexture;
  702. params.renderGetTextureSize = glnvg__renderGetTextureSize;
  703. params.renderViewport = glnvg__renderViewport;
  704. params.renderFill = glnvg__renderFill;
  705. params.renderStroke = glnvg__renderStroke;
  706. params.renderTriangles = glnvg__renderTriangles;
  707. params.renderDelete = glnvg__renderDelete;
  708. params.userPtr = gl;
  709. params.atlasWidth = atlasw;
  710. params.atlasHeight = atlash;
  711. ctx = nvgCreateInternal(&params);
  712. if (ctx == NULL) goto error;
  713. return ctx;
  714. error:
  715. // 'gl' is freed by nvgDeleteInternal.
  716. if (ctx != NULL) nvgDeleteInternal(ctx);
  717. return NULL;
  718. }
  719. void nvgDeleteGL3(struct NVGcontext* ctx)
  720. {
  721. nvgDeleteInternal(ctx);
  722. }
  723. #endif