mirror of
https://github.com/memononen/nanovg
synced 2026-09-26 16:19:07 +03:00
refactor
This commit is contained in:
parent
b5aaa46ca9
commit
fbf3eea9e3
11 changed files with 8243 additions and 0 deletions
1370
example/demo.cpp
Normal file
1370
example/demo.cpp
Normal file
File diff suppressed because it is too large
Load diff
273
example/example_fbo.cpp
Normal file
273
example/example_fbo.cpp
Normal 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
163
example/example_gl2.cpp
Normal 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
199
example/example_gl3.cpp
Normal 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
156
example/example_gles2.cpp
Normal 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
156
example/example_gles3.cpp
Normal 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
187
example/perf.cpp
Normal 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
3088
src/nanovg.cpp
Normal file
File diff suppressed because it is too large
Load diff
760
src/nanovg.hpp
Normal file
760
src/nanovg.hpp
Normal 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
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
158
src/nanovg_gl_utils.hpp
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue