mirror of https://github.com/adamdruppe/arsd.git
Merge pull request #200 from AsumFace/nvgimprovements
Some improvements to nanovega
This commit is contained in:
commit
794ce6ecc5
130
nanovega.d
130
nanovega.d
|
@ -143,11 +143,10 @@ $(SIDE_BY_SIDE
|
||||||
)
|
)
|
||||||
|
|
||||||
$(TIP
|
$(TIP
|
||||||
If you are going to use the library with a SDL OpenGL context,
|
This library can use either inbuilt or BindBC (external dependency) provided bindings for OpenGL and FreeType.
|
||||||
try working with a backwards compatible context profile.
|
Former are used by default, latter can be activated by passing the `bindbc` version specifier to the compiler.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
Creating drawing context
|
Creating drawing context
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -524,7 +523,19 @@ version(Posix) {
|
||||||
} else {
|
} else {
|
||||||
version = nanovg_disable_fontconfig;
|
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_default_no_font_aa;
|
||||||
version = nanovg_builtin_fontconfig_bindings;
|
version = nanovg_builtin_fontconfig_bindings;
|
||||||
version = nanovg_builtin_freetype_bindings;
|
version = nanovg_builtin_freetype_bindings;
|
||||||
|
@ -1291,7 +1302,7 @@ public enum NVGImageFlag : uint {
|
||||||
Premultiplied = 1<<4, /// Image data has premultiplied alpha.
|
Premultiplied = 1<<4, /// Image data has premultiplied alpha.
|
||||||
ClampToBorderX = 1<<5, /// Clamp image to border (instead of clamping to edge by default)
|
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)
|
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
|
Nearest = NoFiltering, /// compatibility with original NanoVG
|
||||||
NoDelete = 1<<16,/// Do not delete GL texture handle.
|
NoDelete = 1<<16,/// Do not delete GL texture handle.
|
||||||
}
|
}
|
||||||
|
@ -9713,6 +9724,11 @@ 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*);
|
void FT_Outline_Get_CBox (const(FT_Outline)*, FT_BBox*);
|
||||||
FT_Error FT_Outline_Decompose (FT_Outline*, const(FT_Outline_Funcs)*, void*);
|
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 {
|
} else {
|
||||||
import iv.freetype;
|
import iv.freetype;
|
||||||
}
|
}
|
||||||
|
@ -12145,14 +12161,35 @@ static if (__VERSION__ < 2076) {
|
||||||
|
|
||||||
|
|
||||||
//import arsd.simpledisplay;
|
//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:
|
private:
|
||||||
// sdpy is missing that yet
|
// sdpy is missing that yet
|
||||||
static if (!is(typeof(GL_STENCIL_BUFFER_BIT))) enum uint GL_STENCIL_BUFFER_BIT = 0x00000400;
|
static if (!is(typeof(GL_STENCIL_BUFFER_BIT))) enum uint GL_STENCIL_BUFFER_BIT = 0x00000400;
|
||||||
|
|
||||||
|
|
||||||
// OpenGL API missing from simpledisplay
|
|
||||||
|
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 {
|
private extern(System) nothrow @nogc {
|
||||||
alias GLvoid = void;
|
alias GLvoid = void;
|
||||||
alias GLboolean = ubyte;
|
alias GLboolean = ubyte;
|
||||||
|
@ -12246,6 +12283,8 @@ private extern(System) nothrow @nogc {
|
||||||
|
|
||||||
enum uint GL_FRAMEBUFFER_BINDING = 0x8CA6U;
|
enum uint GL_FRAMEBUFFER_BINDING = 0x8CA6U;
|
||||||
|
|
||||||
|
enum uint GL_TEXTURE_LOD_BIAS = 0x8501;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
private void* kglLoad (const(char)* name) {
|
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);
|
alias glbfn_glStencilMask = void function(GLuint);
|
||||||
__gshared glbfn_glStencilMask glStencilMask_NVGLZ; alias glStencilMask = glStencilMask_NVGLZ;
|
__gshared glbfn_glStencilMask glStencilMask_NVGLZ; alias glStencilMask = glStencilMask_NVGLZ;
|
||||||
alias glbfn_glStencilFunc = void function(GLenum, GLint, GLuint);
|
alias glbfn_glStencilFunc = void function(GLenum, GLint, GLuint);
|
||||||
|
@ -12357,6 +12405,15 @@ private extern(System) nothrow @nogc {
|
||||||
private void nanovgInitOpenGL () {
|
private void nanovgInitOpenGL () {
|
||||||
__gshared bool initialized = false;
|
__gshared bool initialized = false;
|
||||||
if (initialized) return;
|
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`);
|
glStencilMask_NVGLZ = cast(glbfn_glStencilMask)glbindGetProcAddress(`glStencilMask`);
|
||||||
if (glStencilMask_NVGLZ is null) assert(0, `OpenGL function 'glStencilMask' not found!`);
|
if (glStencilMask_NVGLZ is null) assert(0, `OpenGL function 'glStencilMask' not found!`);
|
||||||
glStencilFunc_NVGLZ = cast(glbfn_glStencilFunc)glbindGetProcAddress(`glStencilFunc`);
|
glStencilFunc_NVGLZ = cast(glbfn_glStencilFunc)glbindGetProcAddress(`glStencilFunc`);
|
||||||
|
@ -12445,10 +12502,11 @@ private extern(System) nothrow @nogc {
|
||||||
|
|
||||||
glGetIntegerv_NVGLZ = cast(glbfn_glGetIntegerv)glbindGetProcAddress(`glGetIntegerv`);
|
glGetIntegerv_NVGLZ = cast(glbfn_glGetIntegerv)glbindGetProcAddress(`glGetIntegerv`);
|
||||||
if (glGetIntegerv_NVGLZ is null) assert(0, `OpenGL function 'glGetIntegerv' not found!`);
|
if (glGetIntegerv_NVGLZ is null) assert(0, `OpenGL function 'glGetIntegerv' not found!`);
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Context creation flags.
|
/// Context creation flags.
|
||||||
|
@ -13051,12 +13109,21 @@ void glnvg__copyFBOToFrom (GLNVGcontext* gl, int didx, int sidx) nothrow @truste
|
||||||
enum y = 0;
|
enum y = 0;
|
||||||
immutable int w = gl.fboWidth;
|
immutable int w = gl.fboWidth;
|
||||||
immutable int h = gl.fboHeight;
|
immutable int h = gl.fboHeight;
|
||||||
glBegin(GL_QUADS);
|
immutable(int[8]) vertices =
|
||||||
glVertex2i(x, y); // top-left
|
[x, y, // top-left
|
||||||
glVertex2i(w, y); // top-right
|
w, y, // top-right
|
||||||
glVertex2i(w, h); // bottom-right
|
w, h, // bottom-right
|
||||||
glVertex2i(x, h); // bottom-left
|
x, h]; // bottom-left
|
||||||
glEnd();
|
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)
|
// restore state (but don't unbind FBO)
|
||||||
static if (NANOVG_GL_USE_STATE_FILTER) glBindTexture(GL_TEXTURE_2D, gl.boundTexture);
|
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_PIXELS, 0);
|
||||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 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);
|
immutable ttype = (type == NVGtexture.RGBA ? GL_RGBA : GL_RED);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, ttype, w, h, 0, ttype, GL_UNSIGNED_BYTE, data);
|
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 =
|
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);
|
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_MIN_FILTER, tfmin);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (imageFlags&NVGImageFlag.NoFiltering ? GL_NEAREST : GL_LINEAR));
|
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);
|
glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x00, 0xff);
|
||||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||||
}
|
}
|
||||||
glBegin(GL_QUADS);
|
immutable(int[8]) vertices =
|
||||||
glVertex2i(0, 0);
|
[0, 0,
|
||||||
glVertex2i(0, gl.fboHeight);
|
0, gl.fboHeight,
|
||||||
glVertex2i(gl.fboWidth, gl.fboHeight);
|
gl.fboWidth, gl.fboHeight,
|
||||||
glVertex2i(gl.fboWidth, 0);
|
gl.fboWidth, 0];
|
||||||
glEnd();
|
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);
|
//glnvg__restoreAffine(gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14538,6 +14619,7 @@ public NVGContext nvgCreateContext (const(NVGContextFlag)[] flagList...) nothrow
|
||||||
NVGparams params = void;
|
NVGparams params = void;
|
||||||
NVGContext ctx = null;
|
NVGContext ctx = null;
|
||||||
version(nanovg_builtin_opengl_bindings) nanovgInitOpenGL(); // why not?
|
version(nanovg_builtin_opengl_bindings) nanovgInitOpenGL(); // why not?
|
||||||
|
version(nanovg_bindbc_opengl_bindings) nanovgInitOpenGL();
|
||||||
GLNVGcontext* gl = cast(GLNVGcontext*)malloc(GLNVGcontext.sizeof);
|
GLNVGcontext* gl = cast(GLNVGcontext*)malloc(GLNVGcontext.sizeof);
|
||||||
if (gl is null) goto error;
|
if (gl is null) goto error;
|
||||||
memset(gl, 0, GLNVGcontext.sizeof);
|
memset(gl, 0, GLNVGcontext.sizeof);
|
||||||
|
|
Loading…
Reference in New Issue