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.

935 lines
27KB

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