diff --git a/src/nanovg.c b/src/nanovg.c index 675fa47..6c8e73c 100644 --- a/src/nanovg.c +++ b/src/nanovg.c @@ -390,7 +390,7 @@ void nvgCancelFrame(NVGcontext* ctx) void nvgEndFrame(NVGcontext* ctx) { NVGstate* state = nvg__getState(ctx); - ctx->params.renderFlush(ctx->params.userPtr, state->compositeOperation); + ctx->params.renderFlush(ctx->params.userPtr); if (ctx->fontImageIdx != 0) { int fontImage = ctx->fontImages[ctx->fontImageIdx]; int i, j, iw, ih; @@ -2212,7 +2212,7 @@ void nvgFill(NVGcontext* ctx) fillPaint.innerColor.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); // Count triangles @@ -2253,7 +2253,7 @@ void nvgStroke(NVGcontext* ctx) else 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); // Count triangles @@ -2401,7 +2401,7 @@ static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts) paint.innerColor.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->textTriCount += nverts/3; diff --git a/src/nanovg.h b/src/nanovg.h index 3e16bec..bd63381 100644 --- a/src/nanovg.h +++ b/src/nanovg.h @@ -652,10 +652,10 @@ struct NVGparams { int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h); void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio); 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); }; typedef struct NVGparams NVGparams; diff --git a/src/nanovg_gl.h b/src/nanovg_gl.h index 651aff8..25f9d80 100644 --- a/src/nanovg_gl.h +++ b/src/nanovg_gl.h @@ -150,6 +150,15 @@ struct GLNVGtexture { }; typedef struct GLNVGtexture GLNVGtexture; +struct GLNVGblend +{ + GLenum srcRGB; + GLenum dstRGB; + GLenum srcAlpha; + GLenum dstAlpha; +}; +typedef struct GLNVGblend GLNVGblend; + enum GLNVGcallType { GLNVG_NONE = 0, GLNVG_FILL, @@ -166,6 +175,7 @@ struct GLNVGcall { int triangleOffset; int triangleCount; int uniformOffset; + GLNVGblend blendFunc; }; typedef struct GLNVGcall GLNVGcall; @@ -256,6 +266,7 @@ struct GLNVGcontext { GLenum stencilFunc; GLint stencilFuncRef; GLuint stencilFuncMask; + GLNVGblend blendFunc; #endif }; typedef struct GLNVGcontext GLNVGcontext; @@ -316,6 +327,21 @@ static void glnvg__stencilFunc(GLNVGcontext* gl, GLenum func, GLint ref, GLuint glStencilFunc(func, ref, mask); #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) { @@ -1116,19 +1142,24 @@ static GLenum glnvg_convertBlendFuncFactor(int factor) 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; int i; @@ -1138,7 +1169,6 @@ static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeO // Setup require GL state. glUseProgram(gl->shader.prog); - glnvg__blendCompositeOperation(compositeOperation); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CCW); @@ -1157,6 +1187,10 @@ static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeO gl->stencilFunc = GL_ALWAYS; gl->stencilFuncRef = 0; 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 #if NANOVG_GL_USE_UNIFORMBUFFER @@ -1186,6 +1220,7 @@ static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeO for (i = 0; i < gl->ncalls; i++) { GLNVGcall* call = &gl->calls[i]; + glnvg__blendFuncSeparate(gl,&call->blendFunc); if (call->type == GLNVG_FILL) glnvg__fill(gl, call); 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; } -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) { GLNVGcontext* gl = (GLNVGcontext*)uptr; @@ -1317,6 +1352,7 @@ static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGscissor* scissor, if (call->pathOffset == -1) goto error; call->pathCount = npaths; call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); if (npaths == 1 && paths[0].convex) call->type = GLNVG_CONVEXFILL; @@ -1382,7 +1418,7 @@ error: 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) { GLNVGcontext* gl = (GLNVGcontext*)uptr; @@ -1396,6 +1432,7 @@ static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGscissor* scissor if (call->pathOffset == -1) goto error; call->pathCount = npaths; call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); // Allocate vertices for all the paths. maxverts = glnvg__maxVertCount(paths, npaths); @@ -1437,7 +1474,7 @@ error: 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) { GLNVGcontext* gl = (GLNVGcontext*)uptr; @@ -1448,6 +1485,7 @@ static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGscissor* scis call->type = GLNVG_TRIANGLES; call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); // Allocate vertices for all the paths. call->triangleOffset = glnvg__allocVerts(gl, nverts);