nanovg_gl2.h 28 KB

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