Browse Source

Shared contexts; feature complete but relatively untested so far.

shared-context
Richie Hindle 3 years ago
parent
commit
5fdfbffd2b
3 changed files with 197 additions and 131 deletions
  1. +122
    -102
      src/nanovg.c
  2. +2
    -2
      src/nanovg.h
  3. +73
    -27
      src/nanovg_gl.h

+ 122
- 102
src/nanovg.c View File

@@ -112,6 +112,14 @@ struct NVGpathCache {
};
typedef struct NVGpathCache NVGpathCache;

struct NVGfontContext { // Fontstash context plus font images; shared between shared NanoVG contexts.
int refCount;
struct FONScontext* fs;
int fontImages[NVG_MAX_FONTIMAGES];
int fontImageIdx;
};
typedef struct NVGfontContext NVGfontContext;

struct NVGcontext {
NVGparams params;
float* commands;
@@ -125,9 +133,7 @@ struct NVGcontext {
float distTol;
float fringeWidth;
float devicePxRatio;
struct FONScontext* fs;
int fontImages[NVG_MAX_FONTIMAGES];
int fontImageIdx;
NVGfontContext* fontContext;
int drawCallCount;
int fillTriCount;
int strokeTriCount;
@@ -286,7 +292,7 @@ static NVGstate* nvg__getState(NVGcontext* ctx)
return &ctx->states[ctx->nstates-1];
}

NVGcontext* nvgCreateInternal(NVGparams* params)
NVGcontext* nvgCreateInternal(NVGparams* params, NVGcontext* other) // Share the fonts and images of 'other' if it's non-NULL.
{
FONSparams fontParams;
NVGcontext* ctx = (NVGcontext*)malloc(sizeof(NVGcontext));
@@ -295,8 +301,16 @@ NVGcontext* nvgCreateInternal(NVGparams* params)
memset(ctx, 0, sizeof(NVGcontext));

ctx->params = *params;
for (i = 0; i < NVG_MAX_FONTIMAGES; i++)
ctx->fontImages[i] = 0;
if (other) {
ctx->fontContext = other->fontContext;
ctx->fontContext->refCount++;
} else {
ctx->fontContext = (NVGfontContext*)malloc(sizeof(NVGfontContext));
if (ctx->fontContext == NULL) goto error;
for (i = 0; i < NVG_MAX_FONTIMAGES; i++)
ctx->fontContext->fontImages[i] = 0;
ctx->fontContext->refCount = 1;
}

ctx->commands = (float*)malloc(sizeof(float)*NVG_INIT_COMMANDS_SIZE);
if (!ctx->commands) goto error;
@@ -311,25 +325,27 @@ NVGcontext* nvgCreateInternal(NVGparams* params)

nvg__setDevicePixelRatio(ctx, 1.0f);

if (ctx->params.renderCreate(ctx->params.userPtr) == 0) goto error;
if (ctx->params.renderCreate(ctx->params.userPtr, other ? other->params.userPtr : NULL) == 0) goto error;

// Init font rendering
memset(&fontParams, 0, sizeof(fontParams));
fontParams.width = NVG_INIT_FONTIMAGE_SIZE;
fontParams.height = NVG_INIT_FONTIMAGE_SIZE;
fontParams.flags = FONS_ZERO_TOPLEFT;
fontParams.renderCreate = NULL;
fontParams.renderUpdate = NULL;
fontParams.renderDraw = NULL;
fontParams.renderDelete = NULL;
fontParams.userPtr = NULL;
ctx->fs = fonsCreateInternal(&fontParams);
if (ctx->fs == NULL) goto error;

// Create font texture
ctx->fontImages[0] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, fontParams.width, fontParams.height, 0, NULL);
if (ctx->fontImages[0] == 0) goto error;
ctx->fontImageIdx = 0;
if (!other) {
memset(&fontParams, 0, sizeof(fontParams));
fontParams.width = NVG_INIT_FONTIMAGE_SIZE;
fontParams.height = NVG_INIT_FONTIMAGE_SIZE;
fontParams.flags = FONS_ZERO_TOPLEFT;
fontParams.renderCreate = NULL;
fontParams.renderUpdate = NULL;
fontParams.renderDraw = NULL;
fontParams.renderDelete = NULL;
fontParams.userPtr = NULL;
ctx->fontContext->fs = fonsCreateInternal(&fontParams);
if (ctx->fontContext->fs == NULL) goto error;

// Create font texture
ctx->fontContext->fontImages[0] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, fontParams.width, fontParams.height, 0, NULL);
if (ctx->fontContext->fontImages[0] == 0) goto error;
ctx->fontContext->fontImageIdx = 0;
}

return ctx;

@@ -350,14 +366,18 @@ void nvgDeleteInternal(NVGcontext* ctx)
if (ctx->commands != NULL) free(ctx->commands);
if (ctx->cache != NULL) nvg__deletePathCache(ctx->cache);

if (ctx->fs)
fonsDeleteInternal(ctx->fs);
if (ctx->fontContext != NULL && --ctx->fontContext->refCount == 0) {
if (ctx->fontContext->fs)
fonsDeleteInternal(ctx->fontContext->fs);

for (i = 0; i < NVG_MAX_FONTIMAGES; i++) {
if (ctx->fontImages[i] != 0) {
nvgDeleteImage(ctx, ctx->fontImages[i]);
ctx->fontImages[i] = 0;
for (i = 0; i < NVG_MAX_FONTIMAGES; i++) {
if (ctx->fontContext->fontImages[i] != 0) {
nvgDeleteImage(ctx, ctx->fontContext->fontImages[i]);
ctx->fontContext->fontImages[i] = 0;
}
}

free(ctx->fontContext);
}

if (ctx->params.renderDelete != NULL)
@@ -394,30 +414,30 @@ void nvgCancelFrame(NVGcontext* ctx)
void nvgEndFrame(NVGcontext* ctx)
{
ctx->params.renderFlush(ctx->params.userPtr);
if (ctx->fontImageIdx != 0) {
int fontImage = ctx->fontImages[ctx->fontImageIdx];
if (ctx->fontContext->fontImageIdx != 0) {
int fontImage = ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx];
int i, j, iw, ih;
// delete images that smaller than current one
if (fontImage == 0)
return;
nvgImageSize(ctx, fontImage, &iw, &ih);
for (i = j = 0; i < ctx->fontImageIdx; i++) {
if (ctx->fontImages[i] != 0) {
for (i = j = 0; i < ctx->fontContext->fontImageIdx; i++) {
if (ctx->fontContext->fontImages[i] != 0) {
int nw, nh;
nvgImageSize(ctx, ctx->fontImages[i], &nw, &nh);
nvgImageSize(ctx, ctx->fontContext->fontImages[i], &nw, &nh);
if (nw < iw || nh < ih)
nvgDeleteImage(ctx, ctx->fontImages[i]);
nvgDeleteImage(ctx, ctx->fontContext->fontImages[i]);
else
ctx->fontImages[j++] = ctx->fontImages[i];
ctx->fontContext->fontImages[j++] = ctx->fontContext->fontImages[i];
}
}
// make current font image to first
ctx->fontImages[j++] = ctx->fontImages[0];
ctx->fontImages[0] = fontImage;
ctx->fontImageIdx = 0;
ctx->fontContext->fontImages[j++] = ctx->fontContext->fontImages[0];
ctx->fontContext->fontImages[0] = fontImage;
ctx->fontContext->fontImageIdx = 0;
// clear all images after j
for (i = j; i < NVG_MAX_FONTIMAGES; i++)
ctx->fontImages[i] = 0;
ctx->fontContext->fontImages[i] = 0;
}
}

@@ -2309,35 +2329,35 @@ void nvgStroke(NVGcontext* ctx)
// Add fonts
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename)
{
return fonsAddFont(ctx->fs, name, filename, 0);
return fonsAddFont(ctx->fontContext->fs, name, filename, 0);
}

int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex)
{
return fonsAddFont(ctx->fs, name, filename, fontIndex);
return fonsAddFont(ctx->fontContext->fs, name, filename, fontIndex);
}

int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData)
{
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, 0);
return fonsAddFontMem(ctx->fontContext->fs, name, data, ndata, freeData, 0);
}

int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex)
{
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, fontIndex);
return fonsAddFontMem(ctx->fontContext->fs, name, data, ndata, freeData, fontIndex);
}

int nvgFindFont(NVGcontext* ctx, const char* name)
{
if (name == NULL) return -1;
return fonsGetFontByName(ctx->fs, name);
return fonsGetFontByName(ctx->fontContext->fs, name);
}


int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont)
{
if(baseFont == -1 || fallbackFont == -1) return 0;
return fonsAddFallbackFont(ctx->fs, baseFont, fallbackFont);
return fonsAddFallbackFont(ctx->fontContext->fs, baseFont, fallbackFont);
}

int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont)
@@ -2347,7 +2367,7 @@ int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallba

void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont)
{
fonsResetFallbackFont(ctx->fs, baseFont);
fonsResetFallbackFont(ctx->fontContext->fs, baseFont);
}

void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont)
@@ -2395,7 +2415,7 @@ void nvgFontFaceId(NVGcontext* ctx, int font)
void nvgFontFace(NVGcontext* ctx, const char* font)
{
NVGstate* state = nvg__getState(ctx);
state->fontId = fonsGetFontByName(ctx->fs, font);
state->fontId = fonsGetFontByName(ctx->fontContext->fs, font);
}

static float nvg__quantize(float a, float d)
@@ -2412,12 +2432,12 @@ static void nvg__flushTextTexture(NVGcontext* ctx)
{
int dirty[4];

if (fonsValidateTexture(ctx->fs, dirty)) {
int fontImage = ctx->fontImages[ctx->fontImageIdx];
if (fonsValidateTexture(ctx->fontContext->fs, dirty)) {
int fontImage = ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx];
// Update texture
if (fontImage != 0) {
int iw, ih;
const unsigned char* data = fonsGetTextureData(ctx->fs, &iw, &ih);
const unsigned char* data = fonsGetTextureData(ctx->fontContext->fs, &iw, &ih);
int x = dirty[0];
int y = dirty[1];
int w = dirty[2] - dirty[0];
@@ -2431,23 +2451,23 @@ static int nvg__allocTextAtlas(NVGcontext* ctx)
{
int iw, ih;
nvg__flushTextTexture(ctx);
if (ctx->fontImageIdx >= NVG_MAX_FONTIMAGES-1)
if (ctx->fontContext->fontImageIdx >= NVG_MAX_FONTIMAGES-1)
return 0;
// if next fontImage already have a texture
if (ctx->fontImages[ctx->fontImageIdx+1] != 0)
nvgImageSize(ctx, ctx->fontImages[ctx->fontImageIdx+1], &iw, &ih);
if (ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1] != 0)
nvgImageSize(ctx, ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1], &iw, &ih);
else { // calculate the new font image size and create it.
nvgImageSize(ctx, ctx->fontImages[ctx->fontImageIdx], &iw, &ih);
nvgImageSize(ctx, ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx], &iw, &ih);
if (iw > ih)
ih *= 2;
else
iw *= 2;
if (iw > NVG_MAX_FONTIMAGE_SIZE || ih > NVG_MAX_FONTIMAGE_SIZE)
iw = ih = NVG_MAX_FONTIMAGE_SIZE;
ctx->fontImages[ctx->fontImageIdx+1] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, iw, ih, 0, NULL);
ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, iw, ih, 0, NULL);
}
++ctx->fontImageIdx;
fonsResetAtlas(ctx->fs, iw, ih);
++ctx->fontContext->fontImageIdx;
fonsResetAtlas(ctx->fontContext->fs, iw, ih);
return 1;
}

@@ -2458,7 +2478,7 @@ static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts)
NVGpaint paint = state->fill;

// Render triangles.
paint.image = ctx->fontImages[ctx->fontImageIdx];
paint.image = ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx];

// Apply global tint
for (i = 0; i < 4; i++) {
@@ -2495,19 +2515,19 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*

if (state->fontId == FONS_INVALID) return x;

fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId);
fonsSetSize(ctx->fontContext->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fontContext->fs, state->textAlign);
fonsSetFont(ctx->fontContext->fs, state->fontId);

cverts = nvg__maxi(2, (int)(end - string)) * 6; // conservative estimate.
verts = nvg__allocTempVerts(ctx, cverts);
if (verts == NULL) return x;

fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_REQUIRED);
fonsTextIterInit(ctx->fontContext->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_REQUIRED);
prevIter = iter;
while (fonsTextIterNext(ctx->fs, &iter, &q)) {
while (fonsTextIterNext(ctx->fontContext->fs, &iter, &q)) {
float c[4*2];
if (iter.prevGlyphIndex == -1) { // can not retrieve glyph?
if (nverts != 0) {
@@ -2517,7 +2537,7 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
iter = prevIter;
fonsTextIterNext(ctx->fs, &iter, &q); // try again
fonsTextIterNext(ctx->fontContext->fs, &iter, &q); // try again
if (iter.prevGlyphIndex == -1) // still can not find glyph?
break;
}
@@ -2602,18 +2622,18 @@ int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string,
if (string == end)
return 0;

fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId);
fonsSetSize(ctx->fontContext->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fontContext->fs, state->textAlign);
fonsSetFont(ctx->fontContext->fs, state->fontId);

fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_OPTIONAL);
fonsTextIterInit(ctx->fontContext->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_OPTIONAL);
prevIter = iter;
while (fonsTextIterNext(ctx->fs, &iter, &q)) {
while (fonsTextIterNext(ctx->fontContext->fs, &iter, &q)) {
if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph?
iter = prevIter;
fonsTextIterNext(ctx->fs, &iter, &q); // try again
fonsTextIterNext(ctx->fontContext->fs, &iter, &q); // try again
}
prevIter = iter;
positions[npos].str = iter.str;
@@ -2666,20 +2686,20 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa

if (string == end) return 0;

fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId);
fonsSetSize(ctx->fontContext->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fontContext->fs, state->textAlign);
fonsSetFont(ctx->fontContext->fs, state->fontId);

breakRowWidth *= scale;

fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end, FONS_GLYPH_BITMAP_OPTIONAL);
fonsTextIterInit(ctx->fontContext->fs, &iter, 0, 0, string, end, FONS_GLYPH_BITMAP_OPTIONAL);
prevIter = iter;
while (fonsTextIterNext(ctx->fs, &iter, &q)) {
while (fonsTextIterNext(ctx->fontContext->fs, &iter, &q)) {
if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph?
iter = prevIter;
fonsTextIterNext(ctx->fs, &iter, &q); // try again
fonsTextIterNext(ctx->fontContext->fs, &iter, &q); // try again
}
prevIter = iter;
switch (iter.codepoint) {
@@ -2850,16 +2870,16 @@ float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const

if (state->fontId == FONS_INVALID) return 0;

fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId);
fonsSetSize(ctx->fontContext->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fontContext->fs, state->textAlign);
fonsSetFont(ctx->fontContext->fs, state->fontId);

width = fonsTextBounds(ctx->fs, x*scale, y*scale, string, end, bounds);
width = fonsTextBounds(ctx->fontContext->fs, x*scale, y*scale, string, end, bounds);
if (bounds != NULL) {
// Use line bounds for height.
fonsLineBounds(ctx->fs, y*scale, &bounds[1], &bounds[3]);
fonsLineBounds(ctx->fontContext->fs, y*scale, &bounds[1], &bounds[3]);
bounds[0] *= invscale;
bounds[1] *= invscale;
bounds[2] *= invscale;
@@ -2894,12 +2914,12 @@ void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, co
minx = maxx = x;
miny = maxy = y;

fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId);
fonsLineBounds(ctx->fs, 0, &rminy, &rmaxy);
fonsSetSize(ctx->fontContext->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fontContext->fs, state->textAlign);
fonsSetFont(ctx->fontContext->fs, state->fontId);
fonsLineBounds(ctx->fontContext->fs, 0, &rminy, &rmaxy);
rminy *= invscale;
rmaxy *= invscale;

@@ -2945,13 +2965,13 @@ void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* l

if (state->fontId == FONS_INVALID) return;

fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId);
fonsSetSize(ctx->fontContext->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fontContext->fs, state->textAlign);
fonsSetFont(ctx->fontContext->fs, state->fontId);

fonsVertMetrics(ctx->fs, ascender, descender, lineh);
fonsVertMetrics(ctx->fontContext->fs, ascender, descender, lineh);
if (ascender != NULL)
*ascender *= invscale;
if (descender != NULL)


+ 2
- 2
src/nanovg.h View File

@@ -662,7 +662,7 @@ typedef struct NVGpath NVGpath;
struct NVGparams {
void* userPtr;
int edgeAntiAlias;
int (*renderCreate)(void* uptr);
int (*renderCreate)(void* uptr, void* otherUptr);
int (*renderCreateTexture)(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data);
int (*renderDeleteTexture)(void* uptr, int image);
int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data);
@@ -678,7 +678,7 @@ struct NVGparams {
typedef struct NVGparams NVGparams;

// Constructor and destructor, called by the render back-end.
NVGcontext* nvgCreateInternal(NVGparams* params);
NVGcontext* nvgCreateInternal(NVGparams* params, NVGcontext* other);
void nvgDeleteInternal(NVGcontext* ctx);

NVGparams* nvgInternalParams(NVGcontext* ctx);


+ 73
- 27
src/nanovg_gl.h View File

@@ -57,6 +57,7 @@ enum NVGcreateFlags {
#if defined NANOVG_GL2

NVGcontext* nvgCreateGL2(int flags);
NVGcontext* nvgCreateSharedGL2(NVGcontext* other, int flags);
void nvgDeleteGL2(NVGcontext* ctx);

int nvglCreateImageFromHandleGL2(NVGcontext* ctx, GLuint textureId, int w, int h, int flags);
@@ -67,6 +68,7 @@ GLuint nvglImageHandleGL2(NVGcontext* ctx, int image);
#if defined NANOVG_GL3

NVGcontext* nvgCreateGL3(int flags);
NVGcontext* nvgCreateSharedGL3(NVGcontext* other, int flags);
void nvgDeleteGL3(NVGcontext* ctx);

int nvglCreateImageFromHandleGL3(NVGcontext* ctx, GLuint textureId, int w, int h, int flags);
@@ -77,6 +79,7 @@ GLuint nvglImageHandleGL3(NVGcontext* ctx, int image);
#if defined NANOVG_GLES2

NVGcontext* nvgCreateGLES2(int flags);
NVGcontext* nvgCreateSharedGLES2(NVGcontext* other, int flags);
void nvgDeleteGLES2(NVGcontext* ctx);

int nvglCreateImageFromHandleGLES2(NVGcontext* ctx, GLuint textureId, int w, int h, int flags);
@@ -87,6 +90,7 @@ GLuint nvglImageHandleGLES2(NVGcontext* ctx, int image);
#if defined NANOVG_GLES3

NVGcontext* nvgCreateGLES3(int flags);
NVGcontext* nvgCreateSharedGLES3(NVGcontext* other, int flags);
void nvgDeleteGLES3(NVGcontext* ctx);

int nvglCreateImageFromHandleGLES3(NVGcontext* ctx, GLuint textureId, int w, int h, int flags);
@@ -228,13 +232,19 @@ struct GLNVGfragUniforms {
};
typedef struct GLNVGfragUniforms GLNVGfragUniforms;

struct GLNVGcontext {
GLNVGshader shader;
struct GLNVGtextureContext { // Textures; shared between shared NanoVG contexts.
int refCount;
GLNVGtexture* textures;
float view[2];
int ntextures;
int ctextures;
int textureId;
};
typedef struct GLNVGtextureContext GLNVGtextureContext;

struct GLNVGcontext {
GLNVGshader shader;
GLNVGtextureContext* textureContext;
float view[2];
GLuint vertBuf;
#if defined NANOVG_GL3
GLuint vertArr;
@@ -350,26 +360,26 @@ static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl)
GLNVGtexture* tex = NULL;
int i;

for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == 0) {
tex = &gl->textures[i];
for (i = 0; i < gl->textureContext->ntextures; i++) {
if (gl->textureContext->textures[i].id == 0) {
tex = &gl->textureContext->textures[i];
break;
}
}
if (tex == NULL) {
if (gl->ntextures+1 > gl->ctextures) {
if (gl->textureContext->ntextures+1 > gl->textureContext->ctextures) {
GLNVGtexture* textures;
int ctextures = glnvg__maxi(gl->ntextures+1, 4) + gl->ctextures/2; // 1.5x Overallocate
textures = (GLNVGtexture*)realloc(gl->textures, sizeof(GLNVGtexture)*ctextures);
int ctextures = glnvg__maxi(gl->textureContext->ntextures+1, 4) + gl->textureContext->ctextures/2; // 1.5x Overallocate
textures = (GLNVGtexture*)realloc(gl->textureContext->textures, sizeof(GLNVGtexture)*ctextures);
if (textures == NULL) return NULL;
gl->textures = textures;
gl->ctextures = ctextures;
gl->textureContext->textures = textures;
gl->textureContext->ctextures = ctextures;
}
tex = &gl->textures[gl->ntextures++];
tex = &gl->textureContext->textures[gl->textureContext->ntextures++];
}

memset(tex, 0, sizeof(*tex));
tex->id = ++gl->textureId;
tex->id = ++gl->textureContext->textureId;

return tex;
}
@@ -377,20 +387,20 @@ static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl)
static GLNVGtexture* glnvg__findTexture(GLNVGcontext* gl, int id)
{
int i;
for (i = 0; i < gl->ntextures; i++)
if (gl->textures[i].id == id)
return &gl->textures[i];
for (i = 0; i < gl->textureContext->ntextures; i++)
if (gl->textureContext->textures[i].id == id)
return &gl->textureContext->textures[i];
return NULL;
}

static int glnvg__deleteTexture(GLNVGcontext* gl, int id)
{
int i;
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == id) {
if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVG_IMAGE_NODELETE) == 0)
glDeleteTextures(1, &gl->textures[i].tex);
memset(&gl->textures[i], 0, sizeof(gl->textures[i]));
for (i = 0; i < gl->textureContext->ntextures; i++) {
if (gl->textureContext->textures[i].id == id) {
if (gl->textureContext->textures[i].tex != 0 && (gl->textureContext->textures[i].flags & NVG_IMAGE_NODELETE) == 0)
glDeleteTextures(1, &gl->textureContext->textures[i].tex);
memset(&gl->textureContext->textures[i], 0, sizeof(gl->textureContext->textures[i]));
return 1;
}
}
@@ -504,9 +514,20 @@ static void glnvg__getUniforms(GLNVGshader* shader)

static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data);

static int glnvg__renderCreate(void* uptr)
static int glnvg__renderCreate(void* uptr, void* otherUptr) // Share the textures of GLNVGcontext 'otherUptr' if it's non-NULL.
{
GLNVGcontext* gl = (GLNVGcontext*)uptr;

if (otherUptr) {
GLNVGcontext* other = (GLNVGcontext*)otherUptr;
gl->textureContext = other->textureContext;
gl->textureContext->refCount++;
} else {
gl->textureContext = (GLNVGtextureContext*)malloc(sizeof(GLNVGtextureContext));
memset(gl->textureContext, 0, sizeof(GLNVGtextureContext));
gl->textureContext->refCount = 1;
}

int align = 4;

// TODO: mediump float may not be enough for GLES2 in iOS.
@@ -1545,11 +1566,14 @@ static void glnvg__renderDelete(void* uptr)
if (gl->vertBuf != 0)
glDeleteBuffers(1, &gl->vertBuf);

for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVG_IMAGE_NODELETE) == 0)
glDeleteTextures(1, &gl->textures[i].tex);
if (gl->textureContext != NULL && --gl->textureContext->refCount == 0) {
for (i = 0; i < gl->textureContext->ntextures; i++) {
if (gl->textureContext->textures[i].tex != 0 && (gl->textureContext->textures[i].flags & NVG_IMAGE_NODELETE) == 0)
glDeleteTextures(1, &gl->textureContext->textures[i].tex);
}
free(gl->textureContext->textures);
free(gl->textureContext);
}
free(gl->textures);

free(gl->paths);
free(gl->verts);
@@ -1569,6 +1593,28 @@ NVGcontext* nvgCreateGLES2(int flags)
#elif defined NANOVG_GLES3
NVGcontext* nvgCreateGLES3(int flags)
#endif
{
#if defined NANOVG_GL2
return nvgCreateSharedGL2(NULL, flags);
#elif defined NANOVG_GL3
return nvgCreateSharedGL3(NULL, flags);
#elif defined NANOVG_GLES2
return nvgCreateSharedGLES2(NULL, flags);
#elif defined NANOVG_GLES3
return nvgCreateSharedGLES3(NULL, flags);
#endif
}

// Share the fonts and textures of 'other' if it's non-NULL.
#if defined NANOVG_GL2
NVGcontext* nvgCreateSharedGL2(NVGcontext* other, int flags)
#elif defined NANOVG_GL3
NVGcontext* nvgCreateSharedGL3(NVGcontext* other, int flags)
#elif defined NANOVG_GLES2
NVGcontext* nvgCreateSharedGLES2(NVGcontext* other, int flags)
#elif defined NANOVG_GLES3
NVGcontext* nvgCreateSharedGLES3(NVGcontext* other, int flags)
#endif
{
NVGparams params;
NVGcontext* ctx = NULL;
@@ -1594,7 +1640,7 @@ NVGcontext* nvgCreateGLES3(int flags)

gl->flags = flags;

ctx = nvgCreateInternal(&params);
ctx = nvgCreateInternal(&params, other);
if (ctx == NULL) goto error;

return ctx;


Loading…
Cancel
Save