Browse Source

Merge pull request #312 from satoren/master

Improve nvgGlobalCompositeOperation with state
shared-context
Mikko Mononen GitHub 8 years ago
parent
commit
47ffd9d0b9
3 changed files with 60 additions and 22 deletions
  1. +4
    -4
      src/nanovg.c
  2. +4
    -4
      src/nanovg.h
  3. +52
    -14
      src/nanovg_gl.h

+ 4
- 4
src/nanovg.c View File

@@ -390,7 +390,7 @@ void nvgCancelFrame(NVGcontext* ctx)
void nvgEndFrame(NVGcontext* ctx) void nvgEndFrame(NVGcontext* ctx)
{ {
NVGstate* state = nvg__getState(ctx); NVGstate* state = nvg__getState(ctx);
ctx->params.renderFlush(ctx->params.userPtr, state->compositeOperation);
ctx->params.renderFlush(ctx->params.userPtr);
if (ctx->fontImageIdx != 0) { if (ctx->fontImageIdx != 0) {
int fontImage = ctx->fontImages[ctx->fontImageIdx]; int fontImage = ctx->fontImages[ctx->fontImageIdx];
int i, j, iw, ih; int i, j, iw, ih;
@@ -2212,7 +2212,7 @@ void nvgFill(NVGcontext* ctx)
fillPaint.innerColor.a *= state->alpha; fillPaint.innerColor.a *= state->alpha;
fillPaint.outerColor.a *= state->alpha; fillPaint.outerColor.a *= state->alpha;


ctx->params.renderFill(ctx->params.userPtr, &fillPaint, &state->scissor, ctx->fringeWidth,
ctx->params.renderFill(ctx->params.userPtr, &fillPaint, state->compositeOperation, &state->scissor, ctx->fringeWidth,
ctx->cache->bounds, ctx->cache->paths, ctx->cache->npaths); ctx->cache->bounds, ctx->cache->paths, ctx->cache->npaths);


// Count triangles // Count triangles
@@ -2253,7 +2253,7 @@ void nvgStroke(NVGcontext* ctx)
else else
nvg__expandStroke(ctx, strokeWidth*0.5f, state->lineCap, state->lineJoin, state->miterLimit); nvg__expandStroke(ctx, strokeWidth*0.5f, state->lineCap, state->lineJoin, state->miterLimit);


ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, &state->scissor, ctx->fringeWidth,
ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, state->compositeOperation, &state->scissor, ctx->fringeWidth,
strokeWidth, ctx->cache->paths, ctx->cache->npaths); strokeWidth, ctx->cache->paths, ctx->cache->npaths);


// Count triangles // Count triangles
@@ -2401,7 +2401,7 @@ static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts)
paint.innerColor.a *= state->alpha; paint.innerColor.a *= state->alpha;
paint.outerColor.a *= state->alpha; paint.outerColor.a *= state->alpha;


ctx->params.renderTriangles(ctx->params.userPtr, &paint, &state->scissor, verts, nverts);
ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts);


ctx->drawCallCount++; ctx->drawCallCount++;
ctx->textTriCount += nverts/3; ctx->textTriCount += nverts/3;


+ 4
- 4
src/nanovg.h View File

@@ -652,10 +652,10 @@ struct NVGparams {
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h); int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio); void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio);
void (*renderCancel)(void* uptr); void (*renderCancel)(void* uptr);
void (*renderFlush)(void* uptr, NVGcompositeOperationState compositeOperation);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGscissor* scissor, const NVGvertex* verts, int nverts);
void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts);
void (*renderDelete)(void* uptr); void (*renderDelete)(void* uptr);
}; };
typedef struct NVGparams NVGparams; typedef struct NVGparams NVGparams;


+ 52
- 14
src/nanovg_gl.h View File

@@ -150,6 +150,15 @@ struct GLNVGtexture {
}; };
typedef struct GLNVGtexture GLNVGtexture; typedef struct GLNVGtexture GLNVGtexture;


struct GLNVGblend
{
GLenum srcRGB;
GLenum dstRGB;
GLenum srcAlpha;
GLenum dstAlpha;
};
typedef struct GLNVGblend GLNVGblend;

enum GLNVGcallType { enum GLNVGcallType {
GLNVG_NONE = 0, GLNVG_NONE = 0,
GLNVG_FILL, GLNVG_FILL,
@@ -166,6 +175,7 @@ struct GLNVGcall {
int triangleOffset; int triangleOffset;
int triangleCount; int triangleCount;
int uniformOffset; int uniformOffset;
GLNVGblend blendFunc;
}; };
typedef struct GLNVGcall GLNVGcall; typedef struct GLNVGcall GLNVGcall;


@@ -256,6 +266,7 @@ struct GLNVGcontext {
GLenum stencilFunc; GLenum stencilFunc;
GLint stencilFuncRef; GLint stencilFuncRef;
GLuint stencilFuncMask; GLuint stencilFuncMask;
GLNVGblend blendFunc;
#endif #endif
}; };
typedef struct GLNVGcontext GLNVGcontext; typedef struct GLNVGcontext GLNVGcontext;
@@ -316,6 +327,21 @@ static void glnvg__stencilFunc(GLNVGcontext* gl, GLenum func, GLint ref, GLuint
glStencilFunc(func, ref, mask); glStencilFunc(func, ref, mask);
#endif #endif
} }
static void glnvg__blendFuncSeparate(GLNVGcontext* gl, const GLNVGblend* blend)
{
#if NANOVG_GL_USE_STATE_FILTER
if ((gl->blendFunc.srcRGB != blend->srcRGB) ||
(gl->blendFunc.dstRGB != blend->dstRGB) ||
(gl->blendFunc.srcAlpha != blend->srcAlpha) ||
(gl->blendFunc.dstAlpha != blend->dstAlpha)) {
gl->blendFunc = *blend;
glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha);
}
#else
glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha);
#endif
}


static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl) static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl)
{ {
@@ -1116,19 +1142,24 @@ static GLenum glnvg_convertBlendFuncFactor(int factor)
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }


static void glnvg__blendCompositeOperation(NVGcompositeOperationState op)
static GLNVGblend glnvg__blendCompositeOperation(NVGcompositeOperationState op)
{ {
GLenum srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB);
GLenum dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB);
GLenum srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha);
GLenum dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha);
if (srcRGB == GL_INVALID_ENUM || dstRGB == GL_INVALID_ENUM || srcAlpha == GL_INVALID_ENUM || dstAlpha == GL_INVALID_ENUM)
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
else
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
GLNVGblend blend;
blend.srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB);
blend.dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB);
blend.srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha);
blend.dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha);
if (blend.srcRGB == GL_INVALID_ENUM || blend.dstRGB == GL_INVALID_ENUM || blend.srcAlpha == GL_INVALID_ENUM || blend.dstAlpha == GL_INVALID_ENUM)
{
blend.srcRGB = GL_ONE;
blend.dstRGB = GL_ONE_MINUS_SRC_ALPHA;
blend.srcAlpha = GL_ONE;
blend.dstAlpha = GL_ONE_MINUS_SRC_ALPHA;
}
return blend;
} }


static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeOperation)
static void glnvg__renderFlush(void* uptr)
{ {
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
int i; int i;
@@ -1138,7 +1169,6 @@ static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeO
// Setup require GL state. // Setup require GL state.
glUseProgram(gl->shader.prog); glUseProgram(gl->shader.prog);


glnvg__blendCompositeOperation(compositeOperation);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
@@ -1157,6 +1187,10 @@ static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeO
gl->stencilFunc = GL_ALWAYS; gl->stencilFunc = GL_ALWAYS;
gl->stencilFuncRef = 0; gl->stencilFuncRef = 0;
gl->stencilFuncMask = 0xffffffff; gl->stencilFuncMask = 0xffffffff;
gl->blendFunc.srcRGB = GL_INVALID_ENUM;
gl->blendFunc.srcAlpha = GL_INVALID_ENUM;
gl->blendFunc.dstRGB = GL_INVALID_ENUM;
gl->blendFunc.dstAlpha = GL_INVALID_ENUM;
#endif #endif


#if NANOVG_GL_USE_UNIFORMBUFFER #if NANOVG_GL_USE_UNIFORMBUFFER
@@ -1186,6 +1220,7 @@ static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeO


for (i = 0; i < gl->ncalls; i++) { for (i = 0; i < gl->ncalls; i++) {
GLNVGcall* call = &gl->calls[i]; GLNVGcall* call = &gl->calls[i];
glnvg__blendFuncSeparate(gl,&call->blendFunc);
if (call->type == GLNVG_FILL) if (call->type == GLNVG_FILL)
glnvg__fill(gl, call); glnvg__fill(gl, call);
else if (call->type == GLNVG_CONVEXFILL) else if (call->type == GLNVG_CONVEXFILL)
@@ -1301,7 +1336,7 @@ static void glnvg__vset(NVGvertex* vtx, float x, float y, float u, float v)
vtx->v = v; vtx->v = v;
} }


static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe,
static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe,
const float* bounds, const NVGpath* paths, int npaths) const float* bounds, const NVGpath* paths, int npaths)
{ {
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
@@ -1317,6 +1352,7 @@ static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGscissor* scissor,
if (call->pathOffset == -1) goto error; if (call->pathOffset == -1) goto error;
call->pathCount = npaths; call->pathCount = npaths;
call->image = paint->image; call->image = paint->image;
call->blendFunc = glnvg__blendCompositeOperation(compositeOperation);


if (npaths == 1 && paths[0].convex) if (npaths == 1 && paths[0].convex)
call->type = GLNVG_CONVEXFILL; call->type = GLNVG_CONVEXFILL;
@@ -1382,7 +1418,7 @@ error:
if (gl->ncalls > 0) gl->ncalls--; if (gl->ncalls > 0) gl->ncalls--;
} }


static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe,
static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe,
float strokeWidth, const NVGpath* paths, int npaths) float strokeWidth, const NVGpath* paths, int npaths)
{ {
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
@@ -1396,6 +1432,7 @@ static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGscissor* scissor
if (call->pathOffset == -1) goto error; if (call->pathOffset == -1) goto error;
call->pathCount = npaths; call->pathCount = npaths;
call->image = paint->image; call->image = paint->image;
call->blendFunc = glnvg__blendCompositeOperation(compositeOperation);


// Allocate vertices for all the paths. // Allocate vertices for all the paths.
maxverts = glnvg__maxVertCount(paths, npaths); maxverts = glnvg__maxVertCount(paths, npaths);
@@ -1437,7 +1474,7 @@ error:
if (gl->ncalls > 0) gl->ncalls--; if (gl->ncalls > 0) gl->ncalls--;
} }


static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGscissor* scissor,
static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor,
const NVGvertex* verts, int nverts) const NVGvertex* verts, int nverts)
{ {
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
@@ -1448,6 +1485,7 @@ static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGscissor* scis


call->type = GLNVG_TRIANGLES; call->type = GLNVG_TRIANGLES;
call->image = paint->image; call->image = paint->image;
call->blendFunc = glnvg__blendCompositeOperation(compositeOperation);


// Allocate vertices for all the paths. // Allocate vertices for all the paths.
call->triangleOffset = glnvg__allocVerts(gl, nverts); call->triangleOffset = glnvg__allocVerts(gl, nverts);


Loading…
Cancel
Save