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
#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.
@@ -231,6 +232,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;

@@ -250,6 +260,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;
@@ -661,7 +712,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
@@ -720,8 +771,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;
}
@@ -739,7 +789,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);

@@ -773,7 +823,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;
}
@@ -917,10 +967,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);
}
}

@@ -938,8 +988,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
@@ -960,7 +1010,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++)
@@ -968,7 +1018,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);

@@ -1000,10 +1050,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");
@@ -1012,14 +1062,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++)
@@ -1069,6 +1119,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
@@ -1115,7 +1173,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…
Cancel
Save