You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.2KB

  1. #include "widgets.hpp"
  2. #include "gui.hpp"
  3. #include <GL/glew.h>
  4. #include "../ext/nanovg/src/nanovg_gl.h"
  5. #include "../ext/nanovg/src/nanovg_gl_utils.h"
  6. namespace rack {
  7. struct FramebufferWidget::Internal {
  8. NVGLUframebuffer *fb = NULL;
  9. Vec offset;
  10. ~Internal() {
  11. setFramebuffer(NULL);
  12. }
  13. void setFramebuffer(NVGLUframebuffer *fb) {
  14. if (this->fb)
  15. nvgluDeleteFramebuffer(this->fb);
  16. this->fb = fb;
  17. }
  18. };
  19. FramebufferWidget::FramebufferWidget() {
  20. internal = new Internal();
  21. }
  22. FramebufferWidget::~FramebufferWidget() {
  23. delete internal;
  24. }
  25. void FramebufferWidget::step() {
  26. if (children.empty())
  27. return;
  28. // Step children before rendering
  29. Widget::step();
  30. // Render the scene to the framebuffer if dirty
  31. if (dirty) {
  32. Rect childrenBox = getChildrenBoundingBox();
  33. assert(childrenBox.size.isFinite());
  34. int width = ceilf(childrenBox.size.x) + 2*margin;
  35. int height = ceilf(childrenBox.size.y) + 2*margin;
  36. internal->offset = childrenBox.pos.minus(Vec(margin, margin));
  37. internal->setFramebuffer(NULL);
  38. NVGLUframebuffer *fb = nvgluCreateFramebuffer(gVg, width, height, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
  39. if (!fb)
  40. return;
  41. internal->setFramebuffer(fb);
  42. // TODO Support screens with pixelRatio != 1.0 (e.g. Retina) by using the actual size of the framebuffer, etc.
  43. const float pixelRatio = 1.0;
  44. nvgluBindFramebuffer(fb);
  45. glViewport(0.0, 0.0, width, height);
  46. glClearColor(0.0, 0.0, 0.0, 0.0);
  47. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  48. nvgBeginFrame(gVg, width, height, pixelRatio);
  49. nvgTranslate(gVg, -internal->offset.x, -internal->offset.y);
  50. Widget::draw(gVg);
  51. nvgEndFrame(gVg);
  52. nvgluBindFramebuffer(NULL);
  53. dirty = false;
  54. }
  55. }
  56. void FramebufferWidget::draw(NVGcontext *vg) {
  57. if (!internal->fb)
  58. return;
  59. // Draw framebuffer image
  60. int width, height;
  61. nvgImageSize(vg, internal->fb->image, &width, &height);
  62. nvgBeginPath(vg);
  63. nvgRect(vg, internal->offset.x, internal->offset.y, width, height);
  64. NVGpaint paint = nvgImagePattern(vg, internal->offset.x, internal->offset.y, width, height, 0.0, internal->fb->image, 1.0);
  65. nvgFillPaint(vg, paint);
  66. nvgFill(vg);
  67. // nvgFillColor(vg, nvgRGBA(255, 0, 0, 64));
  68. // nvgFill(vg);
  69. }
  70. } // namespace rack