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.

1500 lines
41KB

  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_GL_H
  19. #define NANOVG_GL_H
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. // Create flags
  24. enum NVGcreateFlags {
  25. // Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA).
  26. NVG_ANTIALIAS = 1<<0,
  27. // Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little
  28. // slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once.
  29. NVG_STENCIL_STROKES = 1<<1,
  30. // Flag indicating that additional debug checks are done.
  31. NVG_DEBUG = 1<<2,
  32. };
  33. #if defined NANOVG_GL2_IMPLEMENTATION
  34. # define NANOVG_GL2 1
  35. # define NANOVG_GL_IMPLEMENTATION 1
  36. #elif defined NANOVG_GL3_IMPLEMENTATION
  37. # define NANOVG_GL3 1
  38. # define NANOVG_GL_IMPLEMENTATION 1
  39. # define NANOVG_GL_USE_UNIFORMBUFFER 1
  40. #elif defined NANOVG_GLES2_IMPLEMENTATION
  41. # define NANOVG_GLES2 1
  42. # define NANOVG_GL_IMPLEMENTATION 1
  43. #elif defined NANOVG_GLES3_IMPLEMENTATION
  44. # define NANOVG_GLES3 1
  45. # define NANOVG_GL_IMPLEMENTATION 1
  46. #endif
  47. // Creates NanoVG contexts for different OpenGL (ES) versions.
  48. // Flags should be combination of the create flags above.
  49. #if defined NANOVG_GL2
  50. NVGcontext* nvgCreateGL2(int flags);
  51. void nvgDeleteGL2(NVGcontext* ctx);
  52. #endif
  53. #if defined NANOVG_GL3
  54. NVGcontext* nvgCreateGL3(int flags);
  55. void nvgDeleteGL3(NVGcontext* ctx);
  56. #endif
  57. #if defined NANOVG_GLES2
  58. NVGcontext* nvgCreateGLES2(int flags);
  59. void nvgDeleteGLES2(NVGcontext* ctx);
  60. #endif
  61. #if defined NANOVG_GLES3
  62. NVGcontext* nvgCreateGLES3(int flags);
  63. void nvgDeleteGLES3(NVGcontext* ctx);
  64. #endif
  65. // These are additional flags on top of NVGimageFlags.
  66. enum NVGimageFlagsGL {
  67. NVG_IMAGE_NODELETE = 1<<16, // Do not delete GL texture handle.
  68. };
  69. int nvglCreateImageFromHandle(NVGcontext* ctx, GLuint textureId, int w, int h, int flags);
  70. GLuint nvglImageHandle(NVGcontext* ctx, int image);
  71. #ifdef __cplusplus
  72. }
  73. #endif
  74. #endif /* NANOVG_GL_H */
  75. #ifdef NANOVG_GL_IMPLEMENTATION
  76. #include <stdlib.h>
  77. #include <stdio.h>
  78. #include <string.h>
  79. #include <math.h>
  80. #include "nanovg.h"
  81. enum GLNVGuniformLoc {
  82. GLNVG_LOC_VIEWSIZE,
  83. GLNVG_LOC_TEX,
  84. #if NANOVG_GL_USE_UNIFORMBUFFER
  85. GLNVG_LOC_FRAG,
  86. #else
  87. GLNVG_LOC_SCISSORMAT,
  88. GLNVG_LOC_SCISSOREXT,
  89. GLNVG_LOC_SCISSORSCALE,
  90. GLNVG_LOC_PAINTMAT,
  91. GLNVG_LOC_EXTENT,
  92. GLNVG_LOC_RADIUS,
  93. GLNVG_LOC_FEATHER,
  94. GLNVG_LOC_INNERCOL,
  95. GLNVG_LOC_OUTERCOL,
  96. GLNVG_LOC_STROKEMULT,
  97. GLNVG_LOC_STROKETHR,
  98. GLNVG_LOC_TEXTYPE,
  99. GLNVG_LOC_TYPE,
  100. #endif
  101. GLNVG_MAX_LOCS
  102. };
  103. enum GLNVGshaderType {
  104. NSVG_SHADER_FILLGRAD,
  105. NSVG_SHADER_FILLIMG,
  106. NSVG_SHADER_SIMPLE,
  107. NSVG_SHADER_IMG
  108. };
  109. #if NANOVG_GL_USE_UNIFORMBUFFER
  110. enum GLNVGuniformBindings {
  111. GLNVG_FRAG_BINDING = 0,
  112. };
  113. #endif
  114. struct GLNVGshader {
  115. GLuint prog;
  116. GLuint frag;
  117. GLuint vert;
  118. GLint loc[GLNVG_MAX_LOCS];
  119. };
  120. typedef struct GLNVGshader GLNVGshader;
  121. struct GLNVGtexture {
  122. int id;
  123. GLuint tex;
  124. int width, height;
  125. int type;
  126. int flags;
  127. };
  128. typedef struct GLNVGtexture GLNVGtexture;
  129. enum GLNVGcallType {
  130. GLNVG_NONE = 0,
  131. GLNVG_FILL,
  132. GLNVG_CONVEXFILL,
  133. GLNVG_STROKE,
  134. GLNVG_TRIANGLES,
  135. };
  136. struct GLNVGcall {
  137. int type;
  138. int image;
  139. int pathOffset;
  140. int pathCount;
  141. int triangleOffset;
  142. int triangleCount;
  143. int uniformOffset;
  144. };
  145. typedef struct GLNVGcall GLNVGcall;
  146. struct GLNVGpath {
  147. int fillOffset;
  148. int fillCount;
  149. int strokeOffset;
  150. int strokeCount;
  151. };
  152. typedef struct GLNVGpath GLNVGpath;
  153. struct GLNVGfragUniforms {
  154. float scissorMat[12]; // matrices are actually 3 vec4s
  155. float paintMat[12];
  156. struct NVGcolor innerCol;
  157. struct NVGcolor outerCol;
  158. float scissorExt[2];
  159. float scissorScale[2];
  160. float extent[2];
  161. float radius;
  162. float feather;
  163. float strokeMult;
  164. float strokeThr;
  165. int texType;
  166. int type;
  167. };
  168. typedef struct GLNVGfragUniforms GLNVGfragUniforms;
  169. struct GLNVGcontext {
  170. GLNVGshader shader;
  171. GLNVGtexture* textures;
  172. float view[2];
  173. int ntextures;
  174. int ctextures;
  175. int textureId;
  176. GLuint vertBuf;
  177. #if defined NANOVG_GL3
  178. GLuint vertArr;
  179. #endif
  180. #if NANOVG_GL_USE_UNIFORMBUFFER
  181. GLuint fragBuf;
  182. #endif
  183. int fragSize;
  184. int flags;
  185. // Per frame buffers
  186. GLNVGcall* calls;
  187. int ccalls;
  188. int ncalls;
  189. GLNVGpath* paths;
  190. int cpaths;
  191. int npaths;
  192. struct NVGvertex* verts;
  193. int cverts;
  194. int nverts;
  195. unsigned char* uniforms;
  196. int cuniforms;
  197. int nuniforms;
  198. };
  199. typedef struct GLNVGcontext GLNVGcontext;
  200. static int glnvg__maxi(int a, int b) { return a > b ? a : b; }
  201. #ifdef NANOVG_GLES2
  202. static unsigned int glnvg__nearestPow2(unsigned int num)
  203. {
  204. unsigned n = num > 0 ? num - 1 : 0;
  205. n |= n >> 1;
  206. n |= n >> 2;
  207. n |= n >> 4;
  208. n |= n >> 8;
  209. n |= n >> 16;
  210. n++;
  211. return n;
  212. }
  213. #endif
  214. static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl)
  215. {
  216. GLNVGtexture* tex = NULL;
  217. int i;
  218. for (i = 0; i < gl->ntextures; i++) {
  219. if (gl->textures[i].id == 0) {
  220. tex = &gl->textures[i];
  221. break;
  222. }
  223. }
  224. if (tex == NULL) {
  225. if (gl->ntextures+1 > gl->ctextures) {
  226. GLNVGtexture* textures;
  227. int ctextures = glnvg__maxi(gl->ntextures+1, 4) + gl->ctextures/2; // 1.5x Overallocate
  228. textures = (GLNVGtexture*)realloc(gl->textures, sizeof(GLNVGtexture)*ctextures);
  229. if (textures == NULL) return NULL;
  230. gl->textures = textures;
  231. gl->ctextures = ctextures;
  232. }
  233. tex = &gl->textures[gl->ntextures++];
  234. }
  235. memset(tex, 0, sizeof(*tex));
  236. tex->id = ++gl->textureId;
  237. return tex;
  238. }
  239. static GLNVGtexture* glnvg__findTexture(GLNVGcontext* gl, int id)
  240. {
  241. int i;
  242. for (i = 0; i < gl->ntextures; i++)
  243. if (gl->textures[i].id == id)
  244. return &gl->textures[i];
  245. return NULL;
  246. }
  247. static int glnvg__deleteTexture(GLNVGcontext* gl, int id)
  248. {
  249. int i;
  250. for (i = 0; i < gl->ntextures; i++) {
  251. if (gl->textures[i].id == id) {
  252. if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVG_IMAGE_NODELETE) == 0)
  253. glDeleteTextures(1, &gl->textures[i].tex);
  254. memset(&gl->textures[i], 0, sizeof(gl->textures[i]));
  255. return 1;
  256. }
  257. }
  258. return 0;
  259. }
  260. static void glnvg__dumpShaderError(GLuint shader, const char* name, const char* type)
  261. {
  262. char str[512+1];
  263. int len = 0;
  264. glGetShaderInfoLog(shader, 512, &len, str);
  265. if (len > 512) len = 512;
  266. str[len] = '\0';
  267. printf("Shader %s/%s error:\n%s\n", name, type, str);
  268. }
  269. static void glnvg__dumpProgramError(GLuint prog, const char* name)
  270. {
  271. char str[512+1];
  272. int len = 0;
  273. glGetProgramInfoLog(prog, 512, &len, str);
  274. if (len > 512) len = 512;
  275. str[len] = '\0';
  276. printf("Program %s error:\n%s\n", name, str);
  277. }
  278. static void glnvg__checkError(GLNVGcontext* gl, const char* str)
  279. {
  280. GLenum err;
  281. if ((gl->flags & NVG_DEBUG) == 0) return;
  282. err = glGetError();
  283. if (err != GL_NO_ERROR) {
  284. printf("Error %08x after %s\n", err, str);
  285. return;
  286. }
  287. }
  288. static int glnvg__createShader(GLNVGshader* shader, const char* name, const char* header, const char* opts, const char* vshader, const char* fshader)
  289. {
  290. GLint status;
  291. GLuint prog, vert, frag;
  292. const char* str[3];
  293. str[0] = header;
  294. str[1] = opts != NULL ? opts : "";
  295. memset(shader, 0, sizeof(*shader));
  296. prog = glCreateProgram();
  297. vert = glCreateShader(GL_VERTEX_SHADER);
  298. frag = glCreateShader(GL_FRAGMENT_SHADER);
  299. str[2] = vshader;
  300. glShaderSource(vert, 3, str, 0);
  301. str[2] = fshader;
  302. glShaderSource(frag, 3, str, 0);
  303. glCompileShader(vert);
  304. glGetShaderiv(vert, GL_COMPILE_STATUS, &status);
  305. if (status != GL_TRUE) {
  306. glnvg__dumpShaderError(vert, name, "vert");
  307. return 0;
  308. }
  309. glCompileShader(frag);
  310. glGetShaderiv(frag, GL_COMPILE_STATUS, &status);
  311. if (status != GL_TRUE) {
  312. glnvg__dumpShaderError(frag, name, "frag");
  313. return 0;
  314. }
  315. glAttachShader(prog, vert);
  316. glAttachShader(prog, frag);
  317. glBindAttribLocation(prog, 0, "vertex");
  318. glBindAttribLocation(prog, 1, "tcoord");
  319. glLinkProgram(prog);
  320. glGetProgramiv(prog, GL_LINK_STATUS, &status);
  321. if (status != GL_TRUE) {
  322. glnvg__dumpProgramError(prog, name);
  323. return 0;
  324. }
  325. shader->prog = prog;
  326. shader->vert = vert;
  327. shader->frag = frag;
  328. return 1;
  329. }
  330. static void glnvg__deleteShader(GLNVGshader* shader)
  331. {
  332. if (shader->prog != 0)
  333. glDeleteProgram(shader->prog);
  334. if (shader->vert != 0)
  335. glDeleteShader(shader->vert);
  336. if (shader->frag != 0)
  337. glDeleteShader(shader->frag);
  338. }
  339. static void glnvg__getUniforms(GLNVGshader* shader)
  340. {
  341. shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize");
  342. shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex");
  343. #if NANOVG_GL_USE_UNIFORMBUFFER
  344. shader->loc[GLNVG_LOC_FRAG] = glGetUniformBlockIndex(shader->prog, "frag");
  345. #else
  346. shader->loc[GLNVG_LOC_SCISSORMAT] = glGetUniformLocation(shader->prog, "scissorMat");
  347. shader->loc[GLNVG_LOC_SCISSOREXT] = glGetUniformLocation(shader->prog, "scissorExt");
  348. shader->loc[GLNVG_LOC_SCISSORSCALE] = glGetUniformLocation(shader->prog, "scissorScale");
  349. shader->loc[GLNVG_LOC_PAINTMAT] = glGetUniformLocation(shader->prog, "paintMat");
  350. shader->loc[GLNVG_LOC_EXTENT] = glGetUniformLocation(shader->prog, "extent");
  351. shader->loc[GLNVG_LOC_RADIUS] = glGetUniformLocation(shader->prog, "radius");
  352. shader->loc[GLNVG_LOC_FEATHER] = glGetUniformLocation(shader->prog, "feather");
  353. shader->loc[GLNVG_LOC_INNERCOL] = glGetUniformLocation(shader->prog, "innerCol");
  354. shader->loc[GLNVG_LOC_OUTERCOL] = glGetUniformLocation(shader->prog, "outerCol");
  355. shader->loc[GLNVG_LOC_STROKEMULT] = glGetUniformLocation(shader->prog, "strokeMult");
  356. shader->loc[GLNVG_LOC_STROKETHR] = glGetUniformLocation(shader->prog, "strokeThr");
  357. shader->loc[GLNVG_LOC_TEXTYPE] = glGetUniformLocation(shader->prog, "texType");
  358. shader->loc[GLNVG_LOC_TYPE] = glGetUniformLocation(shader->prog, "type");
  359. #endif
  360. }
  361. static int glnvg__renderCreate(void* uptr)
  362. {
  363. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  364. int align = 4;
  365. // TODO: mediump float may not be enough for GLES2 in iOS.
  366. // see the following discussion: https://github.com/memononen/nanovg/issues/46
  367. static const char* shaderHeader =
  368. #if defined NANOVG_GL2
  369. "#define NANOVG_GL2 1\n";
  370. #elif defined NANOVG_GL3
  371. "#version 150 core\n"
  372. #if NANOVG_GL_USE_UNIFORMBUFFER
  373. "#define USE_UNIFORMBUFFER 1\n"
  374. #endif
  375. "#define NANOVG_GL3 1\n";
  376. #elif defined NANOVG_GLES2
  377. "#version 100\n"
  378. "#define NANOVG_GL2 1\n";
  379. #elif defined NANOVG_GLES3
  380. "#version 300 es\n"
  381. "#define NANOVG_GL3 1\n";
  382. #endif
  383. static const char* fillVertShader =
  384. "#ifdef NANOVG_GL3\n"
  385. " uniform vec2 viewSize;\n"
  386. " in vec2 vertex;\n"
  387. " in vec2 tcoord;\n"
  388. " out vec2 ftcoord;\n"
  389. " out vec2 fpos;\n"
  390. "#else\n"
  391. " uniform vec2 viewSize;\n"
  392. " attribute vec2 vertex;\n"
  393. " attribute vec2 tcoord;\n"
  394. " varying vec2 ftcoord;\n"
  395. " varying vec2 fpos;\n"
  396. "#endif\n"
  397. "void main(void) {\n"
  398. " ftcoord = tcoord;\n"
  399. " fpos = vertex;\n"
  400. " gl_Position = vec4(2.0*vertex.x/viewSize.x - 1.0, 1.0 - 2.0*vertex.y/viewSize.y, 0, 1);\n"
  401. "}\n";
  402. static const char* fillFragShader =
  403. "#ifdef GL_ES\n"
  404. "#if defined(GL_FRAGMENT_PRECISION_HIGH) || defined(NANOVG_GL3)\n"
  405. " precision highp float;\n"
  406. "#else\n"
  407. " precision mediump float;\n"
  408. "#endif\n"
  409. "#endif\n"
  410. "#ifdef NANOVG_GL3\n"
  411. "#ifdef USE_UNIFORMBUFFER\n"
  412. " layout(std140) uniform frag {\n"
  413. " mat3 scissorMat;\n"
  414. " mat3 paintMat;\n"
  415. " vec4 innerCol;\n"
  416. " vec4 outerCol;\n"
  417. " vec2 scissorExt;\n"
  418. " vec2 scissorScale;\n"
  419. " vec2 extent;\n"
  420. " float radius;\n"
  421. " float feather;\n"
  422. " float strokeMult;\n"
  423. " float strokeThr;\n"
  424. " int texType;\n"
  425. " int type;\n"
  426. " };\n"
  427. "#else\n"
  428. " uniform mat3 scissorMat;\n"
  429. " uniform mat3 paintMat;\n"
  430. " uniform vec4 innerCol;\n"
  431. " uniform vec4 outerCol;\n"
  432. " uniform vec2 scissorExt;\n"
  433. " uniform vec2 scissorScale;\n"
  434. " uniform vec2 extent;\n"
  435. " uniform float radius;\n"
  436. " uniform float feather;\n"
  437. " uniform float strokeMult;\n"
  438. " uniform float strokeThr;\n"
  439. " uniform int texType;\n"
  440. " uniform int type;\n"
  441. "#endif\n"
  442. " uniform sampler2D tex;\n"
  443. " in vec2 ftcoord;\n"
  444. " in vec2 fpos;\n"
  445. " out vec4 outColor;\n"
  446. "#else\n"
  447. " uniform mat3 scissorMat;\n"
  448. " uniform mat3 paintMat;\n"
  449. " uniform vec4 innerCol;\n"
  450. " uniform vec4 outerCol;\n"
  451. " uniform vec2 scissorExt;\n"
  452. " uniform vec2 scissorScale;\n"
  453. " uniform vec2 extent;\n"
  454. " uniform float radius;\n"
  455. " uniform float feather;\n"
  456. " uniform float strokeMult;\n"
  457. " uniform float strokeThr;\n"
  458. " uniform int texType;\n"
  459. " uniform int type;\n"
  460. " uniform sampler2D tex;\n"
  461. " varying vec2 ftcoord;\n"
  462. " varying vec2 fpos;\n"
  463. "#endif\n"
  464. "\n"
  465. "float sdroundrect(vec2 pt, vec2 ext, float rad) {\n"
  466. " vec2 ext2 = ext - vec2(rad,rad);\n"
  467. " vec2 d = abs(pt) - ext2;\n"
  468. " return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n"
  469. "}\n"
  470. "\n"
  471. "// Scissoring\n"
  472. "float scissorMask(vec2 p) {\n"
  473. " vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n"
  474. " sc = vec2(0.5,0.5) - sc * scissorScale;\n"
  475. " return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
  476. "}\n"
  477. "#ifdef EDGE_AA\n"
  478. "// Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n"
  479. "float strokeMask() {\n"
  480. " return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * min(1.0, ftcoord.y);\n"
  481. "}\n"
  482. "#endif\n"
  483. "\n"
  484. "void main(void) {\n"
  485. " vec4 result;\n"
  486. " float scissor = scissorMask(fpos);\n"
  487. "#ifdef EDGE_AA\n"
  488. " float strokeAlpha = strokeMask();\n"
  489. "#else\n"
  490. " float strokeAlpha = 1.0;\n"
  491. "#endif\n"
  492. " if (type == 0) { // Gradient\n"
  493. " // Calculate gradient color using box gradient\n"
  494. " vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
  495. " float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
  496. " vec4 color = mix(innerCol,outerCol,d);\n"
  497. " // Combine alpha\n"
  498. " color *= strokeAlpha * scissor;\n"
  499. " result = color;\n"
  500. " } else if (type == 1) { // Image\n"
  501. " // Calculate color fron texture\n"
  502. " vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n"
  503. "#ifdef NANOVG_GL3\n"
  504. " vec4 color = texture(tex, pt);\n"
  505. "#else\n"
  506. " vec4 color = texture2D(tex, pt);\n"
  507. "#endif\n"
  508. " if (texType == 1) color = vec4(color.xyz*color.w,color.w);"
  509. " if (texType == 2) color = vec4(color.x);"
  510. " // Apply color tint and alpha.\n"
  511. " color *= innerCol;\n"
  512. " // Combine alpha\n"
  513. " color *= strokeAlpha * scissor;\n"
  514. " result = color;\n"
  515. " } else if (type == 2) { // Stencil fill\n"
  516. " result = vec4(1,1,1,1);\n"
  517. " } else if (type == 3) { // Textured tris\n"
  518. "#ifdef NANOVG_GL3\n"
  519. " vec4 color = texture(tex, ftcoord);\n"
  520. "#else\n"
  521. " vec4 color = texture2D(tex, ftcoord);\n"
  522. "#endif\n"
  523. " if (texType == 1) color = vec4(color.xyz*color.w,color.w);"
  524. " if (texType == 2) color = vec4(color.x);"
  525. " color *= scissor;\n"
  526. " result = color * innerCol;\n"
  527. " }\n"
  528. "#ifdef EDGE_AA\n"
  529. " if (strokeAlpha < strokeThr) discard;\n"
  530. "#endif\n"
  531. "#ifdef NANOVG_GL3\n"
  532. " outColor = result;\n"
  533. "#else\n"
  534. " gl_FragColor = result;\n"
  535. "#endif\n"
  536. "}\n";
  537. glnvg__checkError(gl, "init");
  538. if (gl->flags & NVG_ANTIALIAS) {
  539. if (glnvg__createShader(&gl->shader, "shader", shaderHeader, "#define EDGE_AA 1\n", fillVertShader, fillFragShader) == 0)
  540. return 0;
  541. } else {
  542. if (glnvg__createShader(&gl->shader, "shader", shaderHeader, NULL, fillVertShader, fillFragShader) == 0)
  543. return 0;
  544. }
  545. glnvg__checkError(gl, "uniform locations");
  546. glnvg__getUniforms(&gl->shader);
  547. // Create dynamic vertex array
  548. #if defined NANOVG_GL3
  549. glGenVertexArrays(1, &gl->vertArr);
  550. #endif
  551. glGenBuffers(1, &gl->vertBuf);
  552. #if NANOVG_GL_USE_UNIFORMBUFFER
  553. // Create UBOs
  554. glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_FRAG], GLNVG_FRAG_BINDING);
  555. glGenBuffers(1, &gl->fragBuf);
  556. glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &align);
  557. #endif
  558. gl->fragSize = sizeof(GLNVGfragUniforms) + align - sizeof(GLNVGfragUniforms) % align;
  559. glnvg__checkError(gl, "create done");
  560. glFinish();
  561. return 1;
  562. }
  563. static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data)
  564. {
  565. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  566. GLNVGtexture* tex = glnvg__allocTexture(gl);
  567. if (tex == NULL) return 0;
  568. #ifdef NANOVG_GLES2
  569. // Check for non-power of 2.
  570. if (glnvg__nearestPow2(w) != (unsigned int)w || glnvg__nearestPow2(h) != (unsigned int)h) {
  571. // No repeat
  572. if ((imageFlags & NVG_IMAGE_REPEATX) != 0 || (imageFlags & NVG_IMAGE_REPEATY) != 0) {
  573. printf("Repeat X/Y is not supported for non power-of-two textures (%d x %d)\n", w, h);
  574. imageFlags &= ~(NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
  575. }
  576. // No mips.
  577. if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
  578. printf("Mip-maps is not support for non power-of-two textures (%d x %d)\n", w, h);
  579. imageFlags &= ~NVG_IMAGE_GENERATE_MIPMAPS;
  580. }
  581. }
  582. #endif
  583. glGenTextures(1, &tex->tex);
  584. tex->width = w;
  585. tex->height = h;
  586. tex->type = type;
  587. tex->flags = imageFlags;
  588. glBindTexture(GL_TEXTURE_2D, tex->tex);
  589. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  590. #ifndef NANOVG_GLES2
  591. glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
  592. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  593. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  594. #endif
  595. #if defined (NANOVG_GL2)
  596. // GL 1.4 and later has support for generating mipmaps using a tex parameter.
  597. if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
  598. glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  599. }
  600. #endif
  601. if (type == NVG_TEXTURE_RGBA)
  602. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  603. else
  604. #if defined(NANOVG_GLES2)
  605. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
  606. #elif defined(NANOVG_GLES3)
  607. glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
  608. #else
  609. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
  610. #endif
  611. if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
  612. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  613. } else {
  614. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  615. }
  616. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  617. if (imageFlags & NVG_IMAGE_REPEATX)
  618. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  619. else
  620. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  621. if (imageFlags & NVG_IMAGE_REPEATY)
  622. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  623. else
  624. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  625. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  626. #ifndef NANOVG_GLES2
  627. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  628. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  629. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  630. #endif
  631. // The new way to build mipmaps on GLES and GL3
  632. #if !defined(NANOVG_GL2)
  633. if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
  634. glGenerateMipmap(GL_TEXTURE_2D);
  635. }
  636. #endif
  637. glnvg__checkError(gl, "create tex");
  638. glBindTexture(GL_TEXTURE_2D, 0);
  639. return tex->id;
  640. }
  641. static int glnvg__renderDeleteTexture(void* uptr, int image)
  642. {
  643. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  644. return glnvg__deleteTexture(gl, image);
  645. }
  646. static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data)
  647. {
  648. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  649. GLNVGtexture* tex = glnvg__findTexture(gl, image);
  650. if (tex == NULL) return 0;
  651. glBindTexture(GL_TEXTURE_2D, tex->tex);
  652. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  653. #ifndef NANOVG_GLES2
  654. glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
  655. glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
  656. glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
  657. #else
  658. // No support for all of skip, need to update a whole row at a time.
  659. if (tex->type == NVG_TEXTURE_RGBA)
  660. data += y*tex->width*4;
  661. else
  662. data += y*tex->width;
  663. x = 0;
  664. w = tex->width;
  665. #endif
  666. if (tex->type == NVG_TEXTURE_RGBA)
  667. glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data);
  668. else
  669. #ifdef NANOVG_GLES2
  670. glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
  671. #else
  672. glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data);
  673. #endif
  674. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  675. #ifndef NANOVG_GLES2
  676. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  677. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  678. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  679. #endif
  680. glBindTexture(GL_TEXTURE_2D, 0);
  681. return 1;
  682. }
  683. static int glnvg__renderGetTextureSize(void* uptr, int image, int* w, int* h)
  684. {
  685. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  686. GLNVGtexture* tex = glnvg__findTexture(gl, image);
  687. if (tex == NULL) return 0;
  688. *w = tex->width;
  689. *h = tex->height;
  690. return 1;
  691. }
  692. static void glnvg__xformToMat3x4(float* m3, float* t)
  693. {
  694. m3[0] = t[0];
  695. m3[1] = t[1];
  696. m3[2] = 0.0f;
  697. m3[3] = 0.0f;
  698. m3[4] = t[2];
  699. m3[5] = t[3];
  700. m3[6] = 0.0f;
  701. m3[7] = 0.0f;
  702. m3[8] = t[4];
  703. m3[9] = t[5];
  704. m3[10] = 1.0f;
  705. m3[11] = 0.0f;
  706. }
  707. static NVGcolor glnvg__premulColor(NVGcolor c)
  708. {
  709. c.r *= c.a;
  710. c.g *= c.a;
  711. c.b *= c.a;
  712. return c;
  713. }
  714. static int glnvg__convertPaint(GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGpaint* paint,
  715. NVGscissor* scissor, float width, float fringe, float strokeThr)
  716. {
  717. GLNVGtexture* tex = NULL;
  718. float invxform[6];
  719. memset(frag, 0, sizeof(*frag));
  720. frag->innerCol = glnvg__premulColor(paint->innerColor);
  721. frag->outerCol = glnvg__premulColor(paint->outerColor);
  722. if (scissor->extent[0] < -0.5f || scissor->extent[1] < -0.5f) {
  723. memset(frag->scissorMat, 0, sizeof(frag->scissorMat));
  724. frag->scissorExt[0] = 1.0f;
  725. frag->scissorExt[1] = 1.0f;
  726. frag->scissorScale[0] = 1.0f;
  727. frag->scissorScale[1] = 1.0f;
  728. } else {
  729. nvgTransformInverse(invxform, scissor->xform);
  730. glnvg__xformToMat3x4(frag->scissorMat, invxform);
  731. frag->scissorExt[0] = scissor->extent[0];
  732. frag->scissorExt[1] = scissor->extent[1];
  733. frag->scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe;
  734. frag->scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe;
  735. }
  736. memcpy(frag->extent, paint->extent, sizeof(frag->extent));
  737. frag->strokeMult = (width*0.5f + fringe*0.5f) / fringe;
  738. frag->strokeThr = strokeThr;
  739. if (paint->image != 0) {
  740. tex = glnvg__findTexture(gl, paint->image);
  741. if (tex == NULL) return 0;
  742. if ((tex->flags & NVG_IMAGE_FLIPY) != 0) {
  743. float flipped[6];
  744. nvgTransformScale(flipped, 1.0f, -1.0f);
  745. nvgTransformMultiply(flipped, paint->xform);
  746. nvgTransformInverse(invxform, flipped);
  747. } else {
  748. nvgTransformInverse(invxform, paint->xform);
  749. }
  750. frag->type = NSVG_SHADER_FILLIMG;
  751. if (tex->type == NVG_TEXTURE_RGBA)
  752. frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1;
  753. else
  754. frag->texType = 2;
  755. // printf("frag->texType = %d\n", frag->texType);
  756. } else {
  757. frag->type = NSVG_SHADER_FILLGRAD;
  758. frag->radius = paint->radius;
  759. frag->feather = paint->feather;
  760. nvgTransformInverse(invxform, paint->xform);
  761. }
  762. glnvg__xformToMat3x4(frag->paintMat, invxform);
  763. return 1;
  764. }
  765. static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i);
  766. #if !NANOVG_GL_USE_UNIFORMBUFFER
  767. static void glnvg__mat3(float* dst, float* src)
  768. {
  769. dst[0] = src[0];
  770. dst[1] = src[1];
  771. dst[2] = src[2];
  772. dst[3] = src[4];
  773. dst[4] = src[5];
  774. dst[5] = src[6];
  775. dst[6] = src[8];
  776. dst[7] = src[9];
  777. dst[8] = src[10];
  778. }
  779. #endif
  780. static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)
  781. {
  782. #if NANOVG_GL_USE_UNIFORMBUFFER
  783. glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_FRAG_BINDING, gl->fragBuf, uniformOffset, sizeof(GLNVGfragUniforms));
  784. #else
  785. GLNVGfragUniforms* frag = nvg__fragUniformPtr(gl, uniformOffset);
  786. float tmp[9]; // Maybe there's a way to get rid of this...
  787. glnvg__mat3(tmp, frag->scissorMat);
  788. glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, tmp);
  789. glnvg__mat3(tmp, frag->paintMat);
  790. glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, tmp);
  791. glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, frag->innerCol.rgba);
  792. glUniform4fv(gl->shader.loc[GLNVG_LOC_OUTERCOL], 1, frag->outerCol.rgba);
  793. glUniform2fv(gl->shader.loc[GLNVG_LOC_SCISSOREXT], 1, frag->scissorExt);
  794. glUniform2fv(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], 1, frag->scissorScale);
  795. glUniform2fv(gl->shader.loc[GLNVG_LOC_EXTENT], 1, frag->extent);
  796. glUniform1f(gl->shader.loc[GLNVG_LOC_RADIUS], frag->radius);
  797. glUniform1f(gl->shader.loc[GLNVG_LOC_FEATHER], frag->feather);
  798. glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], frag->strokeMult);
  799. glUniform1f(gl->shader.loc[GLNVG_LOC_STROKETHR], frag->strokeThr);
  800. glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], frag->texType);
  801. glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], frag->type);
  802. #endif
  803. if (image != 0) {
  804. GLNVGtexture* tex = glnvg__findTexture(gl, image);
  805. glBindTexture(GL_TEXTURE_2D, tex != NULL ? tex->tex : 0);
  806. glnvg__checkError(gl, "tex paint tex");
  807. } else {
  808. glBindTexture(GL_TEXTURE_2D, 0);
  809. }
  810. }
  811. static void glnvg__renderViewport(void* uptr, int width, int height)
  812. {
  813. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  814. gl->view[0] = (float)width;
  815. gl->view[1] = (float)height;
  816. }
  817. static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)
  818. {
  819. GLNVGpath* paths = &gl->paths[call->pathOffset];
  820. int i, npaths = call->pathCount;
  821. // Draw shapes
  822. glEnable(GL_STENCIL_TEST);
  823. glStencilMask(0xff);
  824. glStencilFunc(GL_ALWAYS, 0, 0xff);
  825. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  826. // set bindpoint for solid loc
  827. glnvg__setUniforms(gl, call->uniformOffset, 0);
  828. glnvg__checkError(gl, "fill simple");
  829. glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
  830. glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
  831. glDisable(GL_CULL_FACE);
  832. for (i = 0; i < npaths; i++)
  833. glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
  834. glEnable(GL_CULL_FACE);
  835. // Draw anti-aliased pixels
  836. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  837. glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image);
  838. glnvg__checkError(gl, "fill fill");
  839. if (gl->flags & NVG_ANTIALIAS) {
  840. glStencilFunc(GL_EQUAL, 0x00, 0xff);
  841. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  842. // Draw fringes
  843. for (i = 0; i < npaths; i++)
  844. glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
  845. }
  846. // Draw fill
  847. glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
  848. glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
  849. glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);
  850. glDisable(GL_STENCIL_TEST);
  851. }
  852. static void glnvg__convexFill(GLNVGcontext* gl, GLNVGcall* call)
  853. {
  854. GLNVGpath* paths = &gl->paths[call->pathOffset];
  855. int i, npaths = call->pathCount;
  856. glnvg__setUniforms(gl, call->uniformOffset, call->image);
  857. glnvg__checkError(gl, "convex fill");
  858. for (i = 0; i < npaths; i++)
  859. glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
  860. if (gl->flags & NVG_ANTIALIAS) {
  861. // Draw fringes
  862. for (i = 0; i < npaths; i++)
  863. glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
  864. }
  865. }
  866. static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call)
  867. {
  868. GLNVGpath* paths = &gl->paths[call->pathOffset];
  869. int npaths = call->pathCount, i;
  870. if (gl->flags & NVG_STENCIL_STROKES) {
  871. glEnable(GL_STENCIL_TEST);
  872. glStencilMask(0xff);
  873. // Fill the stroke base without overlap
  874. glStencilFunc(GL_EQUAL, 0x0, 0xff);
  875. glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  876. glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image);
  877. glnvg__checkError(gl, "stroke fill 0");
  878. for (i = 0; i < npaths; i++)
  879. glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
  880. // Draw anti-aliased pixels.
  881. glnvg__setUniforms(gl, call->uniformOffset, call->image);
  882. glStencilFunc(GL_EQUAL, 0x00, 0xff);
  883. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  884. for (i = 0; i < npaths; i++)
  885. glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
  886. // Clear stencil buffer.
  887. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  888. glStencilFunc(GL_ALWAYS, 0x0, 0xff);
  889. glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
  890. glnvg__checkError(gl, "stroke fill 1");
  891. for (i = 0; i < npaths; i++)
  892. glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
  893. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  894. glDisable(GL_STENCIL_TEST);
  895. // glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f);
  896. } else {
  897. glnvg__setUniforms(gl, call->uniformOffset, call->image);
  898. glnvg__checkError(gl, "stroke fill");
  899. // Draw Strokes
  900. for (i = 0; i < npaths; i++)
  901. glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
  902. }
  903. }
  904. static void glnvg__triangles(GLNVGcontext* gl, GLNVGcall* call)
  905. {
  906. glnvg__setUniforms(gl, call->uniformOffset, call->image);
  907. glnvg__checkError(gl, "triangles fill");
  908. glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);
  909. }
  910. static void glnvg__renderFlush(void* uptr)
  911. {
  912. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  913. int i;
  914. if (gl->ncalls > 0) {
  915. // Setup require GL state.
  916. glUseProgram(gl->shader.prog);
  917. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  918. glEnable(GL_CULL_FACE);
  919. glCullFace(GL_BACK);
  920. glFrontFace(GL_CCW);
  921. glEnable(GL_BLEND);
  922. glDisable(GL_DEPTH_TEST);
  923. glDisable(GL_SCISSOR_TEST);
  924. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  925. glStencilMask(0xffffffff);
  926. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  927. glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
  928. glActiveTexture(GL_TEXTURE0);
  929. #if NANOVG_GL_USE_UNIFORMBUFFER
  930. // Upload ubo for frag shaders
  931. glBindBuffer(GL_UNIFORM_BUFFER, gl->fragBuf);
  932. glBufferData(GL_UNIFORM_BUFFER, gl->nuniforms * gl->fragSize, gl->uniforms, GL_STREAM_DRAW);
  933. #endif
  934. // Upload vertex data
  935. #if defined NANOVG_GL3
  936. glBindVertexArray(gl->vertArr);
  937. #endif
  938. glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
  939. glBufferData(GL_ARRAY_BUFFER, gl->nverts * sizeof(NVGvertex), gl->verts, GL_STREAM_DRAW);
  940. glEnableVertexAttribArray(0);
  941. glEnableVertexAttribArray(1);
  942. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(NVGvertex), (const GLvoid*)(size_t)0);
  943. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(NVGvertex), (const GLvoid*)(0 + 2*sizeof(float)));
  944. // Set view and texture just once per frame.
  945. glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0);
  946. glUniform2fv(gl->shader.loc[GLNVG_LOC_VIEWSIZE], 1, gl->view);
  947. #if NANOVG_GL_USE_UNIFORMBUFFER
  948. glBindBuffer(GL_UNIFORM_BUFFER, gl->fragBuf);
  949. #endif
  950. for (i = 0; i < gl->ncalls; i++) {
  951. GLNVGcall* call = &gl->calls[i];
  952. if (call->type == GLNVG_FILL)
  953. glnvg__fill(gl, call);
  954. else if (call->type == GLNVG_CONVEXFILL)
  955. glnvg__convexFill(gl, call);
  956. else if (call->type == GLNVG_STROKE)
  957. glnvg__stroke(gl, call);
  958. else if (call->type == GLNVG_TRIANGLES)
  959. glnvg__triangles(gl, call);
  960. }
  961. glDisableVertexAttribArray(0);
  962. glDisableVertexAttribArray(1);
  963. #if defined NANOVG_GL3
  964. glBindVertexArray(0);
  965. #endif
  966. glDisable(GL_CULL_FACE);
  967. glBindBuffer(GL_ARRAY_BUFFER, 0);
  968. glUseProgram(0);
  969. glBindTexture(GL_TEXTURE_2D, 0);
  970. }
  971. // Reset calls
  972. gl->nverts = 0;
  973. gl->npaths = 0;
  974. gl->ncalls = 0;
  975. gl->nuniforms = 0;
  976. }
  977. static int glnvg__maxVertCount(const NVGpath* paths, int npaths)
  978. {
  979. int i, count = 0;
  980. for (i = 0; i < npaths; i++) {
  981. count += paths[i].nfill;
  982. count += paths[i].nstroke;
  983. }
  984. return count;
  985. }
  986. static GLNVGcall* glnvg__allocCall(GLNVGcontext* gl)
  987. {
  988. GLNVGcall* ret = NULL;
  989. if (gl->ncalls+1 > gl->ccalls) {
  990. GLNVGcall* calls;
  991. int ccalls = glnvg__maxi(gl->ncalls+1, 128) + gl->ccalls/2; // 1.5x Overallocate
  992. calls = (GLNVGcall*)realloc(gl->calls, sizeof(GLNVGcall) * ccalls);
  993. if (calls == NULL) return NULL;
  994. gl->calls = calls;
  995. gl->ccalls = ccalls;
  996. }
  997. ret = &gl->calls[gl->ncalls++];
  998. memset(ret, 0, sizeof(GLNVGcall));
  999. return ret;
  1000. }
  1001. static int glnvg__allocPaths(GLNVGcontext* gl, int n)
  1002. {
  1003. int ret = 0;
  1004. if (gl->npaths+n > gl->cpaths) {
  1005. GLNVGpath* paths;
  1006. int cpaths = glnvg__maxi(gl->npaths + n, 128) + gl->cpaths/2; // 1.5x Overallocate
  1007. paths = (GLNVGpath*)realloc(gl->paths, sizeof(GLNVGpath) * cpaths);
  1008. if (paths == NULL) return -1;
  1009. gl->paths = paths;
  1010. gl->cpaths = cpaths;
  1011. }
  1012. ret = gl->npaths;
  1013. gl->npaths += n;
  1014. return ret;
  1015. }
  1016. static int glnvg__allocVerts(GLNVGcontext* gl, int n)
  1017. {
  1018. int ret = 0;
  1019. if (gl->nverts+n > gl->cverts) {
  1020. NVGvertex* verts;
  1021. int cverts = glnvg__maxi(gl->nverts + n, 4096) + gl->cverts/2; // 1.5x Overallocate
  1022. verts = (NVGvertex*)realloc(gl->verts, sizeof(NVGvertex) * cverts);
  1023. if (verts == NULL) return -1;
  1024. gl->verts = verts;
  1025. gl->cverts = cverts;
  1026. }
  1027. ret = gl->nverts;
  1028. gl->nverts += n;
  1029. return ret;
  1030. }
  1031. static int glnvg__allocFragUniforms(GLNVGcontext* gl, int n)
  1032. {
  1033. int ret = 0, structSize = gl->fragSize;
  1034. if (gl->nuniforms+n > gl->cuniforms) {
  1035. unsigned char* uniforms;
  1036. int cuniforms = glnvg__maxi(gl->nuniforms+n, 128) + gl->cuniforms/2; // 1.5x Overallocate
  1037. uniforms = (unsigned char*)realloc(gl->uniforms, structSize * cuniforms);
  1038. if (uniforms == NULL) return -1;
  1039. gl->uniforms = uniforms;
  1040. gl->cuniforms = cuniforms;
  1041. }
  1042. ret = gl->nuniforms * structSize;
  1043. gl->nuniforms += n;
  1044. return ret;
  1045. }
  1046. static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i)
  1047. {
  1048. return (GLNVGfragUniforms*)&gl->uniforms[i];
  1049. }
  1050. static void glnvg__vset(NVGvertex* vtx, float x, float y, float u, float v)
  1051. {
  1052. vtx->x = x;
  1053. vtx->y = y;
  1054. vtx->u = u;
  1055. vtx->v = v;
  1056. }
  1057. static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe,
  1058. const float* bounds, const NVGpath* paths, int npaths)
  1059. {
  1060. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  1061. GLNVGcall* call = glnvg__allocCall(gl);
  1062. NVGvertex* quad;
  1063. GLNVGfragUniforms* frag;
  1064. int i, maxverts, offset;
  1065. if (call == NULL) return;
  1066. call->type = GLNVG_FILL;
  1067. call->pathOffset = glnvg__allocPaths(gl, npaths);
  1068. if (call->pathOffset == -1) goto error;
  1069. call->pathCount = npaths;
  1070. call->image = paint->image;
  1071. if (npaths == 1 && paths[0].convex)
  1072. call->type = GLNVG_CONVEXFILL;
  1073. // Allocate vertices for all the paths.
  1074. maxverts = glnvg__maxVertCount(paths, npaths) + 6;
  1075. offset = glnvg__allocVerts(gl, maxverts);
  1076. if (offset == -1) goto error;
  1077. for (i = 0; i < npaths; i++) {
  1078. GLNVGpath* copy = &gl->paths[call->pathOffset + i];
  1079. const NVGpath* path = &paths[i];
  1080. memset(copy, 0, sizeof(GLNVGpath));
  1081. if (path->nfill > 0) {
  1082. copy->fillOffset = offset;
  1083. copy->fillCount = path->nfill;
  1084. memcpy(&gl->verts[offset], path->fill, sizeof(NVGvertex) * path->nfill);
  1085. offset += path->nfill;
  1086. }
  1087. if (path->nstroke > 0) {
  1088. copy->strokeOffset = offset;
  1089. copy->strokeCount = path->nstroke;
  1090. memcpy(&gl->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke);
  1091. offset += path->nstroke;
  1092. }
  1093. }
  1094. // Quad
  1095. call->triangleOffset = offset;
  1096. call->triangleCount = 6;
  1097. quad = &gl->verts[call->triangleOffset];
  1098. glnvg__vset(&quad[0], bounds[0], bounds[3], 0.5f, 1.0f);
  1099. glnvg__vset(&quad[1], bounds[2], bounds[3], 0.5f, 1.0f);
  1100. glnvg__vset(&quad[2], bounds[2], bounds[1], 0.5f, 1.0f);
  1101. glnvg__vset(&quad[3], bounds[0], bounds[3], 0.5f, 1.0f);
  1102. glnvg__vset(&quad[4], bounds[2], bounds[1], 0.5f, 1.0f);
  1103. glnvg__vset(&quad[5], bounds[0], bounds[1], 0.5f, 1.0f);
  1104. // Setup uniforms for draw calls
  1105. if (call->type == GLNVG_FILL) {
  1106. call->uniformOffset = glnvg__allocFragUniforms(gl, 2);
  1107. if (call->uniformOffset == -1) goto error;
  1108. // Simple shader for stencil
  1109. frag = nvg__fragUniformPtr(gl, call->uniformOffset);
  1110. memset(frag, 0, sizeof(*frag));
  1111. frag->strokeThr = -1.0f;
  1112. frag->type = NSVG_SHADER_SIMPLE;
  1113. // Fill shader
  1114. glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, fringe, fringe, -1.0f);
  1115. } else {
  1116. call->uniformOffset = glnvg__allocFragUniforms(gl, 1);
  1117. if (call->uniformOffset == -1) goto error;
  1118. // Fill shader
  1119. glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, fringe, fringe, -1.0f);
  1120. }
  1121. return;
  1122. error:
  1123. // We get here if call alloc was ok, but something else is not.
  1124. // Roll back the last call to prevent drawing it.
  1125. if (gl->ncalls > 0) gl->ncalls--;
  1126. }
  1127. static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe,
  1128. float strokeWidth, const NVGpath* paths, int npaths)
  1129. {
  1130. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  1131. GLNVGcall* call = glnvg__allocCall(gl);
  1132. int i, maxverts, offset;
  1133. if (call == NULL) return;
  1134. call->type = GLNVG_STROKE;
  1135. call->pathOffset = glnvg__allocPaths(gl, npaths);
  1136. if (call->pathOffset == -1) goto error;
  1137. call->pathCount = npaths;
  1138. call->image = paint->image;
  1139. // Allocate vertices for all the paths.
  1140. maxverts = glnvg__maxVertCount(paths, npaths);
  1141. offset = glnvg__allocVerts(gl, maxverts);
  1142. if (offset == -1) goto error;
  1143. for (i = 0; i < npaths; i++) {
  1144. GLNVGpath* copy = &gl->paths[call->pathOffset + i];
  1145. const NVGpath* path = &paths[i];
  1146. memset(copy, 0, sizeof(GLNVGpath));
  1147. if (path->nstroke) {
  1148. copy->strokeOffset = offset;
  1149. copy->strokeCount = path->nstroke;
  1150. memcpy(&gl->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke);
  1151. offset += path->nstroke;
  1152. }
  1153. }
  1154. if (gl->flags & NVG_STENCIL_STROKES) {
  1155. // Fill shader
  1156. call->uniformOffset = glnvg__allocFragUniforms(gl, 2);
  1157. if (call->uniformOffset == -1) goto error;
  1158. glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f);
  1159. glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f);
  1160. } else {
  1161. // Fill shader
  1162. call->uniformOffset = glnvg__allocFragUniforms(gl, 1);
  1163. if (call->uniformOffset == -1) goto error;
  1164. glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f);
  1165. }
  1166. return;
  1167. error:
  1168. // We get here if call alloc was ok, but something else is not.
  1169. // Roll back the last call to prevent drawing it.
  1170. if (gl->ncalls > 0) gl->ncalls--;
  1171. }
  1172. static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGscissor* scissor,
  1173. const NVGvertex* verts, int nverts)
  1174. {
  1175. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  1176. GLNVGcall* call = glnvg__allocCall(gl);
  1177. GLNVGfragUniforms* frag;
  1178. if (call == NULL) return;
  1179. call->type = GLNVG_TRIANGLES;
  1180. call->image = paint->image;
  1181. // Allocate vertices for all the paths.
  1182. call->triangleOffset = glnvg__allocVerts(gl, nverts);
  1183. if (call->triangleOffset == -1) goto error;
  1184. call->triangleCount = nverts;
  1185. memcpy(&gl->verts[call->triangleOffset], verts, sizeof(NVGvertex) * nverts);
  1186. // Fill shader
  1187. call->uniformOffset = glnvg__allocFragUniforms(gl, 1);
  1188. if (call->uniformOffset == -1) goto error;
  1189. frag = nvg__fragUniformPtr(gl, call->uniformOffset);
  1190. glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, 1.0f, -1.0f);
  1191. frag->type = NSVG_SHADER_IMG;
  1192. return;
  1193. error:
  1194. // We get here if call alloc was ok, but something else is not.
  1195. // Roll back the last call to prevent drawing it.
  1196. if (gl->ncalls > 0) gl->ncalls--;
  1197. }
  1198. static void glnvg__renderDelete(void* uptr)
  1199. {
  1200. GLNVGcontext* gl = (GLNVGcontext*)uptr;
  1201. int i;
  1202. if (gl == NULL) return;
  1203. glnvg__deleteShader(&gl->shader);
  1204. #if NANOVG_GL3
  1205. #if NANOVG_GL_USE_UNIFORMBUFFER
  1206. if (gl->fragBuf != 0)
  1207. glDeleteBuffers(1, &gl->fragBuf);
  1208. #endif
  1209. if (gl->vertArr != 0)
  1210. glDeleteVertexArrays(1, &gl->vertArr);
  1211. #endif
  1212. if (gl->vertBuf != 0)
  1213. glDeleteBuffers(1, &gl->vertBuf);
  1214. for (i = 0; i < gl->ntextures; i++) {
  1215. if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVG_IMAGE_NODELETE) == 0)
  1216. glDeleteTextures(1, &gl->textures[i].tex);
  1217. }
  1218. free(gl->textures);
  1219. free(gl->paths);
  1220. free(gl->verts);
  1221. free(gl->uniforms);
  1222. free(gl->calls);
  1223. free(gl);
  1224. }
  1225. #if defined NANOVG_GL2
  1226. NVGcontext* nvgCreateGL2(int flags)
  1227. #elif defined NANOVG_GL3
  1228. NVGcontext* nvgCreateGL3(int flags)
  1229. #elif defined NANOVG_GLES2
  1230. NVGcontext* nvgCreateGLES2(int flags)
  1231. #elif defined NANOVG_GLES3
  1232. NVGcontext* nvgCreateGLES3(int flags)
  1233. #endif
  1234. {
  1235. NVGparams params;
  1236. NVGcontext* ctx = NULL;
  1237. GLNVGcontext* gl = (GLNVGcontext*)malloc(sizeof(GLNVGcontext));
  1238. if (gl == NULL) goto error;
  1239. memset(gl, 0, sizeof(GLNVGcontext));
  1240. memset(&params, 0, sizeof(params));
  1241. params.renderCreate = glnvg__renderCreate;
  1242. params.renderCreateTexture = glnvg__renderCreateTexture;
  1243. params.renderDeleteTexture = glnvg__renderDeleteTexture;
  1244. params.renderUpdateTexture = glnvg__renderUpdateTexture;
  1245. params.renderGetTextureSize = glnvg__renderGetTextureSize;
  1246. params.renderViewport = glnvg__renderViewport;
  1247. params.renderFlush = glnvg__renderFlush;
  1248. params.renderFill = glnvg__renderFill;
  1249. params.renderStroke = glnvg__renderStroke;
  1250. params.renderTriangles = glnvg__renderTriangles;
  1251. params.renderDelete = glnvg__renderDelete;
  1252. params.userPtr = gl;
  1253. params.edgeAntiAlias = flags & NVG_ANTIALIAS ? 1 : 0;
  1254. gl->flags = flags;
  1255. ctx = nvgCreateInternal(&params);
  1256. if (ctx == NULL) goto error;
  1257. return ctx;
  1258. error:
  1259. // 'gl' is freed by nvgDeleteInternal.
  1260. if (ctx != NULL) nvgDeleteInternal(ctx);
  1261. return NULL;
  1262. }
  1263. #if NANOVG_GL2
  1264. void nvgDeleteGL2(NVGcontext* ctx)
  1265. #elif NANOVG_GL3
  1266. void nvgDeleteGL3(NVGcontext* ctx)
  1267. #elif NANOVG_GLES2
  1268. void nvgDeleteGLES2(NVGcontext* ctx)
  1269. #elif NANOVG_GLES3
  1270. void nvgDeleteGLES3(NVGcontext* ctx)
  1271. #endif
  1272. {
  1273. nvgDeleteInternal(ctx);
  1274. }
  1275. int nvglCreateImageFromHandle(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags)
  1276. {
  1277. GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr;
  1278. GLNVGtexture* tex = glnvg__allocTexture(gl);
  1279. if (tex == NULL) return 0;
  1280. tex->type = NVG_TEXTURE_RGBA;
  1281. tex->tex = textureId;
  1282. tex->flags = imageFlags;
  1283. tex->width = w;
  1284. tex->height = h;
  1285. return tex->id;
  1286. }
  1287. GLuint nvglImageHandle(NVGcontext* ctx, int image)
  1288. {
  1289. GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr;
  1290. GLNVGtexture* tex = glnvg__findTexture(gl, image);
  1291. return tex->tex;
  1292. }
  1293. #endif /* NANOVG_GL_IMPLEMENTATION */