mirror of
https://github.com/memononen/nanovg
synced 2026-09-27 00:28:46 +03:00
Merge pull request #312 from satoren/master
Improve nvgGlobalCompositeOperation with state
This commit is contained in:
commit
47ffd9d0b9
3 changed files with 60 additions and 22 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue