Collection of DPF-based plugins for packaging
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.

809 lines
22KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 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 "../Color.hpp"
  22. #include "../ImageWidgets.hpp"
  23. #include "SubWidgetPrivateData.hpp"
  24. #include "TopLevelWidgetPrivateData.hpp"
  25. #include "WidgetPrivateData.hpp"
  26. #include "WindowPrivateData.hpp"
  27. // templated classes
  28. #include "ImageBaseWidgets.cpp"
  29. START_NAMESPACE_DGL
  30. // -----------------------------------------------------------------------
  31. #if defined(DGL_USE_GLES2)
  32. static void notImplemented(const char* const name)
  33. {
  34. // d_stderr2("GLES2 function not implemented: %s", name);
  35. }
  36. #elif defined(DGL_USE_GLES3)
  37. static void notImplemented(const char* const name)
  38. {
  39. d_stderr2("GLES3 function not implemented: %s", name);
  40. }
  41. #elif defined(DGL_USE_OPENGL3)
  42. static void notImplemented(const char* const name)
  43. {
  44. d_stderr2("OpenGL3 function not implemented: %s", name);
  45. }
  46. #else
  47. # define DGL_USE_COMPAT_OPENGL
  48. #endif
  49. // -----------------------------------------------------------------------
  50. // Color
  51. void Color::setFor(const GraphicsContext&, const bool includeAlpha)
  52. {
  53. #ifdef DGL_USE_COMPAT_OPENGL
  54. if (includeAlpha)
  55. glColor4f(red, green, blue, alpha);
  56. else
  57. glColor3f(red, green, blue);
  58. #else
  59. notImplemented("Color::setFor");
  60. // unused
  61. (void)includeAlpha;
  62. #endif
  63. }
  64. // -----------------------------------------------------------------------
  65. // Line
  66. #ifdef DGL_USE_COMPAT_OPENGL
  67. template<typename T>
  68. static void drawLine(const Point<T>& posStart, const Point<T>& posEnd)
  69. {
  70. DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,);
  71. glBegin(GL_LINES);
  72. {
  73. glVertex2d(posStart.getX(), posStart.getY());
  74. glVertex2d(posEnd.getX(), posEnd.getY());
  75. }
  76. glEnd();
  77. }
  78. #endif
  79. template<typename T>
  80. void Line<T>::draw(const GraphicsContext&, const T width)
  81. {
  82. #ifdef DGL_USE_COMPAT_OPENGL
  83. DISTRHO_SAFE_ASSERT_RETURN(width != 0,);
  84. glLineWidth(static_cast<GLfloat>(width));
  85. drawLine<T>(posStart, posEnd);
  86. #else
  87. notImplemented("Line::draw");
  88. #endif
  89. }
  90. // deprecated calls
  91. template<typename T>
  92. void Line<T>::draw()
  93. {
  94. #ifdef DGL_USE_COMPAT_OPENGL
  95. drawLine<T>(posStart, posEnd);
  96. #else
  97. notImplemented("Line::draw");
  98. #endif
  99. }
  100. template class Line<double>;
  101. template class Line<float>;
  102. template class Line<int>;
  103. template class Line<uint>;
  104. template class Line<short>;
  105. template class Line<ushort>;
  106. // -----------------------------------------------------------------------
  107. // Circle
  108. #ifdef DGL_USE_COMPAT_OPENGL
  109. template<typename T>
  110. static void drawCircle(const Point<T>& pos,
  111. const uint numSegments,
  112. const float size,
  113. const float sin,
  114. const float cos,
  115. const bool outline)
  116. {
  117. DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,);
  118. const T origx = pos.getX();
  119. const T origy = pos.getY();
  120. double t, x = size, y = 0.0;
  121. glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);
  122. for (uint i=0; i<numSegments; ++i)
  123. {
  124. glVertex2d(x + origx, y + origy);
  125. t = x;
  126. x = cos * x - sin * y;
  127. y = sin * t + cos * y;
  128. }
  129. glEnd();
  130. }
  131. #endif
  132. template<typename T>
  133. void Circle<T>::draw(const GraphicsContext&)
  134. {
  135. #ifdef DGL_USE_COMPAT_OPENGL
  136. drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, false);
  137. #else
  138. notImplemented("Circle::draw");
  139. #endif
  140. }
  141. template<typename T>
  142. void Circle<T>::drawOutline(const GraphicsContext&, const T lineWidth)
  143. {
  144. DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);
  145. glLineWidth(static_cast<GLfloat>(lineWidth));
  146. #ifdef DGL_USE_COMPAT_OPENGL
  147. drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, true);
  148. #else
  149. notImplemented("Circle::drawOutline");
  150. #endif
  151. }
  152. // deprecated calls
  153. template<typename T>
  154. void Circle<T>::draw()
  155. {
  156. #ifdef DGL_USE_COMPAT_OPENGL
  157. drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, false);
  158. #else
  159. notImplemented("Circle::draw");
  160. #endif
  161. }
  162. template<typename T>
  163. void Circle<T>::drawOutline()
  164. {
  165. #ifdef DGL_USE_COMPAT_OPENGL
  166. drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, true);
  167. #else
  168. notImplemented("Circle::drawOutline");
  169. #endif
  170. }
  171. template class Circle<double>;
  172. template class Circle<float>;
  173. template class Circle<int>;
  174. template class Circle<uint>;
  175. template class Circle<short>;
  176. template class Circle<ushort>;
  177. // -----------------------------------------------------------------------
  178. // Triangle
  179. #ifdef DGL_USE_COMPAT_OPENGL
  180. template<typename T>
  181. static void drawTriangle(const Point<T>& pos1,
  182. const Point<T>& pos2,
  183. const Point<T>& pos3,
  184. const bool outline)
  185. {
  186. DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,);
  187. glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);
  188. {
  189. glVertex2d(pos1.getX(), pos1.getY());
  190. glVertex2d(pos2.getX(), pos2.getY());
  191. glVertex2d(pos3.getX(), pos3.getY());
  192. }
  193. glEnd();
  194. }
  195. #endif
  196. template<typename T>
  197. void Triangle<T>::draw(const GraphicsContext&)
  198. {
  199. #ifdef DGL_USE_COMPAT_OPENGL
  200. drawTriangle<T>(pos1, pos2, pos3, false);
  201. #else
  202. notImplemented("Triangle::draw");
  203. #endif
  204. }
  205. template<typename T>
  206. void Triangle<T>::drawOutline(const GraphicsContext&, const T lineWidth)
  207. {
  208. DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);
  209. glLineWidth(static_cast<GLfloat>(lineWidth));
  210. #ifdef DGL_USE_COMPAT_OPENGL
  211. drawTriangle<T>(pos1, pos2, pos3, true);
  212. #else
  213. notImplemented("Triangle::drawOutline");
  214. #endif
  215. }
  216. // deprecated calls
  217. template<typename T>
  218. void Triangle<T>::draw()
  219. {
  220. #ifdef DGL_USE_COMPAT_OPENGL
  221. drawTriangle<T>(pos1, pos2, pos3, false);
  222. #else
  223. notImplemented("Triangle::draw");
  224. #endif
  225. }
  226. template<typename T>
  227. void Triangle<T>::drawOutline()
  228. {
  229. #ifdef DGL_USE_COMPAT_OPENGL
  230. drawTriangle<T>(pos1, pos2, pos3, true);
  231. #else
  232. notImplemented("Triangle::drawOutline");
  233. #endif
  234. }
  235. template class Triangle<double>;
  236. template class Triangle<float>;
  237. template class Triangle<int>;
  238. template class Triangle<uint>;
  239. template class Triangle<short>;
  240. template class Triangle<ushort>;
  241. // -----------------------------------------------------------------------
  242. // Rectangle
  243. #ifdef DGL_USE_COMPAT_OPENGL
  244. template<typename T>
  245. static void drawRectangle(const Rectangle<T>& rect, const bool outline)
  246. {
  247. DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),);
  248. glBegin(outline ? GL_LINE_LOOP : GL_QUADS);
  249. {
  250. const T x = rect.getX();
  251. const T y = rect.getY();
  252. const T w = rect.getWidth();
  253. const T h = rect.getHeight();
  254. glTexCoord2f(0.0f, 0.0f);
  255. glVertex2d(x, y);
  256. glTexCoord2f(1.0f, 0.0f);
  257. glVertex2d(x+w, y);
  258. glTexCoord2f(1.0f, 1.0f);
  259. glVertex2d(x+w, y+h);
  260. glTexCoord2f(0.0f, 1.0f);
  261. glVertex2d(x, y+h);
  262. }
  263. glEnd();
  264. }
  265. #endif
  266. template<typename T>
  267. void Rectangle<T>::draw(const GraphicsContext&)
  268. {
  269. #ifdef DGL_USE_COMPAT_OPENGL
  270. drawRectangle<T>(*this, false);
  271. #else
  272. notImplemented("Rectangle::draw");
  273. #endif
  274. }
  275. template<typename T>
  276. void Rectangle<T>::drawOutline(const GraphicsContext&, const T lineWidth)
  277. {
  278. DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);
  279. glLineWidth(static_cast<GLfloat>(lineWidth));
  280. #ifdef DGL_USE_COMPAT_OPENGL
  281. drawRectangle<T>(*this, true);
  282. #else
  283. notImplemented("Rectangle::drawOutline");
  284. #endif
  285. }
  286. // deprecated calls
  287. template<typename T>
  288. void Rectangle<T>::draw()
  289. {
  290. #ifdef DGL_USE_COMPAT_OPENGL
  291. drawRectangle<T>(*this, false);
  292. #else
  293. notImplemented("Rectangle::draw");
  294. #endif
  295. }
  296. template<typename T>
  297. void Rectangle<T>::drawOutline()
  298. {
  299. #ifdef DGL_USE_COMPAT_OPENGL
  300. drawRectangle<T>(*this, true);
  301. #else
  302. notImplemented("Rectangle::drawOutline");
  303. #endif
  304. }
  305. template class Rectangle<double>;
  306. template class Rectangle<float>;
  307. template class Rectangle<int>;
  308. template class Rectangle<uint>;
  309. template class Rectangle<short>;
  310. template class Rectangle<ushort>;
  311. // -----------------------------------------------------------------------
  312. // OpenGLImage
  313. static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId)
  314. {
  315. DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),);
  316. glEnable(GL_TEXTURE_2D);
  317. glBindTexture(GL_TEXTURE_2D, textureId);
  318. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  319. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  320. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  321. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
  322. static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
  323. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);
  324. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  325. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  326. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
  327. static_cast<GLsizei>(image.getWidth()),
  328. static_cast<GLsizei>(image.getHeight()),
  329. 0,
  330. asOpenGLImageFormat(image.getFormat()), GL_UNSIGNED_BYTE, image.getRawData());
  331. glBindTexture(GL_TEXTURE_2D, 0);
  332. glDisable(GL_TEXTURE_2D);
  333. }
  334. static void drawOpenGLImage(const OpenGLImage& image, const Point<int>& pos, const GLuint textureId, bool& setupCalled)
  335. {
  336. if (textureId == 0 || image.isInvalid())
  337. return;
  338. if (! setupCalled)
  339. {
  340. setupOpenGLImage(image, textureId);
  341. setupCalled = true;
  342. }
  343. #ifdef DGL_USE_COMPAT_OPENGL
  344. glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  345. #endif
  346. glEnable(GL_TEXTURE_2D);
  347. glBindTexture(GL_TEXTURE_2D, textureId);
  348. #ifdef DGL_USE_COMPAT_OPENGL
  349. glBegin(GL_QUADS);
  350. {
  351. const int x = pos.getX();
  352. const int y = pos.getY();
  353. const int w = static_cast<int>(image.getWidth());
  354. const int h = static_cast<int>(image.getHeight());
  355. glTexCoord2f(0.0f, 0.0f);
  356. glVertex2d(x, y);
  357. glTexCoord2f(1.0f, 0.0f);
  358. glVertex2d(x+w, y);
  359. glTexCoord2f(1.0f, 1.0f);
  360. glVertex2d(x+w, y+h);
  361. glTexCoord2f(0.0f, 1.0f);
  362. glVertex2d(x, y+h);
  363. }
  364. glEnd();
  365. #endif
  366. glBindTexture(GL_TEXTURE_2D, 0);
  367. glDisable(GL_TEXTURE_2D);
  368. }
  369. OpenGLImage::OpenGLImage()
  370. : ImageBase(),
  371. textureId(0),
  372. setupCalled(false)
  373. {
  374. glGenTextures(1, &textureId);
  375. DISTRHO_SAFE_ASSERT(textureId != 0);
  376. }
  377. OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const ImageFormat fmt)
  378. : ImageBase(rdata, w, h, fmt),
  379. textureId(0),
  380. setupCalled(false)
  381. {
  382. glGenTextures(1, &textureId);
  383. DISTRHO_SAFE_ASSERT(textureId != 0);
  384. }
  385. OpenGLImage::OpenGLImage(const char* const rdata, const Size<uint>& s, const ImageFormat fmt)
  386. : ImageBase(rdata, s, fmt),
  387. textureId(0),
  388. setupCalled(false)
  389. {
  390. glGenTextures(1, &textureId);
  391. DISTRHO_SAFE_ASSERT(textureId != 0);
  392. }
  393. OpenGLImage::OpenGLImage(const OpenGLImage& image)
  394. : ImageBase(image),
  395. textureId(0),
  396. setupCalled(false)
  397. {
  398. glGenTextures(1, &textureId);
  399. DISTRHO_SAFE_ASSERT(textureId != 0);
  400. }
  401. OpenGLImage::~OpenGLImage()
  402. {
  403. if (textureId != 0)
  404. glDeleteTextures(1, &textureId);
  405. }
  406. void OpenGLImage::loadFromMemory(const char* const rdata, const Size<uint>& s, const ImageFormat fmt) noexcept
  407. {
  408. setupCalled = false;
  409. ImageBase::loadFromMemory(rdata, s, fmt);
  410. }
  411. void OpenGLImage::drawAt(const GraphicsContext&, const Point<int>& pos)
  412. {
  413. drawOpenGLImage(*this, pos, textureId, setupCalled);
  414. }
  415. OpenGLImage& OpenGLImage::operator=(const OpenGLImage& image) noexcept
  416. {
  417. rawData = image.rawData;
  418. size = image.size;
  419. format = image.format;
  420. setupCalled = false;
  421. return *this;
  422. }
  423. // deprecated calls
  424. OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const GLenum fmt)
  425. : ImageBase(rdata, w, h, asDISTRHOImageFormat(fmt)),
  426. textureId(0),
  427. setupCalled(false)
  428. {
  429. glGenTextures(1, &textureId);
  430. DISTRHO_SAFE_ASSERT(textureId != 0);
  431. }
  432. OpenGLImage::OpenGLImage(const char* const rdata, const Size<uint>& s, const GLenum fmt)
  433. : ImageBase(rdata, s, asDISTRHOImageFormat(fmt)),
  434. textureId(0),
  435. setupCalled(false)
  436. {
  437. glGenTextures(1, &textureId);
  438. DISTRHO_SAFE_ASSERT(textureId != 0);
  439. }
  440. void OpenGLImage::draw()
  441. {
  442. drawOpenGLImage(*this, Point<int>(0, 0), textureId, setupCalled);
  443. }
  444. void OpenGLImage::drawAt(const int x, const int y)
  445. {
  446. drawOpenGLImage(*this, Point<int>(x, y), textureId, setupCalled);
  447. }
  448. void OpenGLImage::drawAt(const Point<int>& pos)
  449. {
  450. drawOpenGLImage(*this, pos, textureId, setupCalled);
  451. }
  452. // -----------------------------------------------------------------------
  453. // ImageBaseAboutWindow
  454. #if 0
  455. template <>
  456. void ImageBaseAboutWindow<OpenGLImage>::onDisplay()
  457. {
  458. const GraphicsContext& context(getGraphicsContext());
  459. img.draw(context);
  460. }
  461. #endif
  462. template class ImageBaseAboutWindow<OpenGLImage>;
  463. // -----------------------------------------------------------------------
  464. // ImageBaseButton
  465. template class ImageBaseButton<OpenGLImage>;
  466. // -----------------------------------------------------------------------
  467. // ImageBaseKnob
  468. template <>
  469. void ImageBaseKnob<OpenGLImage>::PrivateData::init()
  470. {
  471. glTextureId = 0;
  472. glGenTextures(1, &glTextureId);
  473. }
  474. template <>
  475. void ImageBaseKnob<OpenGLImage>::PrivateData::cleanup()
  476. {
  477. if (glTextureId == 0)
  478. return;
  479. glDeleteTextures(1, &glTextureId);
  480. glTextureId = 0;
  481. }
  482. template <>
  483. void ImageBaseKnob<OpenGLImage>::onDisplay()
  484. {
  485. const GraphicsContext& context(getGraphicsContext());
  486. const float normValue = getNormalizedValue();
  487. glEnable(GL_TEXTURE_2D);
  488. glBindTexture(GL_TEXTURE_2D, pData->glTextureId);
  489. if (! pData->isReady)
  490. {
  491. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  492. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  493. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  494. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
  495. static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
  496. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);
  497. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  498. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  499. uint imageDataOffset = 0;
  500. if (pData->rotationAngle == 0)
  501. {
  502. DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,);
  503. DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);
  504. const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight);
  505. const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth);
  506. // TODO kImageFormatGreyscale
  507. const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA ||
  508. pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3);
  509. /* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1));
  510. }
  511. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
  512. static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
  513. asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset);
  514. pData->isReady = true;
  515. }
  516. const int w = static_cast<int>(getWidth());
  517. const int h = static_cast<int>(getHeight());
  518. if (pData->rotationAngle != 0)
  519. {
  520. #ifdef DGL_USE_COMPAT_OPENGL
  521. glPushMatrix();
  522. #endif
  523. const int w2 = w/2;
  524. const int h2 = h/2;
  525. #ifdef DGL_USE_COMPAT_OPENGL
  526. glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
  527. glRotatef(normValue*static_cast<float>(pData->rotationAngle), 0.0f, 0.0f, 1.0f);
  528. #endif
  529. Rectangle<int>(-w2, -h2, w, h).draw(context);
  530. #ifdef DGL_USE_COMPAT_OPENGL
  531. glPopMatrix();
  532. #endif
  533. }
  534. else
  535. {
  536. Rectangle<int>(0, 0, w, h).draw(context);
  537. }
  538. glBindTexture(GL_TEXTURE_2D, 0);
  539. glDisable(GL_TEXTURE_2D);
  540. }
  541. template class ImageBaseKnob<OpenGLImage>;
  542. // -----------------------------------------------------------------------
  543. // ImageBaseSlider
  544. template class ImageBaseSlider<OpenGLImage>;
  545. // -----------------------------------------------------------------------
  546. // ImageBaseSwitch
  547. template class ImageBaseSwitch<OpenGLImage>;
  548. // -----------------------------------------------------------------------
  549. void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor)
  550. {
  551. if (skipDrawing)
  552. return;
  553. bool needsDisableScissor = false;
  554. if (needsViewportScaling)
  555. {
  556. // limit viewport to widget bounds
  557. const int x = absolutePos.getX();
  558. const int w = static_cast<int>(self->getWidth());
  559. const int h = static_cast<int>(self->getHeight());
  560. if (viewportScaleFactor != 0.0 && viewportScaleFactor != 1.0)
  561. {
  562. glViewport(x,
  563. -static_cast<int>(height * viewportScaleFactor - height + absolutePos.getY() + 0.5),
  564. static_cast<int>(width * viewportScaleFactor + 0.5),
  565. static_cast<int>(height * viewportScaleFactor + 0.5));
  566. }
  567. else
  568. {
  569. const int y = static_cast<int>(height - self->getHeight()) - absolutePos.getY();
  570. glViewport(x, y, w, h);
  571. }
  572. }
  573. else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height)))
  574. {
  575. // full viewport size
  576. glViewport(0,
  577. -static_cast<int>(height * autoScaleFactor - height + 0.5),
  578. static_cast<int>(width * autoScaleFactor + 0.5),
  579. static_cast<int>(height * autoScaleFactor + 0.5));
  580. }
  581. else
  582. {
  583. // set viewport pos
  584. glViewport(static_cast<int>(absolutePos.getX() * autoScaleFactor + 0.5),
  585. -static_cast<int>(std::round((height * autoScaleFactor - height)
  586. + (absolutePos.getY() * autoScaleFactor))),
  587. static_cast<int>(std::round(width * autoScaleFactor)),
  588. static_cast<int>(std::round(height * autoScaleFactor)));
  589. // then cut the outer bounds
  590. glScissor(static_cast<int>(absolutePos.getX() * autoScaleFactor + 0.5),
  591. static_cast<int>(height - std::round((static_cast<int>(self->getHeight()) + absolutePos.getY())
  592. * autoScaleFactor)),
  593. static_cast<int>(std::round(self->getWidth() * autoScaleFactor)),
  594. static_cast<int>(std::round(self->getHeight() * autoScaleFactor)));
  595. glEnable(GL_SCISSOR_TEST);
  596. needsDisableScissor = true;
  597. }
  598. // display widget
  599. self->onDisplay();
  600. if (needsDisableScissor)
  601. glDisable(GL_SCISSOR_TEST);
  602. selfw->pData->displaySubWidgets(width, height, autoScaleFactor);
  603. }
  604. // -----------------------------------------------------------------------
  605. void TopLevelWidget::PrivateData::display()
  606. {
  607. if (! selfw->pData->visible)
  608. return;
  609. const Size<uint> size(window.getSize());
  610. const uint width = size.getWidth();
  611. const uint height = size.getHeight();
  612. const double autoScaleFactor = window.pData->autoScaleFactor;
  613. // full viewport size
  614. if (window.pData->autoScaling)
  615. {
  616. glViewport(0,
  617. -static_cast<int>(height * autoScaleFactor - height + 0.5),
  618. static_cast<int>(width * autoScaleFactor + 0.5),
  619. static_cast<int>(height * autoScaleFactor + 0.5));
  620. }
  621. else
  622. {
  623. glViewport(0, 0, static_cast<int>(width), static_cast<int>(height));
  624. }
  625. // main widget drawing
  626. self->onDisplay();
  627. // now draw subwidgets if there are any
  628. selfw->pData->displaySubWidgets(width, height, autoScaleFactor);
  629. }
  630. // -----------------------------------------------------------------------
  631. void Window::PrivateData::renderToPicture(const char* const filename,
  632. const GraphicsContext&,
  633. const uint width,
  634. const uint height)
  635. {
  636. FILE* const f = fopen(filename, "w");
  637. DISTRHO_SAFE_ASSERT_RETURN(f != nullptr,);
  638. GLubyte* const pixels = new GLubyte[width * height * 3 * sizeof(GLubyte)];
  639. glFlush();
  640. glReadPixels(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height), GL_RGB, GL_UNSIGNED_BYTE, pixels);
  641. fprintf(f, "P3\n%d %d\n255\n", width, height);
  642. for (uint y = 0; y < height; y++)
  643. {
  644. for (uint i, x = 0; x < width; x++)
  645. {
  646. i = 3 * ((height - y - 1) * width + x);
  647. fprintf(f, "%3d %3d %3d ", pixels[i], pixels[i+1], pixels[i+2]);
  648. }
  649. fprintf(f, "\n");
  650. }
  651. delete[] pixels;
  652. fclose(f);
  653. }
  654. // -----------------------------------------------------------------------
  655. const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept
  656. {
  657. return (const GraphicsContext&)graphicsContext;
  658. }
  659. // -----------------------------------------------------------------------
  660. END_NAMESPACE_DGL