|
@@ -60,20 +60,8 @@ void nvgDeleteGL3(struct NVGcontext* ctx); |
|
|
#include "nanovg.h" |
|
|
#include "nanovg.h" |
|
|
|
|
|
|
|
|
enum GLNVGuniformLoc { |
|
|
enum GLNVGuniformLoc { |
|
|
GLNVG_LOC_VIEWSIZE, |
|
|
|
|
|
GLNVG_LOC_SCISSORMAT, |
|
|
|
|
|
GLNVG_LOC_SCISSOREXT, |
|
|
|
|
|
GLNVG_LOC_SCISSORSCALE, |
|
|
|
|
|
GLNVG_LOC_PAINTMAT, |
|
|
|
|
|
GLNVG_LOC_EXTENT, |
|
|
|
|
|
GLNVG_LOC_RADIUS, |
|
|
|
|
|
GLNVG_LOC_FEATHER, |
|
|
|
|
|
GLNVG_LOC_INNERCOL, |
|
|
|
|
|
GLNVG_LOC_OUTERCOL, |
|
|
|
|
|
GLNVG_LOC_STROKEMULT, |
|
|
|
|
|
GLNVG_LOC_TEX, |
|
|
|
|
|
GLNVG_LOC_TEXTYPE, |
|
|
|
|
|
GLNVG_LOC_TYPE, |
|
|
|
|
|
|
|
|
GLNVG_LOC_UBOVIEW, |
|
|
|
|
|
GLNVG_LOC_UBOFRAG, |
|
|
GLNVG_MAX_LOCS |
|
|
GLNVG_MAX_LOCS |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@@ -84,6 +72,11 @@ enum GLNVGshaderType { |
|
|
NSVG_SHADER_IMG |
|
|
NSVG_SHADER_IMG |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
enum GLNVGuniformBindings { |
|
|
|
|
|
GLNVG_UBO_VIEW_BINDING = 0, |
|
|
|
|
|
GLNVG_UBO_FRAG_BINDING = 1, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
struct GLNVGshader { |
|
|
struct GLNVGshader { |
|
|
GLuint prog; |
|
|
GLuint prog; |
|
|
GLuint frag; |
|
|
GLuint frag; |
|
@@ -123,15 +116,33 @@ struct GLNVGpath { |
|
|
int convex; |
|
|
int convex; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct GLNVGuboFrag { |
|
|
|
|
|
float scissorMat[12]; // matrices are actually 3 vec4s |
|
|
|
|
|
float paintMat[12]; |
|
|
|
|
|
float innerCol[4]; |
|
|
|
|
|
float outerCol[4]; |
|
|
|
|
|
float scissorExt[2]; |
|
|
|
|
|
float scissorScale[2]; |
|
|
|
|
|
float extent[2]; |
|
|
|
|
|
float radius; |
|
|
|
|
|
float feather; |
|
|
|
|
|
float strokeMult; |
|
|
|
|
|
int texType; |
|
|
|
|
|
int type; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
struct GLNVGcontext { |
|
|
struct GLNVGcontext { |
|
|
struct GLNVGshader shader; |
|
|
struct GLNVGshader shader; |
|
|
struct GLNVGtexture* textures; |
|
|
struct GLNVGtexture* textures; |
|
|
float viewWidth, viewHeight; |
|
|
|
|
|
|
|
|
float view[2]; |
|
|
int ntextures; |
|
|
int ntextures; |
|
|
int ctextures; |
|
|
int ctextures; |
|
|
int textureId; |
|
|
int textureId; |
|
|
GLuint vertArr; |
|
|
GLuint vertArr; |
|
|
GLuint vertBuf; |
|
|
GLuint vertBuf; |
|
|
|
|
|
GLuint uboViewBuf; |
|
|
|
|
|
GLuint uboFragBuf; |
|
|
|
|
|
int uboPosAlignment; |
|
|
int edgeAntiAlias; |
|
|
int edgeAntiAlias; |
|
|
|
|
|
|
|
|
struct GLNVGcall* calls; |
|
|
struct GLNVGcall* calls; |
|
@@ -145,6 +156,8 @@ struct GLNVGcontext { |
|
|
int nverts; |
|
|
int nverts; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct GLNVGtexture* glnvg__allocTexture(struct GLNVGcontext* gl) |
|
|
static struct GLNVGtexture* glnvg__allocTexture(struct GLNVGcontext* gl) |
|
|
{ |
|
|
{ |
|
|
struct GLNVGtexture* tex = NULL; |
|
|
struct GLNVGtexture* tex = NULL; |
|
@@ -283,20 +296,8 @@ static void glnvg__deleteShader(struct GLNVGshader* shader) |
|
|
|
|
|
|
|
|
static void glnvg__getUniforms(struct GLNVGshader* shader) |
|
|
static void glnvg__getUniforms(struct GLNVGshader* shader) |
|
|
{ |
|
|
{ |
|
|
shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_SCISSORMAT] = glGetUniformLocation(shader->prog, "scissorMat"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_SCISSOREXT] = glGetUniformLocation(shader->prog, "scissorExt"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_SCISSORSCALE] = glGetUniformLocation(shader->prog, "scissorScale"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_PAINTMAT] = glGetUniformLocation(shader->prog, "paintMat"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_EXTENT] = glGetUniformLocation(shader->prog, "extent"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_RADIUS] = glGetUniformLocation(shader->prog, "radius"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_FEATHER] = glGetUniformLocation(shader->prog, "feather"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_INNERCOL] = glGetUniformLocation(shader->prog, "innerCol"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_OUTERCOL] = glGetUniformLocation(shader->prog, "outerCol"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_STROKEMULT] = glGetUniformLocation(shader->prog, "strokeMult"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_TEXTYPE] = glGetUniformLocation(shader->prog, "texType"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_TYPE] = glGetUniformLocation(shader->prog, "type"); |
|
|
|
|
|
|
|
|
shader->loc[GLNVG_LOC_UBOVIEW] = glGetUniformBlockIndex(shader->prog, "uboView"); |
|
|
|
|
|
shader->loc[GLNVG_LOC_UBOFRAG] = glGetUniformBlockIndex(shader->prog, "uboFrag"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int glnvg__renderCreate(void* uptr) |
|
|
static int glnvg__renderCreate(void* uptr) |
|
@@ -310,7 +311,9 @@ static int glnvg__renderCreate(void* uptr) |
|
|
#else |
|
|
#else |
|
|
"#version 150 core\n" |
|
|
"#version 150 core\n" |
|
|
#endif |
|
|
#endif |
|
|
"uniform vec2 viewSize;\n" |
|
|
|
|
|
|
|
|
"layout(std140) uniform uboView {\n" |
|
|
|
|
|
" vec2 viewSize;\n" |
|
|
|
|
|
"};\n" |
|
|
"in vec2 vertex;\n" |
|
|
"in vec2 vertex;\n" |
|
|
"in vec2 tcoord;\n" |
|
|
"in vec2 tcoord;\n" |
|
|
"out vec2 ftcoord;\n" |
|
|
"out vec2 ftcoord;\n" |
|
@@ -328,19 +331,21 @@ static int glnvg__renderCreate(void* uptr) |
|
|
#else |
|
|
#else |
|
|
"#version 150 core\n" |
|
|
"#version 150 core\n" |
|
|
#endif |
|
|
#endif |
|
|
"uniform mat3 scissorMat;\n" |
|
|
|
|
|
"uniform vec2 scissorExt;\n" |
|
|
|
|
|
"uniform vec2 scissorScale;\n" |
|
|
|
|
|
"uniform mat3 paintMat;\n" |
|
|
|
|
|
"uniform vec2 extent;\n" |
|
|
|
|
|
"uniform float radius;\n" |
|
|
|
|
|
"uniform float feather;\n" |
|
|
|
|
|
"uniform vec4 innerCol;\n" |
|
|
|
|
|
"uniform vec4 outerCol;\n" |
|
|
|
|
|
"uniform float strokeMult;\n" |
|
|
|
|
|
|
|
|
"layout(std140) uniform uboFrag {\n" |
|
|
|
|
|
" mat3 scissorMat;\n" |
|
|
|
|
|
" mat3 paintMat;\n" |
|
|
|
|
|
" vec4 innerCol;\n" |
|
|
|
|
|
" vec4 outerCol;\n" |
|
|
|
|
|
" vec2 scissorExt;\n" |
|
|
|
|
|
" vec2 scissorScale;\n" |
|
|
|
|
|
" vec2 extent;\n" |
|
|
|
|
|
" float radius;\n" |
|
|
|
|
|
" float feather;\n" |
|
|
|
|
|
" float strokeMult;\n" |
|
|
|
|
|
" int texType;\n" |
|
|
|
|
|
" int type;\n" |
|
|
|
|
|
"};\n" |
|
|
"uniform sampler2D tex;\n" |
|
|
"uniform sampler2D tex;\n" |
|
|
"uniform int texType;\n" |
|
|
|
|
|
"uniform int type;\n" |
|
|
|
|
|
"in vec2 ftcoord;\n" |
|
|
"in vec2 ftcoord;\n" |
|
|
"in vec2 fpos;\n" |
|
|
"in vec2 fpos;\n" |
|
|
"out vec4 outColor;\n" |
|
|
"out vec4 outColor;\n" |
|
@@ -400,19 +405,21 @@ static int glnvg__renderCreate(void* uptr) |
|
|
#else |
|
|
#else |
|
|
"#version 150 core\n" |
|
|
"#version 150 core\n" |
|
|
#endif |
|
|
#endif |
|
|
"uniform mat3 scissorMat;\n" |
|
|
|
|
|
"uniform vec2 scissorExt;\n" |
|
|
|
|
|
"uniform vec2 scissorScale;\n" |
|
|
|
|
|
"uniform mat3 paintMat;\n" |
|
|
|
|
|
"uniform vec2 extent;\n" |
|
|
|
|
|
"uniform float radius;\n" |
|
|
|
|
|
"uniform float feather;\n" |
|
|
|
|
|
"uniform vec4 innerCol;\n" |
|
|
|
|
|
"uniform vec4 outerCol;\n" |
|
|
|
|
|
"uniform float strokeMult;\n" |
|
|
|
|
|
|
|
|
"layout(std140) uniform uboFrag {\n" |
|
|
|
|
|
" mat3 scissorMat;\n" |
|
|
|
|
|
" mat3 paintMat;\n" |
|
|
|
|
|
" vec4 innerCol;\n" |
|
|
|
|
|
" vec4 outerCol;\n" |
|
|
|
|
|
" vec2 scissorExt;\n" |
|
|
|
|
|
" vec2 scissorScale;\n" |
|
|
|
|
|
" vec2 extent;\n" |
|
|
|
|
|
" float radius;\n" |
|
|
|
|
|
" float feather;\n" |
|
|
|
|
|
" float strokeMult;\n" |
|
|
|
|
|
" int texType;\n" |
|
|
|
|
|
" int type;\n" |
|
|
|
|
|
"};\n" |
|
|
"uniform sampler2D tex;\n" |
|
|
"uniform sampler2D tex;\n" |
|
|
"uniform int texType;\n" |
|
|
|
|
|
"uniform int type;\n" |
|
|
|
|
|
"in vec2 ftcoord;\n" |
|
|
"in vec2 ftcoord;\n" |
|
|
"in vec2 fpos;\n" |
|
|
"in vec2 fpos;\n" |
|
|
"out vec4 outColor;\n" |
|
|
"out vec4 outColor;\n" |
|
@@ -475,6 +482,14 @@ static int glnvg__renderCreate(void* uptr) |
|
|
glGenVertexArrays(1, &gl->vertArr); |
|
|
glGenVertexArrays(1, &gl->vertArr); |
|
|
glGenBuffers(1, &gl->vertBuf); |
|
|
glGenBuffers(1, &gl->vertBuf); |
|
|
|
|
|
|
|
|
|
|
|
// Create UBOs |
|
|
|
|
|
glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_UBOVIEW], GLNVG_UBO_VIEW_BINDING); |
|
|
|
|
|
glGenBuffers(1, &gl->uboViewBuf); |
|
|
|
|
|
glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_UBOFRAG], GLNVG_UBO_FRAG_BINDING); |
|
|
|
|
|
glGenBuffers(1, &gl->uboFragBuf); |
|
|
|
|
|
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &gl->uboPosAlignment); |
|
|
|
|
|
gl->uboPosAlignment = sizeof( struct GLNVGuboFrag ) + gl->uboPosAlignment - sizeof( struct GLNVGuboFrag ) % gl->uboPosAlignment; |
|
|
|
|
|
|
|
|
glnvg__checkError("done"); |
|
|
glnvg__checkError("done"); |
|
|
|
|
|
|
|
|
return 1; |
|
|
return 1; |
|
@@ -595,84 +610,94 @@ static void glnvg__xformToMat3x3(float* m3, float* t) |
|
|
m3[8] = 1.0f; |
|
|
m3[8] = 1.0f; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor, float width) |
|
|
|
|
|
|
|
|
static void glnvg__xformToMat3x4(float* m3, float* t) |
|
|
{ |
|
|
{ |
|
|
float innerCol[4]; |
|
|
|
|
|
float outerCol[4]; |
|
|
|
|
|
glnvg__toFloatColor(innerCol, paint->innerColor); |
|
|
|
|
|
glnvg__toFloatColor(outerCol, paint->outerColor); |
|
|
|
|
|
|
|
|
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 int glnvg__setupPaintUBO(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor, float width, struct GLNVGuboFrag* uboBuff) |
|
|
|
|
|
{ |
|
|
|
|
|
struct GLNVGuboFrag ubo; |
|
|
|
|
|
glnvg__toFloatColor(ubo.innerCol, paint->innerColor); |
|
|
|
|
|
glnvg__toFloatColor(ubo.outerCol, paint->outerColor); |
|
|
struct GLNVGtexture* tex = NULL; |
|
|
struct GLNVGtexture* tex = NULL; |
|
|
float invxform[6], paintMat[9], scissorMat[9]; |
|
|
|
|
|
float scissorx = 0, scissory = 0; |
|
|
|
|
|
float scissorsx = 0, scissorsy = 0; |
|
|
|
|
|
|
|
|
float invxform[6]; |
|
|
|
|
|
|
|
|
glnvg__xformInverse(invxform, paint->xform); |
|
|
glnvg__xformInverse(invxform, paint->xform); |
|
|
glnvg__xformToMat3x3(paintMat, invxform); |
|
|
|
|
|
|
|
|
glnvg__xformToMat3x4(ubo.paintMat, invxform); |
|
|
|
|
|
|
|
|
if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) { |
|
|
if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) { |
|
|
memset(scissorMat, 0, sizeof(scissorMat)); |
|
|
|
|
|
scissorx = 1.0f; |
|
|
|
|
|
scissory = 1.0f; |
|
|
|
|
|
scissorsx = 1.0f; |
|
|
|
|
|
scissorsy = 1.0f; |
|
|
|
|
|
|
|
|
memset(ubo.scissorMat, 0, sizeof(ubo.scissorMat)); |
|
|
|
|
|
ubo.scissorExt[0] = 1.0f; |
|
|
|
|
|
ubo.scissorExt[1] = 1.0f; |
|
|
|
|
|
ubo.scissorScale[0] = 1.0f; |
|
|
|
|
|
ubo.scissorScale[1] = 1.0f; |
|
|
} else { |
|
|
} else { |
|
|
glnvg__xformInverse(invxform, scissor->xform); |
|
|
glnvg__xformInverse(invxform, scissor->xform); |
|
|
glnvg__xformToMat3x3(scissorMat, invxform); |
|
|
|
|
|
scissorx = scissor->extent[0]; |
|
|
|
|
|
scissory = scissor->extent[1]; |
|
|
|
|
|
scissorsx = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]); |
|
|
|
|
|
scissorsy = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]); |
|
|
|
|
|
|
|
|
glnvg__xformToMat3x4(ubo.scissorMat, invxform); |
|
|
|
|
|
ubo.scissorExt[0] = scissor->extent[0]; |
|
|
|
|
|
ubo.scissorExt[1] = scissor->extent[1]; |
|
|
|
|
|
ubo.scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]); |
|
|
|
|
|
ubo.scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]); |
|
|
} |
|
|
} |
|
|
|
|
|
memcpy( ubo.extent, paint->extent, sizeof( ubo.extent ) ); |
|
|
|
|
|
ubo.strokeMult = width*0.5f + 0.5f; |
|
|
|
|
|
|
|
|
if (paint->image != 0) { |
|
|
if (paint->image != 0) { |
|
|
tex = glnvg__findTexture(gl, paint->image); |
|
|
tex = glnvg__findTexture(gl, paint->image); |
|
|
if (tex == NULL) return 0; |
|
|
if (tex == NULL) return 0; |
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLIMG); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight); |
|
|
|
|
|
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy); |
|
|
|
|
|
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]); |
|
|
|
|
|
glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], width*0.5f + 0.5f); |
|
|
|
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0); |
|
|
|
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1); |
|
|
|
|
|
|
|
|
ubo.type = NSVG_SHADER_FILLIMG; |
|
|
|
|
|
ubo.texType = tex->type == NVG_TEXTURE_RGBA ? 0 : 1; |
|
|
glnvg__checkError("tex paint loc"); |
|
|
glnvg__checkError("tex paint loc"); |
|
|
glBindTexture(GL_TEXTURE_2D, tex->tex); |
|
|
|
|
|
glnvg__checkError("tex paint tex"); |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLGRAD); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight); |
|
|
|
|
|
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy); |
|
|
|
|
|
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]); |
|
|
|
|
|
glUniform1f(gl->shader.loc[GLNVG_LOC_RADIUS], paint->radius); |
|
|
|
|
|
glUniform1f(gl->shader.loc[GLNVG_LOC_FEATHER], paint->feather); |
|
|
|
|
|
glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, innerCol); |
|
|
|
|
|
glUniform4fv(gl->shader.loc[GLNVG_LOC_OUTERCOL], 1, outerCol); |
|
|
|
|
|
glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], width*0.5f + 0.5f); |
|
|
|
|
|
|
|
|
ubo.type = NSVG_SHADER_FILLGRAD; |
|
|
|
|
|
ubo.radius = paint->radius; |
|
|
|
|
|
ubo.feather = paint->feather; |
|
|
glnvg__checkError("grad paint loc"); |
|
|
glnvg__checkError("grad paint loc"); |
|
|
} |
|
|
} |
|
|
|
|
|
*uboBuff = ubo; |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, int* uboPos) |
|
|
|
|
|
{ |
|
|
|
|
|
glBindBufferRange( GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag)); |
|
|
|
|
|
*uboPos += gl->uboPosAlignment; |
|
|
|
|
|
if (paint->image != 0) { |
|
|
|
|
|
struct GLNVGtexture* tex = glnvg__findTexture(gl, paint->image); |
|
|
|
|
|
if (tex == NULL) return 0; |
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex->tex); |
|
|
|
|
|
glnvg__checkError("tex paint tex"); |
|
|
|
|
|
} |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void glnvg__renderViewport(void* uptr, int width, int height) |
|
|
static void glnvg__renderViewport(void* uptr, int width, int height) |
|
|
{ |
|
|
{ |
|
|
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr; |
|
|
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr; |
|
|
gl->viewWidth = (float)width; |
|
|
|
|
|
gl->viewHeight = (float)height; |
|
|
|
|
|
|
|
|
gl->view[0] = (float)width; |
|
|
|
|
|
gl->view[1] = (float)height; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
|
|
|
|
|
|
static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos ) |
|
|
{ |
|
|
{ |
|
|
struct GLNVGpath* paths = &gl->paths[call->pathOffset]; |
|
|
struct GLNVGpath* paths = &gl->paths[call->pathOffset]; |
|
|
int npaths = call->pathCount, offset, i; |
|
|
|
|
|
|
|
|
int npaths = call->pathCount, i; |
|
|
|
|
|
|
|
|
if (npaths == 1 && paths[0].convex) { |
|
|
if (npaths == 1 && paths[0].convex) { |
|
|
|
|
|
|
|
|
glnvg__setupPaint(gl, &call->paint, &call->scissor, 1.0001f); |
|
|
|
|
|
|
|
|
glnvg__setupPaint(gl, &call->paint, uboPos); |
|
|
|
|
|
|
|
|
for (i = 0; i < npaths; i++) { |
|
|
for (i = 0; i < npaths; i++) { |
|
|
glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); |
|
|
glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); |
|
@@ -694,8 +719,9 @@ static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
glStencilFunc(GL_ALWAYS, 0, ~0); |
|
|
glStencilFunc(GL_ALWAYS, 0, ~0); |
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
|
|
|
|
|
|
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_SIMPLE); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight); |
|
|
|
|
|
|
|
|
// set bindpoint for solid loc |
|
|
|
|
|
glBindBufferRange( GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag)); |
|
|
|
|
|
*uboPos += gl->uboPosAlignment; |
|
|
glnvg__checkError("fill solid loc"); |
|
|
glnvg__checkError("fill solid loc"); |
|
|
|
|
|
|
|
|
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); |
|
|
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); |
|
@@ -710,7 +736,7 @@ static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
|
|
glEnable(GL_BLEND); |
|
|
glEnable(GL_BLEND); |
|
|
|
|
|
|
|
|
glnvg__setupPaint(gl, &call->paint, &call->scissor, 1.0001f); |
|
|
|
|
|
|
|
|
glnvg__setupPaint(gl, &call->paint, uboPos); |
|
|
|
|
|
|
|
|
if (gl->edgeAntiAlias) { |
|
|
if (gl->edgeAntiAlias) { |
|
|
glStencilFunc(GL_EQUAL, 0x00, 0xff); |
|
|
glStencilFunc(GL_EQUAL, 0x00, 0xff); |
|
@@ -731,12 +757,12 @@ static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
|
|
|
|
|
|
static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos) |
|
|
{ |
|
|
{ |
|
|
struct GLNVGpath* paths = &gl->paths[call->pathOffset]; |
|
|
struct GLNVGpath* paths = &gl->paths[call->pathOffset]; |
|
|
int npaths = call->pathCount, offset, i; |
|
|
|
|
|
|
|
|
int npaths = call->pathCount, i; |
|
|
|
|
|
|
|
|
glnvg__setupPaint(gl, &call->paint, &call->scissor, call->strokeWidth); |
|
|
|
|
|
|
|
|
glnvg__setupPaint(gl, &call->paint, uboPos); |
|
|
|
|
|
|
|
|
// Draw Strokes |
|
|
// Draw Strokes |
|
|
for (i = 0; i < npaths; i++) { |
|
|
for (i = 0; i < npaths; i++) { |
|
@@ -744,22 +770,15 @@ static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
|
|
|
|
|
|
static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos) |
|
|
{ |
|
|
{ |
|
|
struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image); |
|
|
struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image); |
|
|
int offset = call->triangleOffset * sizeof(struct NVGvertex); |
|
|
|
|
|
float color[4]; |
|
|
|
|
|
|
|
|
|
|
|
if (tex != NULL) { |
|
|
if (tex != NULL) { |
|
|
glBindTexture(GL_TEXTURE_2D, tex->tex); |
|
|
glBindTexture(GL_TEXTURE_2D, tex->tex); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_IMG); |
|
|
|
|
|
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight); |
|
|
|
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0); |
|
|
|
|
|
glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1); |
|
|
|
|
|
glnvg__toFloatColor(color, call->paint.innerColor); |
|
|
|
|
|
glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, color ); |
|
|
|
|
|
|
|
|
glBindBufferRange( GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag)); |
|
|
|
|
|
*uboPos += gl->uboPosAlignment; |
|
|
glnvg__checkError("tris solid img loc"); |
|
|
glnvg__checkError("tris solid img loc"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -769,13 +788,46 @@ static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call) |
|
|
static void glnvg__renderFlush(void* uptr) |
|
|
static void glnvg__renderFlush(void* uptr) |
|
|
{ |
|
|
{ |
|
|
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr; |
|
|
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr; |
|
|
int i; |
|
|
|
|
|
|
|
|
int i, uboPos; |
|
|
|
|
|
|
|
|
if (gl->ncalls > 0) { |
|
|
if (gl->ncalls > 0) { |
|
|
|
|
|
|
|
|
glUseProgram(gl->shader.prog); |
|
|
glUseProgram(gl->shader.prog); |
|
|
glEnable(GL_CULL_FACE); |
|
|
glEnable(GL_CULL_FACE); |
|
|
|
|
|
|
|
|
|
|
|
// upload ubo for frag shaders - maximum ubos is 2x num calls |
|
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, gl->uboFragBuf); |
|
|
|
|
|
glBufferData(GL_UNIFORM_BUFFER, 2 * gl->ncalls * sizeof(struct GLNVGuboFrag), 0, GL_STREAM_DRAW); |
|
|
|
|
|
char* buff = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY ); |
|
|
|
|
|
for (i = 0; i < gl->ncalls; i++) { |
|
|
|
|
|
struct GLNVGcall* call = &gl->calls[i]; |
|
|
|
|
|
struct GLNVGuboFrag* ubo = (struct GLNVGuboFrag*)buff; |
|
|
|
|
|
if (call->type == GLNVG_FILL) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!(call->pathCount == 1 && gl->paths[call->pathOffset].convex)) { |
|
|
|
|
|
ubo->type = NSVG_SHADER_SIMPLE; |
|
|
|
|
|
buff += gl->uboPosAlignment;; |
|
|
|
|
|
ubo = (struct GLNVGuboFrag*)buff; |
|
|
|
|
|
} |
|
|
|
|
|
glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, 1.0001f, ubo); |
|
|
|
|
|
buff += gl->uboPosAlignment; |
|
|
|
|
|
} |
|
|
|
|
|
else if (call->type == GLNVG_STROKE) |
|
|
|
|
|
{ |
|
|
|
|
|
glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, call->strokeWidth, ubo); |
|
|
|
|
|
buff += gl->uboPosAlignment; |
|
|
|
|
|
} |
|
|
|
|
|
else if (call->type == GLNVG_TRIANGLES) |
|
|
|
|
|
{ |
|
|
|
|
|
struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image); |
|
|
|
|
|
glnvg__toFloatColor(ubo->innerCol, call->paint.innerColor); |
|
|
|
|
|
ubo->texType = tex->type == NVG_TEXTURE_RGBA ? 0 : 1; |
|
|
|
|
|
ubo->type = NSVG_SHADER_IMG; |
|
|
|
|
|
buff += gl->uboPosAlignment; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
glUnmapBuffer(GL_UNIFORM_BUFFER); |
|
|
|
|
|
|
|
|
// Upload vertex data |
|
|
// Upload vertex data |
|
|
glBindVertexArray(gl->vertArr); |
|
|
glBindVertexArray(gl->vertArr); |
|
|
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf); |
|
|
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf); |
|
@@ -784,15 +836,24 @@ static void glnvg__renderFlush(void* uptr) |
|
|
glEnableVertexAttribArray(1); |
|
|
glEnableVertexAttribArray(1); |
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)0); |
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)0); |
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(0 + 2*sizeof(float))); |
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(0 + 2*sizeof(float))); |
|
|
|
|
|
|
|
|
|
|
|
// once per frame set ubo for view |
|
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, gl->uboViewBuf); |
|
|
|
|
|
glBufferData(GL_UNIFORM_BUFFER, sizeof(gl->view), 0, GL_STREAM_DRAW); |
|
|
|
|
|
glBufferData(GL_UNIFORM_BUFFER, sizeof(gl->view), gl->view, GL_STREAM_DRAW); |
|
|
|
|
|
glBindBufferBase(GL_UNIFORM_BUFFER, GLNVG_UBO_VIEW_BINDING, gl->uboViewBuf); |
|
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, gl->uboFragBuf); |
|
|
|
|
|
uboPos = 0; |
|
|
|
|
|
|
|
|
for (i = 0; i < gl->ncalls; i++) { |
|
|
for (i = 0; i < gl->ncalls; i++) { |
|
|
struct GLNVGcall* call = &gl->calls[i]; |
|
|
struct GLNVGcall* call = &gl->calls[i]; |
|
|
if (call->type == GLNVG_FILL) |
|
|
if (call->type == GLNVG_FILL) |
|
|
glnvg__fill(gl, call); |
|
|
|
|
|
|
|
|
glnvg__fill(gl, call, &uboPos); |
|
|
else if (call->type == GLNVG_STROKE) |
|
|
else if (call->type == GLNVG_STROKE) |
|
|
glnvg__stroke(gl, call); |
|
|
|
|
|
|
|
|
glnvg__stroke(gl, call, &uboPos); |
|
|
else if (call->type == GLNVG_TRIANGLES) |
|
|
else if (call->type == GLNVG_TRIANGLES) |
|
|
glnvg__triangles(gl, call); |
|
|
|
|
|
|
|
|
glnvg__triangles(gl, call, &uboPos); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
glDisableVertexAttribArray(0); |
|
|