Browse Source

Improve nvgGlobalCompositeOperation with state

shared-context
satoren 8 years ago
parent
commit
339c5e507b
7 changed files with 122 additions and 22 deletions
  1. +60
    -0
      example/demo.c
  2. +2
    -0
      example/demo.h
  3. BIN
      example/images/composite_a.png
  4. BIN
      example/images/composite_b.png
  5. +4
    -4
      src/nanovg.c
  6. +4
    -4
      src/nanovg.h
  7. +52
    -14
      src/nanovg_gl.h

+ 60
- 0
example/demo.c View File

@@ -818,6 +818,9 @@ int loadDemoData(NVGcontext* vg, DemoData* data)
return -1;
}
}
data->image_composite_a = nvgCreateImage(vg, "../example/images/composite_a.png", 0);
data->image_composite_b = nvgCreateImage(vg, "../example/images/composite_b.png", 0);

data->fontIcons = nvgCreateFont(vg, "icons", "../example/entypo.ttf");
if (data->fontIcons == -1) {
@@ -854,6 +857,9 @@ void freeDemoData(NVGcontext* vg, DemoData* data)

for (i = 0; i < 12; i++)
nvgDeleteImage(vg, data->images[i]);
nvgDeleteImage(vg, data->image_composite_a);
nvgDeleteImage(vg, data->image_composite_b);
}

void drawParagraph(NVGcontext* vg, float x, float y, float width, float height, float mx, float my)
@@ -1060,6 +1066,58 @@ void drawScissor(NVGcontext* vg, float x, float y, float t)
nvgRestore(vg);
}


void drawGlobalCompositeOperation(NVGcontext* vg, float x, float y, DemoData* data)
{
int i;
NVGpaint imgPaint;
enum NVGcompositeOperation ops[] = {
NVG_SOURCE_OVER,
NVG_SOURCE_IN,
NVG_SOURCE_OUT,
NVG_ATOP,
NVG_DESTINATION_OVER,
NVG_DESTINATION_IN,
NVG_DESTINATION_OUT,
NVG_DESTINATION_ATOP,
NVG_LIGHTER,
NVG_COPY,
NVG_XOR};
int count = sizeof(ops)/sizeof(ops[0]);

for(i=0;i<count;++i)
{
nvgSave(vg);
nvgTranslate(vg, x + i * 40, y);
nvgGlobalCompositeOperation(vg, NVG_COPY);
imgPaint = nvgImagePattern(vg, 0, 0, 30,30, 0.0f/180.0f*NVG_PI, data->image_composite_a, 1.0);
nvgBeginPath(vg);
nvgRect(vg, 0, 0, 30, 30);
nvgFillPaint(vg, imgPaint);
nvgFill(vg);
nvgGlobalCompositeOperation(vg, ops[i]);
imgPaint = nvgImagePattern(vg, 0, 0, 30,30, 0.0f/180.0f*NVG_PI, data->image_composite_b, 1.0);
nvgBeginPath(vg);
nvgRect(vg, 0, 0, 30, 30);
nvgFillPaint(vg, imgPaint);
nvgFill(vg);
//fill background transparent color to white.
nvgGlobalCompositeOperation(vg, NVG_DESTINATION_OVER);
nvgBeginPath(vg);
nvgRect(vg, 0, 0, 30, 30);
nvgFillColor(vg, nvgRGBA(255,255,255,255));
nvgFill(vg);
nvgRestore(vg);
}
}

void renderDemo(NVGcontext* vg, float mx, float my, float width, float height,
float t, int blowup, DemoData* data)
{
@@ -1080,6 +1138,8 @@ void renderDemo(NVGcontext* vg, float mx, float my, float width, float height,
drawCaps(vg, 10, 300, 30);

drawScissor(vg, 50, height-80, t);
drawGlobalCompositeOperation(vg, 100, height-35, data);

nvgSave(vg);
if (blowup) {


+ 2
- 0
example/demo.h View File

@@ -10,6 +10,8 @@ extern "C" {
struct DemoData {
int fontNormal, fontBold, fontIcons, fontEmoji;
int images[12];
int image_composite_a;
int image_composite_b;
};
typedef struct DemoData DemoData;



BIN
example/images/composite_a.png View File

Before After
Width: 30  |  Height: 30  |  Size: 162B

BIN
example/images/composite_b.png View File

Before After
Width: 30  |  Height: 30  |  Size: 591B

+ 4
- 4
src/nanovg.c View File

@@ -385,7 +385,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;
@@ -2198,7 +2198,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
@@ -2239,7 +2239,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
@@ -2387,7 +2387,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;


+ 4
- 4
src/nanovg.h View File

@@ -648,10 +648,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;


+ 52
- 14
src/nanovg_gl.h View File

@@ -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)
{
@@ -1099,19 +1125,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;
@@ -1121,7 +1152,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);
@@ -1140,6 +1170,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
@@ -1169,6 +1203,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)
@@ -1284,7 +1319,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;
@@ -1300,6 +1335,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;
@@ -1365,7 +1401,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;
@@ -1379,6 +1415,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);
@@ -1420,7 +1457,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;
@@ -1431,6 +1468,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);


Loading…
Cancel
Save