diff --git a/include/gui.hpp b/include/gui.hpp index 380b344f..16c500b0 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -14,5 +14,6 @@ void guiCursorUnlock(); extern NVGcontext *gVg; extern std::shared_ptr gGuiFont; +extern float gPixelRatio; } // namespace rack diff --git a/src/gui.cpp b/src/gui.cpp index 8ae7dc47..a7178214 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -23,6 +23,7 @@ namespace rack { static GLFWwindow *window = NULL; std::shared_ptr gGuiFont; NVGcontext *gVg = NULL; +float gPixelRatio = 0.0; void windowSizeCallback(GLFWwindow* window, int width, int height) { @@ -136,6 +137,7 @@ static int lastWindowX, lastWindowY, lastWindowWidth, lastWindowHeight; void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (action == GLFW_PRESS || action == GLFW_REPEAT) { if (key == GLFW_KEY_F11 || key == GLFW_KEY_ESCAPE) { + /* // Toggle fullscreen GLFWmonitor *monitor = glfwGetWindowMonitor(window); if (monitor) { @@ -151,6 +153,7 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods const GLFWvidmode *mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } + */ } else { if (gSelectedWidget) { @@ -163,16 +166,20 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods void renderGui() { int width, height; glfwGetFramebufferSize(window, &width, &height); - // glfwGetWindowSize(window, &width, &height); + int windowWidth, windowHeight; + glfwGetWindowSize(window, &windowWidth, &windowHeight); + gPixelRatio = (float)width / windowWidth; // Update and render glViewport(0, 0, width, height); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - nvgBeginFrame(gVg, width, height, 1.0); + nvgBeginFrame(gVg, width, height, gPixelRatio); nvgSave(gVg); + nvgReset(gVg); + nvgScale(gVg, gPixelRatio, gPixelRatio); gScene->draw(gVg); nvgRestore(gVg); @@ -220,7 +227,7 @@ void guiInit() { // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. glGetError(); - glfwSetWindowSizeLimits(window, 240, 160, GLFW_DONT_CARE, GLFW_DONT_CARE); + glfwSetWindowSizeLimits(window, 640, 480, GLFW_DONT_CARE, GLFW_DONT_CARE); // Set up NanoVG gVg = nvgCreateGL2(NVG_ANTIALIAS); diff --git a/src/widgets/FramebufferWidget.cpp b/src/widgets/FramebufferWidget.cpp index 7915f141..07a7350c 100644 --- a/src/widgets/FramebufferWidget.cpp +++ b/src/widgets/FramebufferWidget.cpp @@ -10,6 +10,7 @@ namespace rack { struct FramebufferWidget::Internal { NVGLUframebuffer *fb = NULL; + Rect box; ~Internal() { setFramebuffer(NULL); @@ -21,6 +22,7 @@ struct FramebufferWidget::Internal { } }; + FramebufferWidget::FramebufferWidget() { internal = new Internal(); } @@ -35,7 +37,9 @@ void FramebufferWidget::step() { // Render the scene to the framebuffer if dirty if (dirty) { - Vec fbSize = box.size.plus(padding.mult(2)); + internal->box.pos = padding.neg(); + internal->box.size = box.size.plus(padding.mult(2)); + Vec fbSize = internal->box.size.mult(gPixelRatio); assert(fbSize.isFinite()); internal->setFramebuffer(NULL); @@ -44,14 +48,13 @@ void FramebufferWidget::step() { return; internal->setFramebuffer(fb); - // TODO Support screens with pixelRatio != 1.0 (e.g. Retina) by using the actual size of the framebuffer, etc. - const float pixelRatio = 1.0; nvgluBindFramebuffer(fb); glViewport(0.0, 0.0, fbSize.x, fbSize.y); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - nvgBeginFrame(gVg, fbSize.x, fbSize.y, pixelRatio); + nvgBeginFrame(gVg, fbSize.x, fbSize.y, gPixelRatio); + nvgScale(gVg, gPixelRatio, gPixelRatio); nvgTranslate(gVg, padding.x, padding.y); Widget::draw(gVg); @@ -67,14 +70,13 @@ void FramebufferWidget::draw(NVGcontext *vg) { return; // Draw framebuffer image - int width, height; - nvgImageSize(vg, internal->fb->image, &width, &height); nvgBeginPath(vg); - nvgRect(vg, -padding.x, -padding.y, width, height); - NVGpaint paint = nvgImagePattern(vg, -padding.x, -padding.y, width, height, 0.0, internal->fb->image, 1.0); + nvgRect(vg, internal->box.pos.x, internal->box.pos.y, internal->box.size.x, internal->box.size.y); + NVGpaint paint = nvgImagePattern(vg, internal->box.pos.x, internal->box.pos.y, internal->box.size.x, internal->box.size.y, 0.0, internal->fb->image, 1.0); nvgFillPaint(vg, paint); nvgFill(vg); + // For debugging bounding box of framebuffer image // nvgFillColor(vg, nvgRGBA(255, 0, 0, 64)); // nvgFill(vg); }