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; }
int main() { GLFWwindow* window; struct DemoData data; struct NVGcontext* vg = NULL; struct GPUtimer gpuTimer; struct 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 #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; } #endif #ifdef DEMO_MSAA vg = nvgCreateGL3(512, 512, 0); #else vg = nvgCreateGL3(512, 512, NVG_ANTIALIAS); #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); 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, premult ? NVG_PREMULTIPLIED_ALPHA : NVG_STRAIGHT_ALPHA); 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); glEnable(GL_DEPTH_TEST); // 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; }
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, 14.0f); nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(240,240,240,192)); nvgText(vg, x+3,y+1, fps->name, NULL); } if (fps->style == GRAPH_RENDER_FPS) { nvgFontSize(vg, 18.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+1, str, NULL); nvgFontSize(vg, 15.0f); nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BOTTOM); nvgFillColor(vg, nvgRGBA(240,240,240,160)); sprintf(str, "%.2f ms", avg * 1000.0f); nvgText(vg, x+w-3,y+h-1, str, NULL); } else if (fps->style == GRAPH_RENDER_PERCENT) { nvgFontSize(vg, 18.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+1, str, NULL); } else { nvgFontSize(vg, 18.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+1, str, NULL); } }