DPF OpenGL examples
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.

1312 lines
37KB

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