Browse Source

Merge pull request #165 from floooh/pr_redundant_state_filter

Redundant GL state filter
shared-context
Mikko Mononen 10 years ago
parent
commit
8b849004d4
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.
@@ -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…
Cancel
Save