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