DISTRHO Plugin Framework
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.

273 lines
8.2KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2026 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifdef _MSC_VER
  17. // instantiated template classes whose methods are defined elsewhere
  18. # pragma warning(disable:4661)
  19. #endif
  20. #include "../OpenGL.hpp"
  21. #include "../ImageWidgets.hpp"
  22. #include "SubWidgetPrivateData.hpp"
  23. #include "TopLevelWidgetPrivateData.hpp"
  24. #include "WidgetPrivateData.hpp"
  25. #include "WindowPrivateData.hpp"
  26. START_NAMESPACE_DGL
  27. // --------------------------------------------------------------------------------------------------------------------
  28. // OpenGLImage
  29. OpenGLImage::OpenGLImage()
  30. : ImageBase(),
  31. setupCalled(false),
  32. textureInit(false),
  33. textureId(0)
  34. #ifdef DGL_USE_GLES
  35. , convertedData(nullptr)
  36. , rawDataLast(nullptr)
  37. #endif
  38. {
  39. }
  40. OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const ImageFormat fmt)
  41. : ImageBase(rdata, w, h, fmt),
  42. setupCalled(false),
  43. textureInit(true),
  44. textureId(0)
  45. #ifdef DGL_USE_GLES
  46. , convertedData(nullptr)
  47. , rawDataLast(nullptr)
  48. #endif
  49. {
  50. glGenTextures(1, &textureId);
  51. DISTRHO_SAFE_ASSERT(textureId != 0);
  52. }
  53. OpenGLImage::OpenGLImage(const char* const rdata, const Size<uint>& s, const ImageFormat fmt)
  54. : ImageBase(rdata, s, fmt),
  55. setupCalled(false),
  56. textureInit(true),
  57. textureId(0)
  58. #ifdef DGL_USE_GLES
  59. , convertedData(nullptr)
  60. , rawDataLast(nullptr)
  61. #endif
  62. {
  63. glGenTextures(1, &textureId);
  64. DISTRHO_SAFE_ASSERT(textureId != 0);
  65. }
  66. OpenGLImage::OpenGLImage(const OpenGLImage& image)
  67. : ImageBase(image),
  68. setupCalled(false),
  69. textureInit(true),
  70. textureId(0)
  71. #ifdef DGL_USE_GLES
  72. , convertedData(nullptr)
  73. , rawDataLast(nullptr)
  74. #endif
  75. {
  76. glGenTextures(1, &textureId);
  77. DISTRHO_SAFE_ASSERT(textureId != 0);
  78. }
  79. OpenGLImage::~OpenGLImage()
  80. {
  81. if (textureId != 0)
  82. glDeleteTextures(1, &textureId);
  83. #ifdef DGL_USE_GLES
  84. std::free(convertedData);
  85. #endif
  86. }
  87. void OpenGLImage::loadFromMemory(const char* const rdata, const Size<uint>& s, const ImageFormat fmt) noexcept
  88. {
  89. if (!textureInit)
  90. {
  91. textureInit = true;
  92. glGenTextures(1, &textureId);
  93. DISTRHO_SAFE_ASSERT(textureId != 0);
  94. }
  95. setupCalled = false;
  96. ImageBase::loadFromMemory(rdata, s, fmt);
  97. }
  98. OpenGLImage& OpenGLImage::operator=(const OpenGLImage& image) noexcept
  99. {
  100. rawData = image.rawData;
  101. size = image.size;
  102. format = image.format;
  103. setupCalled = false;
  104. if (image.isValid() && !textureInit)
  105. {
  106. textureInit = true;
  107. glGenTextures(1, &textureId);
  108. DISTRHO_SAFE_ASSERT(textureId != 0);
  109. }
  110. return *this;
  111. }
  112. #if DGL_ALLOW_DEPRECATED_METHODS
  113. OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const GLenum fmt)
  114. : ImageBase(rdata, w, h, asDISTRHOImageFormat(fmt)),
  115. setupCalled(false),
  116. textureInit(true),
  117. textureId(0)
  118. #ifdef DGL_USE_GLES
  119. , convertedData(nullptr)
  120. , rawDataLast(nullptr)
  121. #endif
  122. {
  123. glGenTextures(1, &textureId);
  124. DISTRHO_SAFE_ASSERT(textureId != 0);
  125. }
  126. OpenGLImage::OpenGLImage(const char* const rdata, const Size<uint>& s, const GLenum fmt)
  127. : ImageBase(rdata, s, asDISTRHOImageFormat(fmt)),
  128. setupCalled(false),
  129. textureInit(true),
  130. textureId(0)
  131. #ifdef DGL_USE_GLES
  132. , convertedData(nullptr)
  133. , rawDataLast(nullptr)
  134. #endif
  135. {
  136. glGenTextures(1, &textureId);
  137. DISTRHO_SAFE_ASSERT(textureId != 0);
  138. }
  139. #endif
  140. // --------------------------------------------------------------------------------------------------------------------
  141. void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor)
  142. {
  143. if (skipDrawing)
  144. return;
  145. bool needsDisableScissor = false;
  146. if (needsViewportScaling)
  147. {
  148. // limit viewport to widget bounds
  149. const int x = absolutePos.getX();
  150. const int w = static_cast<int>(self->getWidth());
  151. const int h = static_cast<int>(self->getHeight());
  152. if (d_isNotZero(viewportScaleFactor) && d_isNotEqual(viewportScaleFactor, 1.0))
  153. {
  154. glViewport(x,
  155. -d_roundToIntPositive(height * viewportScaleFactor - height + absolutePos.getY()),
  156. d_roundToIntPositive(width * viewportScaleFactor),
  157. d_roundToIntPositive(height * viewportScaleFactor));
  158. }
  159. else
  160. {
  161. const int y = static_cast<int>(height - self->getHeight()) - absolutePos.getY();
  162. glViewport(x, y, w, h);
  163. }
  164. }
  165. else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height)))
  166. {
  167. // full viewport size
  168. glViewport(0, 0, static_cast<int>(width), static_cast<int>(height));
  169. }
  170. else
  171. {
  172. // set viewport pos
  173. glViewport(d_roundToIntPositive(absolutePos.getX() * autoScaleFactor),
  174. -d_roundToIntPositive(absolutePos.getY() * autoScaleFactor),
  175. static_cast<int>(width),
  176. static_cast<int>(height));
  177. // then cut the outer bounds
  178. glScissor(d_roundToIntPositive(absolutePos.getX() * autoScaleFactor),
  179. d_roundToIntPositive(height - (static_cast<int>(self->getHeight()) + absolutePos.getY()) * autoScaleFactor),
  180. d_roundToIntPositive(self->getWidth() * autoScaleFactor),
  181. d_roundToIntPositive(self->getHeight() * autoScaleFactor));
  182. glEnable(GL_SCISSOR_TEST);
  183. needsDisableScissor = true;
  184. }
  185. // display widget
  186. self->onDisplay();
  187. if (needsDisableScissor)
  188. glDisable(GL_SCISSOR_TEST);
  189. selfw->pData->displaySubWidgets(width, height, autoScaleFactor);
  190. }
  191. // --------------------------------------------------------------------------------------------------------------------
  192. void TopLevelWidget::PrivateData::display()
  193. {
  194. if (! selfw->pData->visible)
  195. return;
  196. const Size<uint> size(window.getSize());
  197. const uint width = size.getWidth();
  198. const uint height = size.getHeight();
  199. // full viewport size
  200. glViewport(0, 0, static_cast<int>(width), static_cast<int>(height));
  201. // main widget drawing
  202. self->onDisplay();
  203. // now draw subwidgets if there are any
  204. selfw->pData->displaySubWidgets(width, height, window.pData->autoScaleFactor);
  205. }
  206. // --------------------------------------------------------------------------------------------------------------------
  207. void Window::PrivateData::renderToPicture(const char* const filename,
  208. const GraphicsContext&,
  209. const uint width,
  210. const uint height)
  211. {
  212. FILE* const f = fopen(filename, "w");
  213. DISTRHO_SAFE_ASSERT_RETURN(f != nullptr,);
  214. GLubyte* const pixels = new GLubyte[width * height * 3 * sizeof(GLubyte)];
  215. glFlush();
  216. glReadPixels(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height), GL_RGB, GL_UNSIGNED_BYTE, pixels);
  217. fprintf(f, "P3\n%d %d\n255\n", width, height);
  218. for (uint y = 0; y < height; y++)
  219. {
  220. for (uint i, x = 0; x < width; x++)
  221. {
  222. i = 3 * ((height - y - 1) * width + x);
  223. fprintf(f, "%3d %3d %3d ", pixels[i], pixels[i+1], pixels[i+2]);
  224. }
  225. fprintf(f, "\n");
  226. }
  227. delete[] pixels;
  228. fclose(f);
  229. }
  230. // --------------------------------------------------------------------------------------------------------------------
  231. END_NAMESPACE_DGL