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.

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