Merge pull request #200 from AsumFace/nvgimprovements

Some improvements to nanovega
This commit is contained in:
Adam D. Ruppe 2019-07-12 11:07:20 -04:00 committed by GitHub
commit 794ce6ecc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 385 additions and 303 deletions

View File

@ -143,11 +143,10 @@ $(SIDE_BY_SIDE
)
$(TIP
If you are going to use the library with a SDL OpenGL context,
try working with a backwards compatible context profile.
This library can use either inbuilt or BindBC (external dependency) provided bindings for OpenGL and FreeType.
Former are used by default, latter can be activated by passing the `bindbc` version specifier to the compiler.
)
Creating drawing context
========================
@ -524,7 +523,19 @@ version(Posix) {
} else {
version = nanovg_disable_fontconfig;
}
version(aliced) {
version (bindbc) {
version = nanovg_builtin_fontconfig_bindings;
version = nanovg_bindbc_opengl_bindings;
version = nanovg_bindbc_freetype_bindings;
version(BindFT_Dynamic)
static assert(0, "AsumFace was too lazy to write the code for the dynamic bindbc freetype bindings");
else {
version(BindFT_Static) {}
else
static assert(0, "well, duh. you got to pass the BindFT_Static version identifier to the compiler");
}
} else version(aliced) {
version = nanovg_default_no_font_aa;
version = nanovg_builtin_fontconfig_bindings;
version = nanovg_builtin_freetype_bindings;
@ -1291,7 +1302,7 @@ public enum NVGImageFlag : uint {
Premultiplied = 1<<4, /// Image data has premultiplied alpha.
ClampToBorderX = 1<<5, /// Clamp image to border (instead of clamping to edge by default)
ClampToBorderY = 1<<6, /// Clamp image to border (instead of clamping to edge by default)
NoFiltering = 1<<8, /// use GL_NEAREST instead of GL_LINEAR
NoFiltering = 1<<8, /// use GL_NEAREST instead of GL_LINEAR. Only affects upscaling if GenerateMipmaps is active.
Nearest = NoFiltering, /// compatibility with original NanoVG
NoDelete = 1<<16,/// Do not delete GL texture handle.
}
@ -9713,8 +9724,13 @@ FT_Error FT_Get_Kerning (FT_Face, FT_UInt, FT_UInt, FT_UInt, FT_Vector*);
void FT_Outline_Get_CBox (const(FT_Outline)*, FT_BBox*);
FT_Error FT_Outline_Decompose (FT_Outline*, const(FT_Outline_Funcs)*, void*);
}
} else version(bindbc) {
import bindbc.freetype;
alias FT_KERNING_DEFAULT = FT_Kerning_Mode.FT_KERNING_DEFAULT;
alias FT_KERNING_UNFITTED = FT_Kerning_Mode.FT_KERNING_UNFITTED;
alias FT_KERNING_UNSCALED = FT_Kerning_Mode.FT_KERNING_UNSCALED;
} else {
import iv.freetype;
import iv.freetype;
}
struct FONSttFontImpl {
@ -12145,15 +12161,36 @@ static if (__VERSION__ < 2076) {
//import arsd.simpledisplay;
version(nanovg_builtin_opengl_bindings) { import arsd.simpledisplay; } else { import iv.glbinds; }
version(nanovg_bindbc_opengl_bindings) {
import bindbc.opengl;
} else version(nanovg_builtin_opengl_bindings) {
import arsd.simpledisplay;
} else {
import iv.glbinds;
}
private:
// sdpy is missing that yet
static if (!is(typeof(GL_STENCIL_BUFFER_BIT))) enum uint GL_STENCIL_BUFFER_BIT = 0x00000400;
// OpenGL API missing from simpledisplay
private extern(System) nothrow @nogc {
version(bindbc){
private extern(System) nothrow @nogc:
// this definition doesn't exist in regular OpenGL (?)
enum uint GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9U;
private void nanovgInitOpenGL () {
// i'm not aware of calling the load multiple times having negative side effects, so i don't do an initialization check
GLSupport support = loadOpenGL();
if (support == GLSupport.noLibrary)
assert(0, "OpenGL initialization failed: shared library failed to load");
else if (support == GLSupport.badLibrary)
assert(0, "OpenGL initialization failed: a context-independent symbol failed to load");
else if (support == GLSupport.noContext)
assert(0, "OpenGL initialization failed: a context needs to be created prior to initialization");
}
} else { // OpenGL API missing from simpledisplay
private extern(System) nothrow @nogc {
alias GLvoid = void;
alias GLboolean = ubyte;
alias GLuint = uint;
@ -12246,6 +12283,8 @@ private extern(System) nothrow @nogc {
enum uint GL_FRAMEBUFFER_BINDING = 0x8CA6U;
enum uint GL_TEXTURE_LOD_BIAS = 0x8501;
/*
version(Windows) {
private void* kglLoad (const(char)* name) {
@ -12265,6 +12304,15 @@ private extern(System) nothrow @nogc {
}
*/
alias glbfn_glGenVertexArrays = void function(GLsizei, GLuint*);
__gshared glbfn_glGenVertexArrays glGenVertexArrays_NVGLZ; alias glGenVertexArrays = glGenVertexArrays_NVGLZ;
alias glbfn_glBindVertexArray = void function(GLuint);
__gshared glbfn_glBindVertexArray glBindVertexArray_NVGLZ; alias glBindVertexArray = glBindVertexArray_NVGLZ;
alias glbfn_glDeleteVertexArrays = void function(GLsizei, const(GLuint)*);
__gshared glbfn_glDeleteVertexArrays glDeleteVertexArrays_NVGLZ; alias glDeleteVertexArrays = glDeleteVertexArrays_NVGLZ;
alias glbfn_glGenerateMipmap = void function(GLenum);
__gshared glbfn_glGenerateMipmap glGenerateMipmap_NVGLZ; alias glGenerateMipmap = glGenerateMipmap_NVGLZ;
alias glbfn_glStencilMask = void function(GLuint);
__gshared glbfn_glStencilMask glStencilMask_NVGLZ; alias glStencilMask = glStencilMask_NVGLZ;
alias glbfn_glStencilFunc = void function(GLenum, GLint, GLuint);
@ -12357,6 +12405,15 @@ private extern(System) nothrow @nogc {
private void nanovgInitOpenGL () {
__gshared bool initialized = false;
if (initialized) return;
glGenVertexArrays_NVGLZ = cast(glbfn_glGenVertexArrays)glbindGetProcAddress(`glGenVertexArrays`);
if (glGenVertexArrays_NVGLZ is null) assert(0, `OpenGL function 'glGenVertexArrays' not found!`);
glBindVertexArray_NVGLZ = cast(glbfn_glBindVertexArray)glbindGetProcAddress(`glBindVertexArray`);
if (glBindVertexArray_NVGLZ is null) assert(0, `OpenGL function 'glBindVertexArray' not found!`);
glDeleteVertexArrays_NVGLZ = cast(glbfn_glDeleteVertexArrays)glbindGetProcAddress(`glDeleteVertexArrays`);
if (glDeleteVertexArrays_NVGLZ is null) assert(0, `OpenGL function 'glDeleteVertexArrays' not found!`);
glGenerateMipmap_NVGLZ = cast(glbfn_glGenerateMipmap)glbindGetProcAddress(`glGenerateMipmap`);
if (glGenerateMipmap_NVGLZ is null) assert(0, `OpenGL function 'glGenerateMipmap' not found!`);
glStencilMask_NVGLZ = cast(glbfn_glStencilMask)glbindGetProcAddress(`glStencilMask`);
if (glStencilMask_NVGLZ is null) assert(0, `OpenGL function 'glStencilMask' not found!`);
glStencilFunc_NVGLZ = cast(glbfn_glStencilFunc)glbindGetProcAddress(`glStencilFunc`);
@ -12445,12 +12502,13 @@ private extern(System) nothrow @nogc {
glGetIntegerv_NVGLZ = cast(glbfn_glGetIntegerv)glbindGetProcAddress(`glGetIntegerv`);
if (glGetIntegerv_NVGLZ is null) assert(0, `OpenGL function 'glGetIntegerv' not found!`);
initialized = true;
}
}
}
/// Context creation flags.
/// Group: context_management
public enum NVGContextFlag : int {
@ -13051,12 +13109,21 @@ void glnvg__copyFBOToFrom (GLNVGcontext* gl, int didx, int sidx) nothrow @truste
enum y = 0;
immutable int w = gl.fboWidth;
immutable int h = gl.fboHeight;
glBegin(GL_QUADS);
glVertex2i(x, y); // top-left
glVertex2i(w, y); // top-right
glVertex2i(w, h); // bottom-right
glVertex2i(x, h); // bottom-left
glEnd();
immutable(int[8]) vertices =
[x, y, // top-left
w, y, // top-right
w, h, // bottom-right
x, h]; // bottom-left
uint vbo;
glGenBuffers(1, &vbo); //TODO: figure out if allocating a new buffer each time is a good idea
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.sizeof, &vertices, GL_STREAM_DRAW);
uint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
// restore state (but don't unbind FBO)
static if (NANOVG_GL_USE_STATE_FILTER) glBindTexture(GL_TEXTURE_2D, gl.boundTexture);
@ -13402,16 +13469,20 @@ int glnvg__renderCreateTexture (void* uptr, NVGtexture type, int w, int h, int i
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
// GL 1.4 and later has support for generating mipmaps using a tex parameter.
if ((imageFlags&(NVGImageFlag.GenerateMipmaps|NVGImageFlag.NoFiltering)) == NVGImageFlag.GenerateMipmaps) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
immutable ttype = (type == NVGtexture.RGBA ? GL_RGBA : GL_RED);
glTexImage2D(GL_TEXTURE_2D, 0, ttype, w, h, 0, ttype, GL_UNSIGNED_BYTE, data);
// GL 3.0 and later have support for a dedicated function for generating mipmaps
// it needs to be called after the glTexImage2D call
if (imageFlags & NVGImageFlag.GenerateMipmaps)
glGenerateMipmap(GL_TEXTURE_2D);
immutable tfmin =
(imageFlags&NVGImageFlag.NoFiltering ? GL_NEAREST :
imageFlags&NVGImageFlag.GenerateMipmaps ? GL_LINEAR_MIPMAP_LINEAR :
(imageFlags & NVGImageFlag.GenerateMipmaps ? GL_LINEAR_MIPMAP_LINEAR :
imageFlags & NVGImageFlag.NoFiltering ? GL_NEAREST :
GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -1.0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tfmin);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (imageFlags&NVGImageFlag.NoFiltering ? GL_NEAREST : GL_LINEAR));
@ -13652,12 +13723,22 @@ void glnvg__finishClip (GLNVGcontext* gl, NVGClipMode clipmode) nothrow @trusted
glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x00, 0xff);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
}
glBegin(GL_QUADS);
glVertex2i(0, 0);
glVertex2i(0, gl.fboHeight);
glVertex2i(gl.fboWidth, gl.fboHeight);
glVertex2i(gl.fboWidth, 0);
glEnd();
immutable(int[8]) vertices =
[0, 0,
0, gl.fboHeight,
gl.fboWidth, gl.fboHeight,
gl.fboWidth, 0];
uint vbo;
glGenBuffers(1, &vbo); //TODO: figure out if allocating a new buffer each time is a good idea
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.sizeof, &vertices, GL_STREAM_DRAW);
uint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
//glnvg__restoreAffine(gl);
}
@ -14538,6 +14619,7 @@ public NVGContext nvgCreateContext (const(NVGContextFlag)[] flagList...) nothrow
NVGparams params = void;
NVGContext ctx = null;
version(nanovg_builtin_opengl_bindings) nanovgInitOpenGL(); // why not?
version(nanovg_bindbc_opengl_bindings) nanovgInitOpenGL();
GLNVGcontext* gl = cast(GLNVGcontext*)malloc(GLNVGcontext.sizeof);
if (gl is null) goto error;
memset(gl, 0, GLNVGcontext.sizeof);