Merge pull request #312 from satoren/master

Improve nvgGlobalCompositeOperation with state
This commit is contained in:
Mikko Mononen 2017-02-23 11:42:38 +02:00 • committed by GitHub
commit 47ffd9d0b9
3 changed files with 60 additions and 22 deletions

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;

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 (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths); 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, NVGscissor* scissor, float fringe, float strokeWidth, 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, NVGscissor* scissor, const NVGvertex* verts, int nverts); 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;

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); GLNVGblend blend;
GLenum dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB); blend.srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB);
GLenum srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha); blend.dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB);
GLenum dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha); blend.srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha);
if (srcRGB == GL_INVALID_ENUM || dstRGB == GL_INVALID_ENUM || srcAlpha == GL_INVALID_ENUM || dstAlpha == GL_INVALID_ENUM) blend.dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); if (blend.srcRGB == GL_INVALID_ENUM || blend.dstRGB == GL_INVALID_ENUM || blend.srcAlpha == GL_INVALID_ENUM || blend.dstAlpha == GL_INVALID_ENUM)
else {
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); 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);