Browse Source

Implements composite operation for blending rendering between frames.

This commit implements the `nvgGlobalCompositeOperation()` function to support blending between frames. All operations defined in HTML5 canvas API are supported. Also, it is possible to create custom composite operation by calling `nvgBlendFunc()` or `nvgBlendFuncSeparate()` functions.
shared-context
Olli Wang 8 years ago
parent
commit
c4b865796d
3 changed files with 112 additions and 1 deletions
  1. +19
    -0
      src/nanovg.c
  2. +52
    -0
      src/nanovg.h
  3. +41
    -1
      src/nanovg_gl.h

+ 19
- 0
src/nanovg.c View File

@@ -338,6 +338,25 @@ void nvgEndFrame(NVGcontext* ctx)
} }
} }


NVGcompositeOperation nvgBlendFunc(int sfactor, int dfactor)
{
return nvgBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
}

NVGcompositeOperation nvgBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha)
{
NVGcompositeOperation operation;
operation.srcRGB = srcRGB;
operation.dstRGB = dstRGB;
operation.srcAlpha = srcAlpha;
operation.dstAlpha = dstAlpha;
return operation;
}

void nvgGlobalCompositeOperation(NVGcontext* ctx, NVGcompositeOperation op) {
ctx->params.renderCompositeOperation(ctx->params.userPtr, op);
}

NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b) NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b)
{ {
return nvgRGBA(r,g,b,255); return nvgRGBA(r,g,b,255);


+ 52
- 0
src/nanovg.h View File

@@ -83,6 +83,41 @@ enum NVGalign {
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline. NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
}; };


enum NVGblendFactor {
NVG_ZERO = 1<<0,
NVG_ONE = 1<<1,
NVG_SRC_COLOR = 1<<2,
NVG_ONE_MINUS_SRC_COLOR = 1<<3,
NVG_DST_COLOR = 1<<4,
NVG_ONE_MINUS_DST_COLOR = 1<<5,
NVG_SRC_ALPHA = 1<<6,
NVG_ONE_MINUS_SRC_ALPHA = 1<<7,
NVG_DST_ALPHA = 1<<8,
NVG_ONE_MINUS_DST_ALPHA = 1<<9,
NVG_SRC_ALPHA_SATURATE = 1<<10,
};

struct NVGcompositeOperation {
int srcRGB;
int dstRGB;
int srcAlpha;
int dstAlpha;
};
typedef struct NVGcompositeOperation NVGcompositeOperation;

// Predefined composite operations.
#define NVG_SOURCE_OVER nvgBlendFunc(NVG_ONE, NVG_ONE_MINUS_SRC_ALPHA)
#define NVG_SOURCE_IN nvgBlendFunc(NVG_DST_ALPHA, NVG_ZERO)
#define NVG_SOURCE_OUT nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA, NVG_ZERO)
#define NVG_ATOP nvgBlendFunc(NVG_DST_ALPHA, NVG_ONE_MINUS_SRC_ALPHA)
#define NVG_DESTINATION_OVER nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA, NVG_ONE)
#define NVG_DESTINATION_IN nvgBlendFunc(NVG_ZERO, NVG_SRC_ALPHA)
#define NVG_DESTINATION_OUT nvgBlendFunc(NVG_ZERO, NVG_ONE_MINUS_SRC_ALPHA)
#define NVG_DESTINATION_ATOP nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA, NVG_SRC_ALPHA)
#define NVG_LIGHTER nvgBlendFunc(NVG_ONE, NVG_ONE)
#define NVG_COPY nvgBlendFunc(NVG_ONE, NVG_ZERO)
#define NVG_XOR nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA NVG_ONE_MINUS_SRC_ALPHA)

struct NVGglyphPosition { struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string. const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position. float x; // The x-coordinate of the logical glyph position.
@@ -123,6 +158,22 @@ void nvgCancelFrame(NVGcontext* ctx);
// Ends drawing flushing remaining render state. // Ends drawing flushing remaining render state.
void nvgEndFrame(NVGcontext* ctx); void nvgEndFrame(NVGcontext* ctx);


//
// Composite operation
//
// Composite operation in NanoVG works between frames. The default composite
// operation of NanoVG is NVG_SOURCE_OVER, and the value is reset whenever
// calling nvgBeginFrame().

// Creates a composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor.
NVGcompositeOperation nvgBlendFunc(int sfactor, int dfactor);

// Creates a composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor.
NVGcompositeOperation nvgBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);

// Sets the composite operation for the current frame. This function should be called between nvgBeginFrame() and nvgEndFrame(). The default composite operation of NanoVG is NVG_SOURCE_OVER.
void nvgGlobalCompositeOperation(NVGcontext* ctx, NVGcompositeOperation op);

// //
// Color utils // Color utils
// //
@@ -590,6 +641,7 @@ 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 (*renderCompositeOperation)(void* uptr, NVGcompositeOperation op);
void (*renderFlush)(void* uptr); 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, 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, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);


+ 41
- 1
src/nanovg_gl.h View File

@@ -219,6 +219,7 @@ struct GLNVGfragUniforms {
typedef struct GLNVGfragUniforms GLNVGfragUniforms; typedef struct GLNVGfragUniforms GLNVGfragUniforms;


struct GLNVGcontext { struct GLNVGcontext {
NVGcompositeOperation compositeOperation;
GLNVGshader shader; GLNVGshader shader;
GLNVGtexture* textures; GLNVGtexture* textures;
float view[2]; float view[2];
@@ -944,6 +945,7 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)
static void glnvg__renderViewport(void* uptr, int width, int height, float devicePixelRatio) static void glnvg__renderViewport(void* uptr, int width, int height, float devicePixelRatio)
{ {
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
gl->compositeOperation = NVG_SOURCE_OVER; // resets composition
gl->view[0] = (float)width; gl->view[0] = (float)width;
gl->view[1] = (float)height; gl->view[1] = (float)height;
} }
@@ -1072,6 +1074,43 @@ static void glnvg__renderCancel(void* uptr) {
gl->nuniforms = 0; gl->nuniforms = 0;
} }


static GLenum glnvg_convertBlendFuncFactor(int factor)
{
if (factor == NVG_ZERO)
return GL_ZERO;
if (factor == NVG_ONE)
return GL_ONE;
if (factor == NVG_SRC_COLOR)
return GL_SRC_COLOR;
if (factor == NVG_ONE_MINUS_SRC_COLOR)
return GL_ONE_MINUS_SRC_COLOR;
if (factor == NVG_DST_COLOR)
return GL_DST_COLOR;
if (factor == NVG_ONE_MINUS_DST_COLOR)
return GL_ONE_MINUS_DST_COLOR;
if (factor == NVG_SRC_ALPHA)
return GL_SRC_ALPHA;
if (factor == NVG_ONE_MINUS_SRC_ALPHA)
return GL_ONE_MINUS_SRC_ALPHA;
if (factor == NVG_DST_ALPHA)
return GL_DST_ALPHA;
if (factor == NVG_ONE_MINUS_DST_ALPHA)
return GL_ONE_MINUS_DST_ALPHA;
if (factor == NVG_SRC_ALPHA_SATURATE)
return GL_SRC_ALPHA_SATURATE;
}

static void glnvg__blendCompositeOperation(NVGcompositeOperation operation)
{
glBlendFuncSeparate(glnvg_convertBlendFuncFactor(operation.srcRGB), glnvg_convertBlendFuncFactor(operation.dstRGB), glnvg_convertBlendFuncFactor(operation.srcAlpha), glnvg_convertBlendFuncFactor(operation.dstAlpha));
}

static void glnvg__renderCompositeOperation(void* uptr, NVGcompositeOperation op)
{
GLNVGcontext* gl = (GLNVGcontext*)uptr;
gl->compositeOperation = op;
}

static void glnvg__renderFlush(void* uptr) static void glnvg__renderFlush(void* uptr)
{ {
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
@@ -1082,7 +1121,7 @@ static void glnvg__renderFlush(void* uptr)
// Setup require GL state. // Setup require GL state.
glUseProgram(gl->shader.prog); glUseProgram(gl->shader.prog);


glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glnvg__blendCompositeOperation(gl->compositeOperation);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
@@ -1473,6 +1512,7 @@ NVGcontext* nvgCreateGLES3(int flags)
params.renderGetTextureSize = glnvg__renderGetTextureSize; params.renderGetTextureSize = glnvg__renderGetTextureSize;
params.renderViewport = glnvg__renderViewport; params.renderViewport = glnvg__renderViewport;
params.renderCancel = glnvg__renderCancel; params.renderCancel = glnvg__renderCancel;
params.renderCompositeOperation = glnvg__renderCompositeOperation;
params.renderFlush = glnvg__renderFlush; params.renderFlush = glnvg__renderFlush;
params.renderFill = glnvg__renderFill; params.renderFill = glnvg__renderFill;
params.renderStroke = glnvg__renderStroke; params.renderStroke = glnvg__renderStroke;


Loading…
Cancel
Save