mirror of
https://github.com/memononen/nanovg
synced 2026-09-26 16:19:07 +03:00
Merge pull request #165 from floooh/pr_redundant_state_filter
Redundant GL state filter
This commit is contained in:
commit
8b849004d4
1 changed files with 74 additions and 16 deletions
|
|
@ -49,6 +49,7 @@ enum NVGcreateFlags {
|
|||
# define NANOVG_GL_IMPLEMENTATION 1
|
||||
#endif
|
||||
|
||||
#define NANOVG_GL_USE_STATE_FILTER (1)
|
||||
|
||||
// Creates NanoVG contexts for different OpenGL (ES) versions.
|
||||
// Flags should be combination of the create flags above.
|
||||
|
|
@ -239,6 +240,15 @@ struct GLNVGcontext {
|
|||
unsigned char* uniforms;
|
||||
int cuniforms;
|
||||
int nuniforms;
|
||||
|
||||
// cached state
|
||||
#if NANOVG_GL_USE_STATE_FILTER
|
||||
GLuint boundTexture;
|
||||
GLuint stencilMask;
|
||||
GLenum stencilFunc;
|
||||
GLint stencilFuncRef;
|
||||
GLuint stencilFuncMask;
|
||||
#endif
|
||||
};
|
||||
typedef struct GLNVGcontext GLNVGcontext;
|
||||
|
||||
|
|
@ -258,6 +268,47 @@ static unsigned int glnvg__nearestPow2(unsigned int num)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void glnvg__bindTexture(GLNVGcontext* gl, GLuint tex)
|
||||
{
|
||||
#if NANOVG_GL_USE_STATE_FILTER
|
||||
if (gl->boundTexture != tex) {
|
||||
gl->boundTexture = tex;
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
}
|
||||
#else
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void glnvg__stencilMask(GLNVGcontext* gl, GLuint mask)
|
||||
{
|
||||
#if NANOVG_GL_USE_STATE_FILTER
|
||||
if (gl->stencilMask != mask) {
|
||||
gl->stencilMask = mask;
|
||||
glStencilMask(mask);
|
||||
}
|
||||
#else
|
||||
glStencilMask(mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void glnvg__stencilFunc(GLNVGcontext* gl, GLenum func, GLint ref, GLuint mask)
|
||||
{
|
||||
#if NANOVG_GL_USE_STATE_FILTER
|
||||
if ((gl->stencilFunc != func) ||
|
||||
(gl->stencilFuncRef != ref) ||
|
||||
(gl->stencilFuncMask != mask)) {
|
||||
|
||||
gl->stencilFunc = func;
|
||||
gl->stencilFuncRef = ref;
|
||||
gl->stencilFuncMask = mask;
|
||||
glStencilFunc(func, ref, mask);
|
||||
}
|
||||
#else
|
||||
glStencilFunc(func, ref, mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl)
|
||||
{
|
||||
GLNVGtexture* tex = NULL;
|
||||
|
|
@ -652,7 +703,7 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im
|
|||
tex->height = h;
|
||||
tex->type = type;
|
||||
tex->flags = imageFlags;
|
||||
glBindTexture(GL_TEXTURE_2D, tex->tex);
|
||||
glnvg__bindTexture(gl, tex->tex);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
||||
#ifndef NANOVG_GLES2
|
||||
|
|
@ -711,8 +762,7 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im
|
|||
#endif
|
||||
|
||||
glnvg__checkError(gl, "create tex");
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glnvg__bindTexture(gl, 0);
|
||||
|
||||
return tex->id;
|
||||
}
|
||||
|
|
@ -730,7 +780,7 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w
|
|||
GLNVGtexture* tex = glnvg__findTexture(gl, image);
|
||||
|
||||
if (tex == NULL) return 0;
|
||||
glBindTexture(GL_TEXTURE_2D, tex->tex);
|
||||
glnvg__bindTexture(gl, tex->tex);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
||||
|
||||
|
|
@ -764,7 +814,7 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w
|
|||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
#endif
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glnvg__bindTexture(gl, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -876,10 +926,10 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)
|
|||
|
||||
if (image != 0) {
|
||||
GLNVGtexture* tex = glnvg__findTexture(gl, image);
|
||||
glBindTexture(GL_TEXTURE_2D, tex != NULL ? tex->tex : 0);
|
||||
glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0);
|
||||
glnvg__checkError(gl, "tex paint tex");
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glnvg__bindTexture(gl, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -897,8 +947,8 @@ static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)
|
|||
|
||||
// Draw shapes
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMask(0xff);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0xff);
|
||||
glnvg__stencilMask(gl, 0xff);
|
||||
glnvg__stencilFunc(gl, GL_ALWAYS, 0, 0xff);
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
// set bindpoint for solid loc
|
||||
|
|
@ -919,7 +969,7 @@ static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)
|
|||
glnvg__checkError(gl, "fill fill");
|
||||
|
||||
if (gl->flags & NVG_ANTIALIAS) {
|
||||
glStencilFunc(GL_EQUAL, 0x00, 0xff);
|
||||
glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
// Draw fringes
|
||||
for (i = 0; i < npaths; i++)
|
||||
|
|
@ -927,7 +977,7 @@ static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)
|
|||
}
|
||||
|
||||
// Draw fill
|
||||
glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
|
||||
glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x0, 0xff);
|
||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);
|
||||
|
||||
|
|
@ -959,10 +1009,10 @@ static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call)
|
|||
if (gl->flags & NVG_STENCIL_STROKES) {
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMask(0xff);
|
||||
glnvg__stencilMask(gl, 0xff);
|
||||
|
||||
// Fill the stroke base without overlap
|
||||
glStencilFunc(GL_EQUAL, 0x0, 0xff);
|
||||
glnvg__stencilFunc(gl, GL_EQUAL, 0x0, 0xff);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image);
|
||||
glnvg__checkError(gl, "stroke fill 0");
|
||||
|
|
@ -971,14 +1021,14 @@ static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call)
|
|||
|
||||
// Draw anti-aliased pixels.
|
||||
glnvg__setUniforms(gl, call->uniformOffset, call->image);
|
||||
glStencilFunc(GL_EQUAL, 0x00, 0xff);
|
||||
glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
for (i = 0; i < npaths; i++)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
|
||||
|
||||
// Clear stencil buffer.
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glStencilFunc(GL_ALWAYS, 0x0, 0xff);
|
||||
glnvg__stencilFunc(gl, GL_ALWAYS, 0x0, 0xff);
|
||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
glnvg__checkError(gl, "stroke fill 1");
|
||||
for (i = 0; i < npaths; i++)
|
||||
|
|
@ -1036,6 +1086,14 @@ static void glnvg__renderFlush(void* uptr)
|
|||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
#if NANOVG_GL_USE_STATE_FILTER
|
||||
gl->boundTexture = 0;
|
||||
gl->stencilMask = 0xffffffff;
|
||||
gl->stencilFunc = GL_ALWAYS;
|
||||
gl->stencilFuncRef = 0;
|
||||
gl->stencilFuncMask = 0xffffffff;
|
||||
#endif
|
||||
|
||||
#if NANOVG_GL_USE_UNIFORMBUFFER
|
||||
// Upload ubo for frag shaders
|
||||
|
|
@ -1082,7 +1140,7 @@ static void glnvg__renderFlush(void* uptr)
|
|||
glDisable(GL_CULL_FACE);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glnvg__bindTexture(gl, 0);
|
||||
}
|
||||
|
||||
// Reset calls
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue