This commit is contained in:
Blake Lucas 2026-03-22 22:52:13 -07:00
parent b5aaa46ca9
commit fbf3eea9e3
11 changed files with 8243 additions and 0 deletions

1370
example/demo.cpp Normal file

File diff suppressed because it is too large Load diff

273
example/example_fbo.cpp Normal file
View file

@ -0,0 +1,273 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#ifdef __APPLE__
# define GLFW_INCLUDE_GLCOREARB
#endif
#include <GLFW/glfw3.h>
#include "nanovg.hpp"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.hpp"
#include "nanovg_gl_utils.hpp"
using namespace nvg;
#include "perf.h"
void renderPattern(NVGcontext* vg, NVGLUframebuffer* fb, float t, float pxRatio)
{
int winWidth, winHeight;
int fboWidth, fboHeight;
int pw, ph, x, y;
float s = 20.0f;
float sr = (cosf(t)+1)*0.5f;
float r = s * 0.6f * (0.2f + 0.8f * sr);
if (fb == NULL) return;
nvgImageSize(vg, fb->image, &fboWidth, &fboHeight);
winWidth = (int)(fboWidth / pxRatio);
winHeight = (int)(fboHeight / pxRatio);
// Draw some stuff to an FBO as a test
nvgluBindFramebuffer(fb);
glViewport(0, 0, fboWidth, fboHeight);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
pw = (int)ceilf(winWidth / s);
ph = (int)ceilf(winHeight / s);
nvgBeginPath(vg);
for (y = 0; y < ph; y++) {
for (x = 0; x < pw; x++) {
float cx = (x+0.5f) * s;
float cy = (y+0.5f) * s;
nvgCircle(vg, cx,cy, r);
}
}
nvgFillColor(vg, nvgRGBA(220,160,0,200));
nvgFill(vg);
nvgEndFrame(vg);
nvgluBindFramebuffer(NULL);
}
int loadFonts(NVGcontext* vg)
{
int font;
font = nvgCreateFont(vg, "sans", "../example/Roboto-Regular.ttf");
if (font == -1) {
printf("Could not add font regular.\n");
return -1;
}
font = nvgCreateFont(vg, "sans-bold", "../example/Roboto-Bold.ttf");
if (font == -1) {
printf("Could not add font bold.\n");
return -1;
}
return 0;
}
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main()
{
GLFWwindow* window;
NVGcontext* vg = NULL;
GPUtimer gpuTimer;
PerfGraph fps, cpuGraph, gpuGraph;
double prevt = 0, cpuTime = 0;
NVGLUframebuffer* fb = NULL;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time");
glfwSetErrorCallback(errorcb);
#ifndef _WIN32 // don't require this on win32, and works with more cards
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
#ifdef DEMO_MSAA
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
#ifdef NANOVG_GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
printf("Could not init glew.\n");
return -1;
}
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError();
#endif
#ifdef DEMO_MSAA
vg = nvgCreateGL3(NVG_STENCIL_STROKES | NVG_DEBUG);
#else
vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
// Create hi-dpi FBO for hi-dpi screens.
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// The image pattern is tiled, set repeat on x and y.
fb = nvgluCreateFramebuffer(vg, (int)(100*pxRatio), (int)(100*pxRatio), NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
if (fb == NULL) {
printf("Could not create FBO.\n");
return -1;
}
if (loadFonts(vg) == -1) {
printf("Could not load fonts\n");
return -1;
}
glfwSwapInterval(0);
initGPUTimer(&gpuTimer);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
float gpuTimes[3];
int i, n;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
startGPUTimer(&gpuTimer);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
renderPattern(vg, fb, t, pxRatio);
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
// Use the FBO as image pattern.
if (fb != NULL) {
NVGpaint img = nvgImagePattern(vg, 0, 0, 100, 100, 0, fb->image, 1.0f);
nvgSave(vg);
for (i = 0; i < 20; i++) {
nvgBeginPath(vg);
nvgRect(vg, 10 + i*30,10, 10, winHeight-20);
nvgFillColor(vg, nvgHSLA(i/19.0f, 0.5f, 0.5f, 255));
nvgFill(vg);
}
nvgBeginPath(vg);
nvgRoundedRect(vg, 140 + sinf(t*1.3f)*100, 140 + cosf(t*1.71244f)*100, 250, 250, 20);
nvgFillPaint(vg, img);
nvgFill(vg);
nvgStrokeColor(vg, nvgRGBA(220,160,0,255));
nvgStrokeWidth(vg, 3.0f);
nvgStroke(vg);
nvgRestore(vg);
}
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5+200+5,5, &cpuGraph);
if (gpuTimer.supported)
renderGraph(vg, 5+200+5+200+5,5, &gpuGraph);
nvgEndFrame(vg);
// Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU)
cpuTime = glfwGetTime() - t;
updateGraph(&fps, dt);
updateGraph(&cpuGraph, cpuTime);
// We may get multiple results.
n = stopGPUTimer(&gpuTimer, gpuTimes, 3);
for (i = 0; i < n; i++)
updateGraph(&gpuGraph, gpuTimes[i]);
glfwSwapBuffers(window);
glfwPollEvents();
}
nvgluDeleteFramebuffer(fb);
nvgDeleteGL3(vg);
printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f);
glfwTerminate();
return 0;
}

163
example/example_gl2.cpp Normal file
View file

@ -0,0 +1,163 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.hpp"
#define NANOVG_GL2_IMPLEMENTATION
#include "nanovg_gl.hpp"
using namespace nvg;
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
PerfGraph fps;
double prevt = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
#ifdef DEMO_MSAA
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
#ifdef NANOVG_GLEW
if(glewInit() != GLEW_OK) {
printf("Could not init glew.\n");
return -1;
}
#endif
#ifdef DEMO_MSAA
vg = nvgCreateGL2(NVG_STENCIL_STROKES | NVG_DEBUG);
#else
vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGL2(vg);
glfwTerminate();
return 0;
}

199
example/example_gl3.cpp Normal file
View file

@ -0,0 +1,199 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#ifdef __APPLE__
# define GLFW_INCLUDE_GLCOREARB
#endif
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.hpp"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.hpp"
using namespace nvg;
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
GPUtimer gpuTimer;
PerfGraph fps, cpuGraph, gpuGraph;
double prevt = 0, cpuTime = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time");
glfwSetErrorCallback(errorcb);
#ifndef _WIN32 // don't require this on win32, and works with more cards
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
#ifdef DEMO_MSAA
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
#ifdef NANOVG_GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
printf("Could not init glew.\n");
return -1;
}
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError();
#endif
#ifdef DEMO_MSAA
vg = nvgCreateGL3(NVG_STENCIL_STROKES | NVG_DEBUG);
#else
vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
initGPUTimer(&gpuTimer);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
float gpuTimes[3];
int i, n;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
startGPUTimer(&gpuTimer);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5+200+5,5, &cpuGraph);
if (gpuTimer.supported)
renderGraph(vg, 5+200+5+200+5,5, &gpuGraph);
nvgEndFrame(vg);
// Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU)
cpuTime = glfwGetTime() - t;
updateGraph(&fps, dt);
updateGraph(&cpuGraph, cpuTime);
// We may get multiple results.
n = stopGPUTimer(&gpuTimer, gpuTimes, 3);
for (i = 0; i < n; i++)
updateGraph(&gpuGraph, gpuTimes[i]);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGL3(vg);
printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f);
glfwTerminate();
return 0;
}

156
example/example_gles2.cpp Normal file
View file

@ -0,0 +1,156 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#define GLFW_INCLUDE_ES2
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.hpp"
#define NANOVG_GLES2_IMPLEMENTATION
#include "nanovg_gl.hpp"
#include "nanovg_gl_utils.hpp"
using namespace nvg;
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
PerfGraph fps;
double prevt = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
vg = nvgCreateGLES2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glEnable(GL_DEPTH_TEST);
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGLES2(vg);
glfwTerminate();
return 0;
}

156
example/example_gles3.cpp Normal file
View file

@ -0,0 +1,156 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#define GLFW_INCLUDE_ES3
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.hpp"
#define NANOVG_GLES3_IMPLEMENTATION
#include "nanovg_gl.hpp"
#include "nanovg_gl_utils.hpp"
using namespace nvg;
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
PerfGraph fps;
double prevt = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
glEnable(GL_DEPTH_TEST);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGLES3(vg);
glfwTerminate();
return 0;
}

187
example/perf.cpp Normal file
View file

@ -0,0 +1,187 @@
#include "perf.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#include <GLFW/glfw3.h>
#include "nanovg.hpp"
using namespace nvg;
#ifdef _MSC_VER
#define snprintf _snprintf
#elif !defined(__MINGW32__)
#include <iconv.h>
#endif
// timer query support
#ifndef GL_ARB_timer_query
#define GL_TIME_ELAPSED 0x88BF
//typedef void (APIENTRY *pfnGLGETQUERYOBJECTUI64V)(GLuint id, GLenum pname, GLuint64* params);
//pfnGLGETQUERYOBJECTUI64V glGetQueryObjectui64v = 0;
#endif
void initGPUTimer(GPUtimer* timer)
{
memset(timer, 0, sizeof(*timer));
/* timer->supported = glfwExtensionSupported("GL_ARB_timer_query");
if (timer->supported) {
#ifndef GL_ARB_timer_query
glGetQueryObjectui64v = (pfnGLGETQUERYOBJECTUI64V)glfwGetProcAddress("glGetQueryObjectui64v");
printf("glGetQueryObjectui64v=%p\n", glGetQueryObjectui64v);
if (!glGetQueryObjectui64v) {
timer->supported = GL_FALSE;
return;
}
#endif
glGenQueries(GPU_QUERY_COUNT, timer->queries);
}*/
}
void startGPUTimer(GPUtimer* timer)
{
if (!timer->supported)
return;
glBeginQuery(GL_TIME_ELAPSED, timer->queries[timer->cur % GPU_QUERY_COUNT] );
timer->cur++;
}
int stopGPUTimer(GPUtimer* timer, float* times, int maxTimes)
{
NVG_NOTUSED(times);
NVG_NOTUSED(maxTimes);
GLint available = 1;
int n = 0;
if (!timer->supported)
return 0;
glEndQuery(GL_TIME_ELAPSED);
while (available && timer->ret <= timer->cur) {
// check for results if there are any
glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available);
if (available) {
/* GLuint64 timeElapsed = 0;
glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed);
timer->ret++;
if (n < maxTimes) {
times[n] = (float)((double)timeElapsed * 1e-9);
n++;
}*/
}
}
return n;
}
void initGraph(PerfGraph* fps, int style, const char* name)
{
memset(fps, 0, sizeof(PerfGraph));
fps->style = style;
strncpy(fps->name, name, sizeof(fps->name));
fps->name[sizeof(fps->name)-1] = '\0';
}
void updateGraph(PerfGraph* fps, float frameTime)
{
fps->head = (fps->head+1) % GRAPH_HISTORY_COUNT;
fps->values[fps->head] = frameTime;
}
float getGraphAverage(PerfGraph* fps)
{
int i;
float avg = 0;
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
avg += fps->values[i];
}
return avg / (float)GRAPH_HISTORY_COUNT;
}
void renderGraph(NVGcontext* vg, float x, float y, PerfGraph* fps)
{
int i;
float avg, w, h;
char str[64];
avg = getGraphAverage(fps);
w = 200;
h = 35;
nvgBeginPath(vg);
nvgRect(vg, x,y, w,h);
nvgFillColor(vg, nvgRGBA(0,0,0,128));
nvgFill(vg);
nvgBeginPath(vg);
nvgMoveTo(vg, x, y+h);
if (fps->style == GRAPH_RENDER_FPS) {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = 1.0f / (0.00001f + fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT]);
float vx, vy;
if (v > 80.0f) v = 80.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 80.0f) * h);
nvgLineTo(vg, vx, vy);
}
} else if (fps->style == GRAPH_RENDER_PERCENT) {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1.0f;
float vx, vy;
if (v > 100.0f) v = 100.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 100.0f) * h);
nvgLineTo(vg, vx, vy);
}
} else {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1000.0f;
float vx, vy;
if (v > 20.0f) v = 20.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 20.0f) * h);
nvgLineTo(vg, vx, vy);
}
}
nvgLineTo(vg, x+w, y+h);
nvgFillColor(vg, nvgRGBA(255,192,0,128));
nvgFill(vg);
nvgFontFace(vg, "sans");
if (fps->name[0] != '\0') {
nvgFontSize(vg, 12.0f);
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,192));
nvgText(vg, x+3,y+3, fps->name, NULL);
}
if (fps->style == GRAPH_RENDER_FPS) {
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.2f FPS", 1.0f / avg);
nvgText(vg, x+w-3,y+3, str, NULL);
nvgFontSize(vg, 13.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BASELINE);
nvgFillColor(vg, nvgRGBA(240,240,240,160));
sprintf(str, "%.2f ms", avg * 1000.0f);
nvgText(vg, x+w-3,y+h-3, str, NULL);
}
else if (fps->style == GRAPH_RENDER_PERCENT) {
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.1f %%", avg * 1.0f);
nvgText(vg, x+w-3,y+3, str, NULL);
} else {
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.2f ms", avg * 1000.0f);
nvgText(vg, x+w-3,y+3, str, NULL);
}
}

3088
src/nanovg.cpp Normal file

File diff suppressed because it is too large Load diff

760
src/nanovg.hpp Normal file
View file

@ -0,0 +1,760 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_HPP
#define NANOVG_HPP
#include <type_traits>
namespace nvg {
inline constexpr float NVG_PI = 3.14159265358979323846264338327f;
template<typename E>
constexpr std::underlying_type_t<E> to_underlying(E e) noexcept {
return static_cast<std::underlying_type_t<E>>(e);
}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
#endif
typedef struct NVGcontext NVGcontext;
struct NVGcolor {
union {
float rgba[4];
struct {
float r,g,b,a;
};
};
};
typedef struct NVGcolor NVGcolor;
struct NVGpaint {
float xform[6];
float extent[2];
float radius;
float feather;
NVGcolor innerColor;
NVGcolor outerColor;
int image;
};
typedef struct NVGpaint NVGpaint;
enum class Winding : int {
CCW = 1, // Winding for solid shapes
CW = 2, // Winding for holes
};
enum class Solidity : int {
Solid = 1, // CCW
Hole = 2, // CW
};
enum class LineStyle : int {
Solid = 1,
Dashed = 2,
Dotted = 3,
Glow = 4
};
enum class LineCap : int {
Butt = 0,
Round = 1,
Square = 2,
Bevel = 3,
Miter = 4,
};
enum class Align : int {
Left = 1 << 0,
Center = 1 << 1,
Right = 1 << 2,
Top = 1 << 3,
Middle = 1 << 4,
MiddleAscent = 1 << 5,
Bottom = 1 << 6,
Baseline = 1 << 7,
};
inline constexpr Align operator|(Align a, Align b) noexcept {
return static_cast<Align>(to_underlying(a) | to_underlying(b));
}
inline constexpr int operator&(int a, Align b) noexcept {
return a & to_underlying(b);
}
enum class BlendFactor : int {
Zero = 1 << 0,
One = 1 << 1,
SrcColor = 1 << 2,
OneMinusSrcColor = 1 << 3,
DstColor = 1 << 4,
OneMinusDstColor = 1 << 5,
SrcAlpha = 1 << 6,
OneMinusSrcAlpha = 1 << 7,
DstAlpha = 1 << 8,
OneMinusDstAlpha = 1 << 9,
SrcAlphaSaturate = 1 << 10,
};
enum class CompositeOperation : int {
SourceOver,
SourceIn,
SourceOut,
Atop,
DestinationOver,
DestinationIn,
DestinationOut,
DestinationAtop,
Lighter,
Copy,
Xor,
};
struct NVGcompositeOperationState {
int srcRGB;
int dstRGB;
int srcAlpha;
int dstAlpha;
};
typedef struct NVGcompositeOperationState NVGcompositeOperationState;
struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position.
float minx, maxx; // The bounds of the glyph shape.
};
typedef struct NVGglyphPosition NVGglyphPosition;
struct NVGtextRow {
const char* start; // Pointer to the input text where the row starts.
const char* end; // Pointer to the input text where the row ends (one past the last character).
const char* next; // Pointer to the beginning of the next row.
float width; // Logical width of the row.
float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending.
};
typedef struct NVGtextRow NVGtextRow;
enum class ImageFlags : int {
GenerateMipmaps = 1 << 0,
RepeatX = 1 << 1,
RepeatY = 1 << 2,
Flipy = 1 << 3,
Premultiplied = 1 << 4,
Nearest = 1 << 5,
};
inline constexpr ImageFlags operator|(ImageFlags a, ImageFlags b) noexcept {
return static_cast<ImageFlags>(to_underlying(a) | to_underlying(b));
}
inline constexpr int operator&(int a, ImageFlags b) noexcept { return a & to_underlying(b); }
// Internal Render API
//
enum class Texture : int {
Alpha = 0x01,
Rgba = 0x02,
};
struct NVGscissor {
float xform[6];
float extent[2];
};
typedef struct NVGscissor NVGscissor;
struct NVGscissorBounds {
float x;
float y;
float w;
float h;
};
typedef struct NVGscissorBounds NVGscissorBounds;
struct NVGvertex {
float x,y,u,v,s,t;
};
typedef struct NVGvertex NVGvertex;
struct NVGpath {
int first;
int count;
int reversed;
unsigned char closed;
int nbevel;
NVGvertex* fill;
int nfill;
NVGvertex* stroke;
int nstroke;
int winding;
int convex;
};
typedef struct NVGpath NVGpath;
struct NVGparams {
void* userPtr;
int edgeAntiAlias;
int (*renderCreate)(void* uptr);
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);
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
int (*renderGetImageTextureId)(void* uptr, int handle);
void (*renderViewport)(void* uptr, float width, float height, float devicePixelRatio);
void (*renderCancel)(void* uptr);
void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, int lineStyle, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts, float fringe);
void (*renderDelete)(void* uptr);
};
typedef struct NVGparams NVGparams;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace nvg
extern "C" {
// Begin drawing a new frame
// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame()
// nvgBeginFrame() defines the size of the window to render to in relation currently
// set viewport (i.e. glViewport on GL backends). Device pixel ration allows to
// control the rendering on Hi-DPI devices.
// For example, GLFW returns two dimension for an opened window: window size and
// frame buffer size. In that case you would set windowWidth/Height to the window size
// devicePixelRatio to: frameBufferWidth / windowWidth.
void nvgBeginFrame(nvg::NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio);
// Cancels drawing the current frame.
void nvgCancelFrame(nvg::NVGcontext* ctx);
// Ends drawing flushing remaining render state.
void nvgEndFrame(nvg::NVGcontext* ctx);
//
// Composite operation
//
// The composite operations in NanoVG are modeled after HTML Canvas API, and
// the blend func is based on OpenGL (see corresponding manuals for more info).
// The colors in the blending state have premultiplied alpha.
// Sets the composite operation. The op parameter should be one of NVGcompositeOperation.
void nvgGlobalCompositeOperation(nvg::NVGcontext* ctx, int op);
// Sets the composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor.
void nvgGlobalCompositeBlendFunc(nvg::NVGcontext* ctx, int sfactor, int dfactor);
// Sets the composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor.
void nvgGlobalCompositeBlendFuncSeparate(nvg::NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);
//
// Color utils
//
// Colors in NanoVG are stored as unsigned ints in ABGR format.
// Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f).
nvg::NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b);
// Returns a color value from red, green, blue values. Alpha will be set to 1.0f.
nvg::NVGcolor nvgRGBf(float r, float g, float b);
// Returns a color value from red, green, blue and alpha values.
nvg::NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
// Returns a color value from red, green, blue and alpha values.
nvg::NVGcolor nvgRGBAf(float r, float g, float b, float a);
// Linearly interpolates from color c0 to c1, and returns resulting color value.
nvg::NVGcolor nvgLerpRGBA(nvg::NVGcolor c0, nvg::NVGcolor c1, float u);
// Sets transparency of a color value.
nvg::NVGcolor nvgTransRGBA(nvg::NVGcolor c0, unsigned char a);
// Sets transparency of a color value.
nvg::NVGcolor nvgTransRGBAf(nvg::NVGcolor c0, float a);
// Returns color value specified by hue, saturation and lightness.
// HSL values are all in range [0..1], alpha will be set to 255.
nvg::NVGcolor nvgHSL(float h, float s, float l);
// Returns color value specified by hue, saturation and lightness and alpha.
// HSL values are all in range [0..1], alpha in range [0..255]
nvg::NVGcolor nvgHSLA(float h, float s, float l, unsigned char a);
//
// State Handling
//
// NanoVG contains state which represents how paths will be rendered.
// The state contains transform, fill and stroke styles, text and font styles,
// and scissor clipping.
// Pushes and saves the current render state into a state stack.
// A matching nvgRestore() must be used to restore the state.
void nvgSave(nvg::NVGcontext* ctx);
// Pops and restores current render state.
void nvgRestore(nvg::NVGcontext* ctx);
// Resets current render state to default values. Does not affect the render state stack.
void nvgReset(nvg::NVGcontext* ctx);
// Gets the current scissor bounds
nvg::NVGscissorBounds nvgCurrentScissor(nvg::NVGcontext* ctx);
//
// Render styles
//
// Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern.
// Solid color is simply defined as a color value, different kinds of paints can be created
// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern().
//
// Current render style can be saved and restored using nvgSave() and nvgRestore().
// Sets whether to draw antialias for nvgStroke() and nvgFill(). It's enabled by default.
void nvgShapeAntiAlias(nvg::NVGcontext* ctx, int enabled);
// Sets current stroke style to a solid color.
void nvgStrokeColor(nvg::NVGcontext* ctx, nvg::NVGcolor color);
// Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
void nvgStrokePaint(nvg::NVGcontext* ctx, nvg::NVGpaint paint);
// Sets current fill style to a solid color.
void nvgFillColor(nvg::NVGcontext* ctx, nvg::NVGcolor color);
// Sets current fill style to a paint, which can be a one of the gradients or a pattern.
void nvgFillPaint(nvg::NVGcontext* ctx, nvg::NVGpaint paint);
// Sets the miter limit of the stroke style.
// Miter limit controls when a sharp corner is beveled.
void nvgMiterLimit(nvg::NVGcontext* ctx, float limit);
// Sets the stroke width of the stroke style.
void nvgStrokeWidth(nvg::NVGcontext* ctx, float size);
// Sets how line is drawn.
// Can be one of LineStyle::Solid (default), LineStyle::Glow, LineStyle::Dashed, LineStyle::Dotted
void nvgLineStyle(nvg::NVGcontext* ctx, int lineStyle);
// Sets how the end of the line (cap) is drawn,
// Can be one of: LineCap::Butt (default), LineCap::Round, LineCap::Square.
void nvgLineCap(nvg::NVGcontext* ctx, int cap);
// Sets how sharp path corners are drawn.
// Can be one of LineCap::Miter (default), LineCap::Round, LineCap::Bevel.
void nvgLineJoin(nvg::NVGcontext* ctx, int join);
// Sets the transparency applied to all rendered shapes.
// Already transparent paths will get proportionally more transparent as well.
void nvgGlobalAlpha(nvg::NVGcontext* ctx, float alpha);
//
// Transforms
//
// The paths, gradients, patterns and scissor region are transformed by an transformation
// matrix at the time when they are passed to the API.
// The current transformation matrix is a affine matrix:
// [sx kx tx]
// [ky sy ty]
// [ 0 0 1]
// Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation.
// The last row is assumed to be 0,0,1 and is not stored.
//
// Apart from nvgResetTransform(), each transformation function first creates
// specific transformation matrix and pre-multiplies the current transformation by it.
//
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().
// Resets current transform to a identity matrix.
void nvgResetTransform(nvg::NVGcontext* ctx);
// Premultiplies current coordinate system by specified matrix.
// The parameters are interpreted as matrix as follows:
// [a c e]
// [b d f]
// [0 0 1]
void nvgTransform(nvg::NVGcontext* ctx, float a, float b, float c, float d, float e, float f);
// Translates current coordinate system.
void nvgTranslate(nvg::NVGcontext* ctx, float x, float y);
// Rotates current coordinate system. Angle is specified in radians.
void nvgRotate(nvg::NVGcontext* ctx, float angle);
// Skews the current coordinate system along X axis. Angle is specified in radians.
void nvgSkewX(nvg::NVGcontext* ctx, float angle);
// Skews the current coordinate system along Y axis. Angle is specified in radians.
void nvgSkewY(nvg::NVGcontext* ctx, float angle);
// Scales the current coordinate system.
void nvgScale(nvg::NVGcontext* ctx, float x, float y);
// Stores the top part (a-f) of the current transformation matrix in to the specified buffer.
// [a c e]
// [b d f]
// [0 0 1]
// There should be space for 6 floats in the return buffer for the values a-f.
void nvgCurrentTransform(nvg::NVGcontext* ctx, float* xform);
// The following functions can be used to make calculations on 2x3 transformation matrices.
// A 2x3 matrix is represented as float[6].
// Sets the transform to identity matrix.
void nvgTransformIdentity(float* dst);
// Sets the transform to translation matrix matrix.
void nvgTransformTranslate(float* dst, float tx, float ty);
// Sets the transform to scale matrix.
void nvgTransformScale(float* dst, float sx, float sy);
// Sets the transform to rotate matrix. Angle is specified in radians.
void nvgTransformRotate(float* dst, float a);
// Sets the transform to skew-x matrix. Angle is specified in radians.
void nvgTransformSkewX(float* dst, float a);
// Sets the transform to skew-y matrix. Angle is specified in radians.
void nvgTransformSkewY(float* dst, float a);
// Sets the transform to the result of multiplication of two transforms, of A = A*B.
void nvgTransformMultiply(float* dst, const float* src);
// Sets the transform to the result of multiplication of two transforms, of A = B*A.
void nvgTransformPremultiply(float* dst, const float* src);
// Sets the destination to inverse of specified transform.
// Returns 1 if the inverse could be calculated, else 0.
int nvgTransformInverse(float* dst, const float* src);
// Transform a point by given transform.
void nvgTransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy);
// Converts degrees to radians and vice versa.
float nvgDegToRad(float deg);
float nvgRadToDeg(float rad);
//
// Images
//
// NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering.
// In addition you can upload your own image. The image loading is provided by stb_image.
// The parameter imageFlags is combination of flags defined in ImageFlags.
// Creates image by loading it from the disk from specified file name.
// Returns handle to the image.
int nvgCreateImage(nvg::NVGcontext* ctx, const char* filename, int imageFlags);
// Creates image by loading it from the specified chunk of memory.
// Returns handle to the image.
int nvgCreateImageMem(nvg::NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata);
// Creates image from specified image data.
// Returns handle to the image.
int nvgCreateImageRGBA(nvg::NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data);
// Updates image data specified by image handle.
void nvgUpdateImage(nvg::NVGcontext* ctx, int image, const unsigned char* data);
// Returns the dimensions of a created image.
void nvgImageSize(nvg::NVGcontext* ctx, int image, int* w, int* h);
// Deletes created image.
void nvgDeleteImage(nvg::NVGcontext* ctx, int image);
//
// Paints
//
// NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern.
// These can be used as paints for strokes and fills.
// Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates
// of the linear gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
nvg::NVGpaint nvgLinearGradient(nvg::NVGcontext* ctx, float sx, float sy, float ex, float ey,
nvg::NVGcolor icol, nvg::NVGcolor ocol);
// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
nvg::NVGpaint nvgBoxGradient(nvg::NVGcontext* ctx, float x, float y, float w, float h,
float r, float f, nvg::NVGcolor icol, nvg::NVGcolor ocol);
// Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify
// the inner and outer radius of the gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
nvg::NVGpaint nvgRadialGradient(nvg::NVGcontext* ctx, float cx, float cy, float inr, float outr,
nvg::NVGcolor icol, nvg::NVGcolor ocol);
// Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern,
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
nvg::NVGpaint nvgImagePattern(nvg::NVGcontext* ctx, float ox, float oy, float ex, float ey,
float angle, int image, float alpha);
//
// Scissoring
//
// Scissoring allows you to clip the rendering into a rectangle. This is useful for various
// user interface cases like rendering a text edit or a timeline.
// Sets the current scissor rectangle.
// The scissor rectangle is transformed by the current transform.
void nvgScissor(nvg::NVGcontext* ctx, float x, float y, float w, float h);
// Intersects current scissor rectangle with the specified rectangle.
// The scissor rectangle is transformed by the current transform.
// Note: in case the rotation of previous scissor rect differs from
// the current one, the intersection will be done between the specified
// rectangle and the previous scissor rectangle transformed in the current
// transform space. The resulting shape is always rectangle.
void nvgIntersectScissor(nvg::NVGcontext* ctx, float x, float y, float w, float h);
// Reset and disables scissoring.
void nvgResetScissor(nvg::NVGcontext* ctx);
//
// Paths
//
// Drawing a new shape starts with nvgBeginPath(), it clears all the currently defined paths.
// Then you define one or more paths and sub-paths which describe the shape. The are functions
// to draw common shapes like rectangles and circles, and lower level step-by-step functions,
// which allow to define a path curve by curve.
//
// NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise
// winding and holes should have counter clockwise order. To specify winding of a path you can
// call nvgPathWinding(). This is useful especially for the common shapes, which are drawn CCW.
//
// Finally you can fill the path using current fill style by calling nvgFill(), and stroke it
// with current stroke style by calling nvgStroke().
//
// The curve segments and sub-paths are transformed by the current transform.
// Clears the current path and sub-paths.
void nvgBeginPath(nvg::NVGcontext* ctx);
// Starts new sub-path with specified point as first point.
void nvgMoveTo(nvg::NVGcontext* ctx, float x, float y);
// Adds line segment from the last point in the path to the specified point.
void nvgLineTo(nvg::NVGcontext* ctx, float x, float y);
// Adds cubic bezier segment from last point in the path via two control points to the specified point.
void nvgBezierTo(nvg::NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y);
// Adds quadratic bezier segment from last point in the path via a control point to the specified point.
void nvgQuadTo(nvg::NVGcontext* ctx, float cx, float cy, float x, float y);
// Adds an arc segment at the corner defined by the last path point, and two specified points.
void nvgArcTo(nvg::NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius);
// Closes current sub-path with a line segment.
void nvgClosePath(nvg::NVGcontext* ctx);
// Sets the current sub-path winding, see Winding and Solidity.
void nvgPathWinding(nvg::NVGcontext* ctx, int dir);
// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
// and the arc is drawn from angle a0 to a1, and swept in direction dir (Winding::CCW, or Winding::CW).
// Angles are specified in radians.
void nvgArc(nvg::NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir);
// Creates new rectangle shaped sub-path.
void nvgRect(nvg::NVGcontext* ctx, float x, float y, float w, float h);
// Creates new rounded rectangle shaped sub-path.
void nvgRoundedRect(nvg::NVGcontext* ctx, float x, float y, float w, float h, float r);
// Creates new rounded rectangle shaped sub-path with varying radii for each corner.
void nvgRoundedRectVarying(nvg::NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft);
// Creates new ellipse shaped sub-path.
void nvgEllipse(nvg::NVGcontext* ctx, float cx, float cy, float rx, float ry);
// Creates new circle shaped sub-path.
void nvgCircle(nvg::NVGcontext* ctx, float cx, float cy, float r);
// Fills the current path with current fill style.
void nvgFill(nvg::NVGcontext* ctx);
// Fills the current path with current stroke style.
void nvgStroke(nvg::NVGcontext* ctx);
//
// Text
//
// NanoVG allows you to load .ttf files and use the font to render text.
//
// The appearance of the text can be defined by setting the current text style
// and by specifying the fill color. Common text and font settings such as
// font size, letter spacing and text align are supported. Font blur allows you
// to create simple text effects such as drop shadows.
//
// At render time the font face can be set based on the font handles or name.
//
// Font measure functions return values in local space, the calculations are
// carried in the same resolution as the final rendering. This is done because
// the text glyph positions are snapped to the nearest pixels sharp rendering.
//
// The local space means that values are not rotated or scale as per the current
// transformation. For example if you set font size to 12, which would mean that
// line height is 16, then regardless of the current scaling and rotation, the
// returned line height is always 16. Some measures may vary because of the scaling
// since aforementioned pixel snapping.
//
// While this may sound a little odd, the setup allows you to always render the
// same way regardless of scaling. I.e. following works regardless of scaling:
//
// const char* txt = "Text me up.";
// nvgTextBounds(vg, x,y, txt, NULL, bounds);
// nvgBeginPath(vg);
// nvgRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
// nvgFill(vg);
//
// Note: currently only solid color fill is supported for text.
// Creates font by loading it from the disk from specified file name.
// Returns handle to the font.
int nvgCreateFont(nvg::NVGcontext* ctx, const char* name, const char* filename);
// fontIndex specifies which font face to load from a .ttf/.ttc file.
int nvgCreateFontAtIndex(nvg::NVGcontext* ctx, const char* name, const char* filename, const int fontIndex);
// Creates font by loading it from the specified memory chunk.
// Returns handle to the font.
int nvgCreateFontMem(nvg::NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData);
// fontIndex specifies which font face to load from a .ttf/.ttc file.
int nvgCreateFontMemAtIndex(nvg::NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex);
// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
int nvgFindFont(nvg::NVGcontext* ctx, const char* name);
// Adds a fallback font by handle.
int nvgAddFallbackFontId(nvg::NVGcontext* ctx, int baseFont, int fallbackFont);
// Adds a fallback font by name.
int nvgAddFallbackFont(nvg::NVGcontext* ctx, const char* baseFont, const char* fallbackFont);
// Resets fallback fonts by handle.
void nvgResetFallbackFontsId(nvg::NVGcontext* ctx, int baseFont);
// Resets fallback fonts by name.
void nvgResetFallbackFonts(nvg::NVGcontext* ctx, const char* baseFont);
// Sets the font size of current text style.
void nvgFontSize(nvg::NVGcontext* ctx, float size);
// Sets the blur of current text style.
void nvgFontBlur(nvg::NVGcontext* ctx, float blur);
// Sets the dilation of current text style.
void nvgFontDilate(nvg::NVGcontext* ctx, float dilate);
// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(nvg::NVGcontext* ctx, float spacing);
// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(nvg::NVGcontext* ctx, float lineHeight);
// Sets the text align of current text style, see NVGalign for options.
void nvgTextAlign(nvg::NVGcontext* ctx, int align);
// Sets the font face based on specified id of current text style.
void nvgFontFaceId(nvg::NVGcontext* ctx, int font);
// Sets the font face based on specified name of current text style.
void nvgFontFace(nvg::NVGcontext* ctx, const char* font);
// Gets the font size of current text style.
int nvgGetFontFaceId(nvg::NVGcontext* ctx);
// Get the font size
float nvgGetFontSize(nvg::NVGcontext* ctx);
//Get Stroke width
float nvgGetStrokeWidth(nvg::NVGcontext* ctx);
// Get text alignment
int nvgGetTextAlign(nvg::NVGcontext* ctx);
// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
float nvgText(nvg::NVGcontext* ctx, float x, float y, const char* string, const char* end);
// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
void nvgTextBox(nvg::NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end);
// Measures the specified text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Returns the horizontal advance of the measured text (i.e. where the next character should drawn).
// Measured values are returned in local coordinate space.
float nvgTextBounds(nvg::NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds);
// Measures the specified multi-text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Measured values are returned in local coordinate space.
void nvgTextBoxBounds(nvg::NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);
// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
// Measured values are returned in local coordinate space.
int nvgTextGlyphPositions(nvg::NVGcontext* ctx, float x, float y, const char* string, const char* end, nvg::NVGglyphPosition* positions, int maxPositions);
// Returns the vertical metrics based on the current text style.
// Measured values are returned in local coordinate space.
void nvgTextMetrics(nvg::NVGcontext* ctx, float* ascender, float* descender, float* lineh);
// Breaks the specified text into lines. If end is specified only the sub-string will be used.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
int nvgTextBreakLines(nvg::NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, nvg::NVGtextRow* rows, int maxRows, int skipSpaces);
// Get image texture Id
int nvgGetImageTextureId(nvg::NVGcontext* ctx, int handle);
//
// Constructor and destructor, called by the render back-end.
nvg::NVGcontext* nvgCreateInternal(nvg::NVGparams* params);
void nvgDeleteInternal(nvg::NVGcontext* ctx);
nvg::NVGparams* nvgInternalParams(nvg::NVGcontext* ctx);
// Debug function to dump cached path data.
void nvgDebugDumpPathCache(nvg::NVGcontext* ctx);
#define NVG_NOTUSED(v) for (;;) { (void)(1 ? (void)0 : ( (void)(v) ) ); break; }
} // extern "C"
#endif // NANOVG_HPP

1733
src/nanovg_gl.hpp Normal file

File diff suppressed because it is too large Load diff

158
src/nanovg_gl_utils.hpp Normal file
View file

@ -0,0 +1,158 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL_UTILS_HPP
#define NANOVG_GL_UTILS_HPP
#include "nanovg.hpp"
struct NVGLUframebuffer {
nvg::NVGcontext* ctx;
GLuint fbo;
GLuint rbo;
GLuint texture;
int image;
};
typedef struct NVGLUframebuffer NVGLUframebuffer;
// Helper function to create GL frame buffer to render to.
void nvgluBindFramebuffer(NVGLUframebuffer* fb);
NVGLUframebuffer* nvgluCreateFramebuffer(nvg::NVGcontext* ctx, int w, int h, int imageFlags);
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb);
#endif // NANOVG_GL_UTILS_HPP
#ifdef NANOVG_GL_IMPLEMENTATION
using namespace nvg;
#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3)
// FBO is core in OpenGL 3>.
# define NANOVG_FBO_VALID 1
#elif defined(NANOVG_GL2)
// On OS X including glext defines FBO on GL2 too.
# ifdef __APPLE__
# include <OpenGL/glext.h>
# define NANOVG_FBO_VALID 1
# endif
#endif
static GLint defaultFBO = -1;
NVGLUframebuffer* nvgluCreateFramebuffer(nvg::NVGcontext* ctx, int w, int h, int imageFlags)
{
#ifdef NANOVG_FBO_VALID
GLint defaultFBO;
GLint defaultRBO;
NVGLUframebuffer* fb = NULL;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);
fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer));
if (fb == NULL) goto error;
memset(fb, 0, sizeof(NVGLUframebuffer));
fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL);
#if defined NANOVG_GL2
fb->texture = nvglImageHandleGL2(ctx, fb->image);
#elif defined NANOVG_GL3
fb->texture = nvglImageHandleGL3(ctx, fb->image);
#elif defined NANOVG_GLES2
fb->texture = nvglImageHandleGLES2(ctx, fb->image);
#elif defined NANOVG_GLES3
fb->texture = nvglImageHandleGLES3(ctx, fb->image);
#endif
fb->ctx = ctx;
// frame buffer object
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
// render buffer object
glGenRenderbuffers(1, &fb->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h);
// combine all
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
#ifdef GL_DEPTH24_STENCIL8
// If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback.
// Some graphics cards require a depth buffer along with a stencil.
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
#endif // GL_DEPTH24_STENCIL8
goto error;
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
return fb;
error:
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
nvgluDeleteFramebuffer(fb);
return NULL;
#else
NVG_NOTUSED(ctx);
NVG_NOTUSED(w);
NVG_NOTUSED(h);
NVG_NOTUSED(imageFlags);
return NULL;
#endif
}
void nvgluBindFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : (GLuint)defaultFBO);
#else
NVG_NOTUSED(fb);
#endif
}
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (fb == NULL) return;
if (fb->fbo != 0)
glDeleteFramebuffers(1, &fb->fbo);
if (fb->rbo != 0)
glDeleteRenderbuffers(1, &fb->rbo);
if (fb->image >= 0)
nvgDeleteImage(fb->ctx, fb->image);
fb->ctx = NULL;
fb->fbo = 0;
fb->rbo = 0;
fb->texture = 0;
fb->image = -1;
free(fb);
#else
NVG_NOTUSED(fb);
#endif
}
#endif // NANOVG_GL_IMPLEMENTATION