Browse Source

Don't set redundant GL state (glBindTexture, glStencilFunc, glStencilMask)

shared-context
Andre Weissflog 10 years ago
parent
commit
4aadf46465
1 changed files with 74 additions and 16 deletions
  1. +74
    -16
      src/nanovg_gl.h

+ 74
- 16
src/nanovg_gl.h View File

@@ -49,6 +49,7 @@ enum NVGcreateFlags {
# define NANOVG_GL_IMPLEMENTATION 1 # define NANOVG_GL_IMPLEMENTATION 1
#endif #endif


#define NANOVG_GL_USE_STATE_FILTER (1)


// Creates NanoVG contexts for different OpenGL (ES) versions. // Creates NanoVG contexts for different OpenGL (ES) versions.
// Flags should be combination of the create flags above. // Flags should be combination of the create flags above.
@@ -231,6 +232,15 @@ struct GLNVGcontext {
unsigned char* uniforms; unsigned char* uniforms;
int cuniforms; int cuniforms;
int nuniforms; 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; typedef struct GLNVGcontext GLNVGcontext;


@@ -250,6 +260,47 @@ static unsigned int glnvg__nearestPow2(unsigned int num)
} }
#endif #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) static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl)
{ {
GLNVGtexture* tex = NULL; GLNVGtexture* tex = NULL;
@@ -661,7 +712,7 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im
tex->height = h; tex->height = h;
tex->type = type; tex->type = type;
tex->flags = imageFlags; tex->flags = imageFlags;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glnvg__bindTexture(gl, tex->tex);


glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_UNPACK_ALIGNMENT,1);
#ifndef NANOVG_GLES2 #ifndef NANOVG_GLES2
@@ -720,8 +771,7 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im
#endif #endif


glnvg__checkError(gl, "create tex"); glnvg__checkError(gl, "create tex");

glBindTexture(GL_TEXTURE_2D, 0);
glnvg__bindTexture(gl, 0);


return tex->id; return tex->id;
} }
@@ -739,7 +789,7 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w
GLNVGtexture* tex = glnvg__findTexture(gl, image); GLNVGtexture* tex = glnvg__findTexture(gl, image);


if (tex == NULL) return 0; if (tex == NULL) return 0;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glnvg__bindTexture(gl, tex->tex);


glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_UNPACK_ALIGNMENT,1);


@@ -773,7 +823,7 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
#endif #endif


glBindTexture(GL_TEXTURE_2D, 0);
glnvg__bindTexture(gl, 0);


return 1; return 1;
} }
@@ -917,10 +967,10 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)


if (image != 0) { if (image != 0) {
GLNVGtexture* tex = glnvg__findTexture(gl, image); 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"); glnvg__checkError(gl, "tex paint tex");
} else { } else {
glBindTexture(GL_TEXTURE_2D, 0);
glnvg__bindTexture(gl, 0);
} }
} }


@@ -938,8 +988,8 @@ static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)


// Draw shapes // Draw shapes
glEnable(GL_STENCIL_TEST); 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); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);


// set bindpoint for solid loc // set bindpoint for solid loc
@@ -960,7 +1010,7 @@ static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)
glnvg__checkError(gl, "fill fill"); glnvg__checkError(gl, "fill fill");


if (gl->flags & NVG_ANTIALIAS) { if (gl->flags & NVG_ANTIALIAS) {
glStencilFunc(GL_EQUAL, 0x00, 0xff);
glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw fringes // Draw fringes
for (i = 0; i < npaths; i++) for (i = 0; i < npaths; i++)
@@ -968,7 +1018,7 @@ static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call)
} }


// Draw fill // Draw fill
glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x0, 0xff);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount); glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);


@@ -1000,10 +1050,10 @@ static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call)
if (gl->flags & NVG_STENCIL_STROKES) { if (gl->flags & NVG_STENCIL_STROKES) {


glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glStencilMask(0xff);
glnvg__stencilMask(gl, 0xff);


// Fill the stroke base without overlap // 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); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image); glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image);
glnvg__checkError(gl, "stroke fill 0"); glnvg__checkError(gl, "stroke fill 0");
@@ -1012,14 +1062,14 @@ static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call)


// Draw anti-aliased pixels. // Draw anti-aliased pixels.
glnvg__setUniforms(gl, call->uniformOffset, call->image); 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); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
for (i = 0; i < npaths; i++) for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);


// Clear stencil buffer. // Clear stencil buffer.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 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); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glnvg__checkError(gl, "stroke fill 1"); glnvg__checkError(gl, "stroke fill 1");
for (i = 0; i < npaths; i++) for (i = 0; i < npaths; i++)
@@ -1069,6 +1119,14 @@ static void glnvg__renderFlush(void* uptr)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xffffffff); glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
glActiveTexture(GL_TEXTURE0); 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 #if NANOVG_GL_USE_UNIFORMBUFFER
// Upload ubo for frag shaders // Upload ubo for frag shaders
@@ -1115,7 +1173,7 @@ static void glnvg__renderFlush(void* uptr)
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0); glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
glnvg__bindTexture(gl, 0);
} }


// Reset calls // Reset calls


Loading…
Cancel
Save