nanovg_gl3.h 28 KB

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