mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-30 07:42:13 +00:00
520 lines
17 KiB
C
520 lines
17 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
#include "nanovg.h"
|
||
|
#include "nanovg/dk_renderer.hpp"
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
static int dknvg__maxi(int a, int b) { return a > b ? a : b; }
|
||
|
|
||
|
static const DKNVGtextureDescriptor* dknvg__findTexture(DKNVGcontext* dk, int id) {
|
||
|
return dk->renderer->GetTextureDescriptor(*dk, id);
|
||
|
}
|
||
|
|
||
|
static int dknvg__renderCreate(void* uptr)
|
||
|
{
|
||
|
DKNVGcontext *dk = (DKNVGcontext*)uptr;
|
||
|
return dk->renderer->Create(*dk);
|
||
|
}
|
||
|
|
||
|
static int dknvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data)
|
||
|
{
|
||
|
DKNVGcontext *dk = (DKNVGcontext*)uptr;
|
||
|
return dk->renderer->CreateTexture(*dk, type, w, h, imageFlags, data);
|
||
|
}
|
||
|
|
||
|
static int dknvg__renderDeleteTexture(void* uptr, int image) {
|
||
|
DKNVGcontext *dk = (DKNVGcontext*)uptr;
|
||
|
return dk->renderer->DeleteTexture(*dk, image);
|
||
|
}
|
||
|
|
||
|
static int dknvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data) {
|
||
|
DKNVGcontext *dk = (DKNVGcontext*)uptr;
|
||
|
return dk->renderer->UpdateTexture(*dk, image, x, y, w, h, data);
|
||
|
}
|
||
|
|
||
|
static int dknvg__renderGetTextureSize(void* uptr, int image, int* w, int* h) {
|
||
|
DKNVGcontext *dk = (DKNVGcontext*)uptr;
|
||
|
return dk->renderer->GetTextureSize(*dk, image, w, h);
|
||
|
}
|
||
|
|
||
|
static void dknvg__xformToMat3x4(float* m3, float* t) {
|
||
|
m3[0] = t[0];
|
||
|
m3[1] = t[1];
|
||
|
m3[2] = 0.0f;
|
||
|
m3[3] = 0.0f;
|
||
|
m3[4] = t[2];
|
||
|
m3[5] = t[3];
|
||
|
m3[6] = 0.0f;
|
||
|
m3[7] = 0.0f;
|
||
|
m3[8] = t[4];
|
||
|
m3[9] = t[5];
|
||
|
m3[10] = 1.0f;
|
||
|
m3[11] = 0.0f;
|
||
|
}
|
||
|
|
||
|
static NVGcolor dknvg__premulColor(NVGcolor c) {
|
||
|
c.r *= c.a;
|
||
|
c.g *= c.a;
|
||
|
c.b *= c.a;
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
static int dknvg__convertPaint(DKNVGcontext* dk, DKNVGfragUniforms* frag, NVGpaint* paint,
|
||
|
NVGscissor* scissor, float width, float fringe, float strokeThr)
|
||
|
{
|
||
|
const DKNVGtextureDescriptor *tex = NULL;
|
||
|
float invxform[6];
|
||
|
|
||
|
memset(frag, 0, sizeof(*frag));
|
||
|
|
||
|
frag->innerCol = dknvg__premulColor(paint->innerColor);
|
||
|
frag->outerCol = dknvg__premulColor(paint->outerColor);
|
||
|
|
||
|
if (scissor->extent[0] < -0.5f || scissor->extent[1] < -0.5f) {
|
||
|
memset(frag->scissorMat, 0, sizeof(frag->scissorMat));
|
||
|
frag->scissorExt[0] = 1.0f;
|
||
|
frag->scissorExt[1] = 1.0f;
|
||
|
frag->scissorScale[0] = 1.0f;
|
||
|
frag->scissorScale[1] = 1.0f;
|
||
|
} else {
|
||
|
nvgTransformInverse(invxform, scissor->xform);
|
||
|
dknvg__xformToMat3x4(frag->scissorMat, invxform);
|
||
|
frag->scissorExt[0] = scissor->extent[0];
|
||
|
frag->scissorExt[1] = scissor->extent[1];
|
||
|
frag->scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe;
|
||
|
frag->scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe;
|
||
|
}
|
||
|
|
||
|
memcpy(frag->extent, paint->extent, sizeof(frag->extent));
|
||
|
frag->strokeMult = (width*0.5f + fringe*0.5f) / fringe;
|
||
|
frag->strokeThr = strokeThr;
|
||
|
|
||
|
if (paint->image != 0) {
|
||
|
tex = dknvg__findTexture(dk, paint->image);
|
||
|
if (tex == NULL) return 0;
|
||
|
if ((tex->flags & NVG_IMAGE_FLIPY) != 0) {
|
||
|
float m1[6], m2[6];
|
||
|
nvgTransformTranslate(m1, 0.0f, frag->extent[1] * 0.5f);
|
||
|
nvgTransformMultiply(m1, paint->xform);
|
||
|
nvgTransformScale(m2, 1.0f, -1.0f);
|
||
|
nvgTransformMultiply(m2, m1);
|
||
|
nvgTransformTranslate(m1, 0.0f, -frag->extent[1] * 0.5f);
|
||
|
nvgTransformMultiply(m1, m2);
|
||
|
nvgTransformInverse(invxform, m1);
|
||
|
} else {
|
||
|
nvgTransformInverse(invxform, paint->xform);
|
||
|
}
|
||
|
frag->type = NSVG_SHADER_FILLIMG;
|
||
|
|
||
|
if (tex->type == NVG_TEXTURE_RGBA)
|
||
|
frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1;
|
||
|
else
|
||
|
frag->texType = 2;
|
||
|
// printf("frag->texType = %d\n", frag->texType);
|
||
|
} else {
|
||
|
frag->type = NSVG_SHADER_FILLGRAD;
|
||
|
frag->radius = paint->radius;
|
||
|
frag->feather = paint->feather;
|
||
|
nvgTransformInverse(invxform, paint->xform);
|
||
|
}
|
||
|
|
||
|
dknvg__xformToMat3x4(frag->paintMat, invxform);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static DKNVGfragUniforms* nvg__fragUniformPtr(DKNVGcontext* dk, int i);
|
||
|
|
||
|
static void dknvg__renderViewport(void* uptr, float width, float height, float devicePixelRatio)
|
||
|
{
|
||
|
NVG_NOTUSED(devicePixelRatio);
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)uptr;
|
||
|
dk->view[0] = width;
|
||
|
dk->view[1] = height;
|
||
|
}
|
||
|
|
||
|
static void dknvg__renderCancel(void* uptr) {
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)uptr;
|
||
|
dk->nverts = 0;
|
||
|
dk->npaths = 0;
|
||
|
dk->ncalls = 0;
|
||
|
dk->nuniforms = 0;
|
||
|
}
|
||
|
|
||
|
static int dknvg_convertBlendFuncFactor(int factor) {
|
||
|
switch (factor) {
|
||
|
case NVG_ZERO:
|
||
|
return DkBlendFactor_Zero;
|
||
|
case NVG_ONE:
|
||
|
return DkBlendFactor_One;
|
||
|
case NVG_SRC_COLOR:
|
||
|
return DkBlendFactor_SrcColor;
|
||
|
case NVG_ONE_MINUS_SRC_COLOR:
|
||
|
return DkBlendFactor_InvSrcColor;
|
||
|
case NVG_DST_COLOR:
|
||
|
return DkBlendFactor_DstColor;
|
||
|
case NVG_ONE_MINUS_DST_COLOR:
|
||
|
return DkBlendFactor_InvDstColor;
|
||
|
case NVG_SRC_ALPHA:
|
||
|
return DkBlendFactor_SrcAlpha;
|
||
|
case NVG_ONE_MINUS_SRC_ALPHA:
|
||
|
return DkBlendFactor_InvSrcAlpha;
|
||
|
case NVG_DST_ALPHA:
|
||
|
return DkBlendFactor_DstAlpha;
|
||
|
case NVG_ONE_MINUS_DST_ALPHA:
|
||
|
return DkBlendFactor_InvDstAlpha;
|
||
|
case NVG_SRC_ALPHA_SATURATE:
|
||
|
return DkBlendFactor_SrcAlphaSaturate;
|
||
|
default:
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static DKNVGblend dknvg__blendCompositeOperation(NVGcompositeOperationState op) {
|
||
|
DKNVGblend blend;
|
||
|
blend.srcRGB = dknvg_convertBlendFuncFactor(op.srcRGB);
|
||
|
blend.dstRGB = dknvg_convertBlendFuncFactor(op.dstRGB);
|
||
|
blend.srcAlpha = dknvg_convertBlendFuncFactor(op.srcAlpha);
|
||
|
blend.dstAlpha = dknvg_convertBlendFuncFactor(op.dstAlpha);
|
||
|
|
||
|
if (blend.srcRGB == -1 || blend.dstRGB == -1 || blend.srcAlpha == -1 || blend.dstAlpha == -1) {
|
||
|
blend.srcRGB = DkBlendFactor_One;
|
||
|
blend.dstRGB = DkBlendFactor_InvSrcAlpha;
|
||
|
blend.srcAlpha = DkBlendFactor_One;
|
||
|
blend.dstAlpha = DkBlendFactor_InvSrcAlpha;
|
||
|
}
|
||
|
return blend;
|
||
|
}
|
||
|
|
||
|
static void dknvg__renderFlush(void* uptr) {
|
||
|
DKNVGcontext *dk = (DKNVGcontext*)uptr;
|
||
|
dk->renderer->Flush(*dk);
|
||
|
}
|
||
|
|
||
|
static int dknvg__maxVertCount(const NVGpath* paths, int npaths) {
|
||
|
int i, count = 0;
|
||
|
for (i = 0; i < npaths; i++) {
|
||
|
count += paths[i].nfill;
|
||
|
count += paths[i].nstroke;
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static DKNVGcall* dknvg__allocCall(DKNVGcontext* dk)
|
||
|
{
|
||
|
DKNVGcall* ret = NULL;
|
||
|
if (dk->ncalls+1 > dk->ccalls) {
|
||
|
DKNVGcall* calls;
|
||
|
int ccalls = dknvg__maxi(dk->ncalls+1, 128) + dk->ccalls/2; // 1.5x Overallocate
|
||
|
calls = (DKNVGcall*)realloc(dk->calls, sizeof(DKNVGcall) * ccalls);
|
||
|
if (calls == NULL) return NULL;
|
||
|
dk->calls = calls;
|
||
|
dk->ccalls = ccalls;
|
||
|
}
|
||
|
ret = &dk->calls[dk->ncalls++];
|
||
|
memset(ret, 0, sizeof(DKNVGcall));
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int dknvg__allocPaths(DKNVGcontext* dk, int n)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
if (dk->npaths+n > dk->cpaths) {
|
||
|
DKNVGpath* paths;
|
||
|
int cpaths = dknvg__maxi(dk->npaths + n, 128) + dk->cpaths/2; // 1.5x Overallocate
|
||
|
paths = (DKNVGpath*)realloc(dk->paths, sizeof(DKNVGpath) * cpaths);
|
||
|
if (paths == NULL) return -1;
|
||
|
dk->paths = paths;
|
||
|
dk->cpaths = cpaths;
|
||
|
}
|
||
|
ret = dk->npaths;
|
||
|
dk->npaths += n;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int dknvg__allocVerts(DKNVGcontext* dk, int n)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
if (dk->nverts+n > dk->cverts) {
|
||
|
NVGvertex* verts;
|
||
|
int cverts = dknvg__maxi(dk->nverts + n, 4096) + dk->cverts/2; // 1.5x Overallocate
|
||
|
verts = (NVGvertex*)realloc(dk->verts, sizeof(NVGvertex) * cverts);
|
||
|
if (verts == NULL) return -1;
|
||
|
dk->verts = verts;
|
||
|
dk->cverts = cverts;
|
||
|
}
|
||
|
ret = dk->nverts;
|
||
|
dk->nverts += n;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int dknvg__allocFragUniforms(DKNVGcontext* dk, int n)
|
||
|
{
|
||
|
int ret = 0, structSize = dk->fragSize;
|
||
|
if (dk->nuniforms+n > dk->cuniforms) {
|
||
|
unsigned char* uniforms;
|
||
|
int cuniforms = dknvg__maxi(dk->nuniforms+n, 128) + dk->cuniforms/2; // 1.5x Overallocate
|
||
|
uniforms = (unsigned char*)realloc(dk->uniforms, structSize * cuniforms);
|
||
|
if (uniforms == NULL) return -1;
|
||
|
dk->uniforms = uniforms;
|
||
|
dk->cuniforms = cuniforms;
|
||
|
}
|
||
|
ret = dk->nuniforms * structSize;
|
||
|
dk->nuniforms += n;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static DKNVGfragUniforms* nvg__fragUniformPtr(DKNVGcontext* dk, int i)
|
||
|
{
|
||
|
return (DKNVGfragUniforms*)&dk->uniforms[i];
|
||
|
}
|
||
|
|
||
|
static void dknvg__vset(NVGvertex* vtx, float x, float y, float u, float v)
|
||
|
{
|
||
|
vtx->x = x;
|
||
|
vtx->y = y;
|
||
|
vtx->u = u;
|
||
|
vtx->v = v;
|
||
|
}
|
||
|
|
||
|
static void dknvg__renderFill(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe,
|
||
|
const float* bounds, const NVGpath* paths, int npaths)
|
||
|
{
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)uptr;
|
||
|
DKNVGcall* call = dknvg__allocCall(dk);
|
||
|
NVGvertex* quad;
|
||
|
DKNVGfragUniforms* frag;
|
||
|
int i, maxverts, offset;
|
||
|
|
||
|
if (call == NULL) return;
|
||
|
|
||
|
call->type = DKNVG_FILL;
|
||
|
call->triangleCount = 4;
|
||
|
call->pathOffset = dknvg__allocPaths(dk, npaths);
|
||
|
if (call->pathOffset == -1) goto error;
|
||
|
call->pathCount = npaths;
|
||
|
call->image = paint->image;
|
||
|
call->blendFunc = dknvg__blendCompositeOperation(compositeOperation);
|
||
|
|
||
|
if (npaths == 1 && paths[0].convex)
|
||
|
{
|
||
|
call->type = DKNVG_CONVEXFILL;
|
||
|
call->triangleCount = 0; // Bounding box fill quad not needed for convex fill
|
||
|
}
|
||
|
|
||
|
// Allocate vertices for all the paths.
|
||
|
maxverts = dknvg__maxVertCount(paths, npaths) + call->triangleCount;
|
||
|
offset = dknvg__allocVerts(dk, maxverts);
|
||
|
if (offset == -1) goto error;
|
||
|
|
||
|
for (i = 0; i < npaths; i++) {
|
||
|
DKNVGpath* copy = &dk->paths[call->pathOffset + i];
|
||
|
const NVGpath* path = &paths[i];
|
||
|
memset(copy, 0, sizeof(DKNVGpath));
|
||
|
if (path->nfill > 0) {
|
||
|
copy->fillOffset = offset;
|
||
|
copy->fillCount = path->nfill;
|
||
|
memcpy(&dk->verts[offset], path->fill, sizeof(NVGvertex) * path->nfill);
|
||
|
offset += path->nfill;
|
||
|
}
|
||
|
if (path->nstroke > 0) {
|
||
|
copy->strokeOffset = offset;
|
||
|
copy->strokeCount = path->nstroke;
|
||
|
memcpy(&dk->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke);
|
||
|
offset += path->nstroke;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Setup uniforms for draw calls
|
||
|
if (call->type == DKNVG_FILL) {
|
||
|
// Quad
|
||
|
call->triangleOffset = offset;
|
||
|
quad = &dk->verts[call->triangleOffset];
|
||
|
dknvg__vset(&quad[0], bounds[2], bounds[3], 0.5f, 1.0f);
|
||
|
dknvg__vset(&quad[1], bounds[2], bounds[1], 0.5f, 1.0f);
|
||
|
dknvg__vset(&quad[2], bounds[0], bounds[3], 0.5f, 1.0f);
|
||
|
dknvg__vset(&quad[3], bounds[0], bounds[1], 0.5f, 1.0f);
|
||
|
|
||
|
call->uniformOffset = dknvg__allocFragUniforms(dk, 2);
|
||
|
if (call->uniformOffset == -1) goto error;
|
||
|
// Simple shader for stencil
|
||
|
frag = nvg__fragUniformPtr(dk, call->uniformOffset);
|
||
|
memset(frag, 0, sizeof(*frag));
|
||
|
frag->strokeThr = -1.0f;
|
||
|
frag->type = NSVG_SHADER_SIMPLE;
|
||
|
// Fill shader
|
||
|
dknvg__convertPaint(dk, nvg__fragUniformPtr(dk, call->uniformOffset + dk->fragSize), paint, scissor, fringe, fringe, -1.0f);
|
||
|
} else {
|
||
|
call->uniformOffset = dknvg__allocFragUniforms(dk, 1);
|
||
|
if (call->uniformOffset == -1) goto error;
|
||
|
// Fill shader
|
||
|
dknvg__convertPaint(dk, nvg__fragUniformPtr(dk, call->uniformOffset), paint, scissor, fringe, fringe, -1.0f);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
// We get here if call alloc was ok, but something else is not.
|
||
|
// Roll back the last call to prevent drawing it.
|
||
|
if (dk->ncalls > 0) dk->ncalls--;
|
||
|
}
|
||
|
|
||
|
static void dknvg__renderStroke(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe,
|
||
|
float strokeWidth, const NVGpath* paths, int npaths)
|
||
|
{
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)uptr;
|
||
|
DKNVGcall* call = dknvg__allocCall(dk);
|
||
|
int i, maxverts, offset;
|
||
|
|
||
|
if (call == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
call->type = DKNVG_STROKE;
|
||
|
call->pathOffset = dknvg__allocPaths(dk, npaths);
|
||
|
if (call->pathOffset == -1) goto error;
|
||
|
call->pathCount = npaths;
|
||
|
call->image = paint->image;
|
||
|
call->blendFunc = dknvg__blendCompositeOperation(compositeOperation);
|
||
|
|
||
|
// Allocate vertices for all the paths.
|
||
|
maxverts = dknvg__maxVertCount(paths, npaths);
|
||
|
offset = dknvg__allocVerts(dk, maxverts);
|
||
|
if (offset == -1) goto error;
|
||
|
|
||
|
for (i = 0; i < npaths; i++) {
|
||
|
DKNVGpath* copy = &dk->paths[call->pathOffset + i];
|
||
|
const NVGpath* path = &paths[i];
|
||
|
memset(copy, 0, sizeof(DKNVGpath));
|
||
|
if (path->nstroke) {
|
||
|
copy->strokeOffset = offset;
|
||
|
copy->strokeCount = path->nstroke;
|
||
|
memcpy(&dk->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke);
|
||
|
offset += path->nstroke;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dk->flags & NVG_STENCIL_STROKES) {
|
||
|
// Fill shader
|
||
|
call->uniformOffset = dknvg__allocFragUniforms(dk, 2);
|
||
|
if (call->uniformOffset == -1) goto error;
|
||
|
|
||
|
dknvg__convertPaint(dk, nvg__fragUniformPtr(dk, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f);
|
||
|
dknvg__convertPaint(dk, nvg__fragUniformPtr(dk, call->uniformOffset + dk->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f);
|
||
|
} else {
|
||
|
// Fill shader
|
||
|
call->uniformOffset = dknvg__allocFragUniforms(dk, 1);
|
||
|
if (call->uniformOffset == -1) goto error;
|
||
|
|
||
|
dknvg__convertPaint(dk, nvg__fragUniformPtr(dk, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
// We get here if call alloc was ok, but something else is not.
|
||
|
// Roll back the last call to prevent drawing it.
|
||
|
if (dk->ncalls > 0) dk->ncalls--;
|
||
|
}
|
||
|
|
||
|
static void dknvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor,
|
||
|
const NVGvertex* verts, int nverts, float fringe)
|
||
|
{
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)uptr;
|
||
|
DKNVGcall* call = dknvg__allocCall(dk);
|
||
|
DKNVGfragUniforms* frag;
|
||
|
|
||
|
if (call == NULL) return;
|
||
|
|
||
|
call->type = DKNVG_TRIANGLES;
|
||
|
call->image = paint->image;
|
||
|
call->blendFunc = dknvg__blendCompositeOperation(compositeOperation);
|
||
|
|
||
|
// Allocate vertices for all the paths.
|
||
|
call->triangleOffset = dknvg__allocVerts(dk, nverts);
|
||
|
if (call->triangleOffset == -1) goto error;
|
||
|
call->triangleCount = nverts;
|
||
|
|
||
|
memcpy(&dk->verts[call->triangleOffset], verts, sizeof(NVGvertex) * nverts);
|
||
|
|
||
|
// Fill shader
|
||
|
call->uniformOffset = dknvg__allocFragUniforms(dk, 1);
|
||
|
if (call->uniformOffset == -1) goto error;
|
||
|
frag = nvg__fragUniformPtr(dk, call->uniformOffset);
|
||
|
dknvg__convertPaint(dk, frag, paint, scissor, 1.0f, fringe, -1.0f);
|
||
|
frag->type = NSVG_SHADER_IMG;
|
||
|
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
// We get here if call alloc was ok, but something else is not.
|
||
|
// Roll back the last call to prevent drawing it.
|
||
|
if (dk->ncalls > 0) dk->ncalls--;
|
||
|
}
|
||
|
|
||
|
static void dknvg__renderDelete(void* uptr) {
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)uptr;
|
||
|
if (dk == NULL) return;
|
||
|
|
||
|
free(dk->paths);
|
||
|
free(dk->verts);
|
||
|
free(dk->uniforms);
|
||
|
free(dk->calls);
|
||
|
|
||
|
free(dk);
|
||
|
}
|
||
|
|
||
|
NVGcontext* nvgCreateDk(nvg::DkRenderer *renderer, int flags) {
|
||
|
NVGparams params;
|
||
|
NVGcontext* ctx = NULL;
|
||
|
DKNVGcontext* dk = (DKNVGcontext*)malloc(sizeof(DKNVGcontext));
|
||
|
if (dk == NULL) goto error;
|
||
|
memset(dk, 0, sizeof(DKNVGcontext));
|
||
|
|
||
|
memset(¶ms, 0, sizeof(params));
|
||
|
params.renderCreate = dknvg__renderCreate;
|
||
|
params.renderCreateTexture = dknvg__renderCreateTexture;
|
||
|
params.renderDeleteTexture = dknvg__renderDeleteTexture;
|
||
|
params.renderUpdateTexture = dknvg__renderUpdateTexture;
|
||
|
params.renderGetTextureSize = dknvg__renderGetTextureSize;
|
||
|
params.renderViewport = dknvg__renderViewport;
|
||
|
params.renderCancel = dknvg__renderCancel;
|
||
|
params.renderFlush = dknvg__renderFlush;
|
||
|
params.renderFill = dknvg__renderFill;
|
||
|
params.renderStroke = dknvg__renderStroke;
|
||
|
params.renderTriangles = dknvg__renderTriangles;
|
||
|
params.renderDelete = dknvg__renderDelete;
|
||
|
params.userPtr = dk;
|
||
|
params.edgeAntiAlias = flags & NVG_ANTIALIAS ? 1 : 0;
|
||
|
|
||
|
dk->renderer = renderer;
|
||
|
dk->flags = flags;
|
||
|
|
||
|
ctx = nvgCreateInternal(¶ms);
|
||
|
if (ctx == NULL) goto error;
|
||
|
|
||
|
return ctx;
|
||
|
|
||
|
error:
|
||
|
// 'dk' is freed by nvgDeleteInternal.
|
||
|
if (ctx != NULL) nvgDeleteInternal(ctx);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void nvgDeleteDk(NVGcontext* ctx)
|
||
|
{
|
||
|
nvgDeleteInternal(ctx);
|
||
|
}
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|