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.

571 lines
15KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2025 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. // Check for correct build config
  32. #ifndef DGL_OPENGL
  33. # error Build config error, OpenGL was NOT requested while building OpenGL2 code
  34. #endif
  35. #ifdef DGL_CAIRO
  36. # error Build config error, Cairo requested while building OpenGL2 code
  37. #endif
  38. #ifdef DGL_VULKAN
  39. # error Build config error, Vulkan requested while building OpenGL2 code
  40. #endif
  41. #ifdef DGL_USE_GLES2
  42. # error Build config error, GLESv2 requested while building OpenGL2 code
  43. #endif
  44. #ifdef DGL_USE_GLES3
  45. # error Build config error, GLESv3 requested while building OpenGL2 code
  46. #endif
  47. #ifdef DGL_USE_OPENGL3
  48. # error Build config error, OpenGL3 requested while building OpenGL2 code
  49. #endif
  50. // --------------------------------------------------------------------------------------------------------------------
  51. // Color
  52. void Color::setFor(const GraphicsContext&, const bool includeAlpha)
  53. {
  54. if (includeAlpha)
  55. glColor4f(red, green, blue, alpha);
  56. else
  57. glColor3f(red, green, blue);
  58. }
  59. // --------------------------------------------------------------------------------------------------------------------
  60. // Line
  61. template<typename T>
  62. static void drawLine(const Point<T>& posStart, const Point<T>& posEnd)
  63. {
  64. DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,);
  65. glBegin(GL_LINES);
  66. {
  67. glVertex2d(posStart.getX(), posStart.getY());
  68. glVertex2d(posEnd.getX(), posEnd.getY());
  69. }
  70. glEnd();
  71. }
  72. template<typename T>
  73. void Line<T>::draw(const GraphicsContext&, const T width)
  74. {
  75. DISTRHO_SAFE_ASSERT_RETURN(width != 0,);
  76. glLineWidth(static_cast<GLfloat>(width));
  77. drawLine<T>(posStart, posEnd);
  78. }
  79. #ifdef DGL_ALLOW_DEPRECATED_METHODS
  80. template<typename T>
  81. void Line<T>::draw()
  82. {
  83. drawLine<T>(posStart, posEnd);
  84. }
  85. #endif
  86. template class Line<double>;
  87. template class Line<float>;
  88. template class Line<int>;
  89. template class Line<uint>;
  90. template class Line<short>;
  91. template class Line<ushort>;
  92. // --------------------------------------------------------------------------------------------------------------------
  93. // Circle
  94. template<typename T>
  95. static void drawCircle(const Point<T>& pos,
  96. const uint numSegments,
  97. const float size,
  98. const float sin,
  99. const float cos,
  100. const bool outline)
  101. {
  102. DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,);
  103. const double origx = static_cast<double>(pos.getX());
  104. const double origy = static_cast<double>(pos.getY());
  105. double t;
  106. double x = size;
  107. double y = 0.0;
  108. glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);
  109. for (uint i = 0; i < numSegments; ++i)
  110. {
  111. glVertex2d(x + origx, y + origy);
  112. t = x;
  113. x = cos * x - sin * y;
  114. y = sin * t + cos * y;
  115. }
  116. glEnd();
  117. }
  118. template<typename T>
  119. static void drawCircle(const GraphicsContext&,
  120. const Point<T>& pos,
  121. const uint numSegments,
  122. const float size,
  123. const float sin,
  124. const float cos,
  125. const bool outline)
  126. {
  127. drawCircle<T>(pos, numSegments, size, sin, cos, outline);
  128. }
  129. template<typename T>
  130. void Circle<T>::draw(const GraphicsContext& context)
  131. {
  132. drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, false);
  133. }
  134. template<typename T>
  135. void Circle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
  136. {
  137. DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);
  138. glLineWidth(static_cast<GLfloat>(lineWidth));
  139. drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, true);
  140. }
  141. #ifdef DGL_ALLOW_DEPRECATED_METHODS
  142. template<typename T>
  143. void Circle<T>::draw()
  144. {
  145. drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, false);
  146. }
  147. template<typename T>
  148. void Circle<T>::drawOutline()
  149. {
  150. drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, true);
  151. }
  152. #endif
  153. template class Circle<double>;
  154. template class Circle<float>;
  155. template class Circle<int>;
  156. template class Circle<uint>;
  157. template class Circle<short>;
  158. template class Circle<ushort>;
  159. // --------------------------------------------------------------------------------------------------------------------
  160. // Triangle
  161. template<typename T>
  162. static void drawTriangle(const Point<T>& pos1,
  163. const Point<T>& pos2,
  164. const Point<T>& pos3,
  165. const bool outline)
  166. {
  167. DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,);
  168. glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);
  169. {
  170. glVertex2d(pos1.getX(), pos1.getY());
  171. glVertex2d(pos2.getX(), pos2.getY());
  172. glVertex2d(pos3.getX(), pos3.getY());
  173. }
  174. glEnd();
  175. }
  176. template<typename T>
  177. static void drawTriangle(const GraphicsContext&,
  178. const Point<T>& pos1,
  179. const Point<T>& pos2,
  180. const Point<T>& pos3,
  181. const bool outline)
  182. {
  183. drawTriangle<T>(pos1, pos2, pos3, outline);
  184. }
  185. template<typename T>
  186. void Triangle<T>::draw(const GraphicsContext&)
  187. {
  188. drawTriangle<T>(pos1, pos2, pos3, false);
  189. }
  190. template<typename T>
  191. void Triangle<T>::drawOutline(const GraphicsContext&, const T lineWidth)
  192. {
  193. DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);
  194. glLineWidth(static_cast<GLfloat>(lineWidth));
  195. drawTriangle<T>(pos1, pos2, pos3, true);
  196. }
  197. #ifdef DGL_ALLOW_DEPRECATED_METHODS
  198. template<typename T>
  199. void Triangle<T>::draw()
  200. {
  201. drawTriangle<T>(pos1, pos2, pos3, false);
  202. }
  203. template<typename T>
  204. void Triangle<T>::drawOutline()
  205. {
  206. drawTriangle<T>(pos1, pos2, pos3, true);
  207. }
  208. #endif
  209. template class Triangle<double>;
  210. template class Triangle<float>;
  211. template class Triangle<int>;
  212. template class Triangle<uint>;
  213. template class Triangle<short>;
  214. template class Triangle<ushort>;
  215. // --------------------------------------------------------------------------------------------------------------------
  216. // Rectangle
  217. template<typename T>
  218. static void drawRectangle(const Rectangle<T>& rect, const bool outline)
  219. {
  220. DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),);
  221. glBegin(outline ? GL_LINE_LOOP : GL_QUADS);
  222. {
  223. const T x = rect.getX();
  224. const T y = rect.getY();
  225. const T w = rect.getWidth();
  226. const T h = rect.getHeight();
  227. glTexCoord2f(0.0f, 0.0f);
  228. glVertex2d(x, y);
  229. glTexCoord2f(1.0f, 0.0f);
  230. glVertex2d(x+w, y);
  231. glTexCoord2f(1.0f, 1.0f);
  232. glVertex2d(x+w, y+h);
  233. glTexCoord2f(0.0f, 1.0f);
  234. glVertex2d(x, y+h);
  235. }
  236. glEnd();
  237. }
  238. template<typename T>
  239. void Rectangle<T>::draw(const GraphicsContext& context)
  240. {
  241. drawRectangle<T>(*this, false);
  242. }
  243. template<typename T>
  244. void Rectangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
  245. {
  246. DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);
  247. glLineWidth(static_cast<GLfloat>(lineWidth));
  248. drawRectangle<T>(*this, true);
  249. }
  250. #ifdef DGL_ALLOW_DEPRECATED_METHODS
  251. template<typename T>
  252. void Rectangle<T>::draw()
  253. {
  254. drawRectangle<T>(*this, false);
  255. }
  256. template<typename T>
  257. void Rectangle<T>::drawOutline()
  258. {
  259. drawRectangle<T>(*this, true);
  260. }
  261. #endif
  262. template class Rectangle<double>;
  263. template class Rectangle<float>;
  264. template class Rectangle<int>;
  265. template class Rectangle<uint>;
  266. template class Rectangle<short>;
  267. template class Rectangle<ushort>;
  268. // --------------------------------------------------------------------------------------------------------------------
  269. // OpenGLImage
  270. static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId)
  271. {
  272. DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),);
  273. glEnable(GL_TEXTURE_2D);
  274. glBindTexture(GL_TEXTURE_2D, textureId);
  275. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  276. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  277. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  278. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
  279. static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
  280. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);
  281. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  282. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  283. glTexImage2D(GL_TEXTURE_2D,
  284. 0,
  285. GL_RGBA,
  286. static_cast<GLsizei>(image.getWidth()),
  287. static_cast<GLsizei>(image.getHeight()),
  288. 0,
  289. asOpenGLImageFormat(image.getFormat()),
  290. GL_UNSIGNED_BYTE,
  291. image.getRawData());
  292. glBindTexture(GL_TEXTURE_2D, 0);
  293. glDisable(GL_TEXTURE_2D);
  294. }
  295. static void drawOpenGLImage(const OpenGLImage& image, const Point<int>& pos, const GLuint textureId, bool& setupCalled)
  296. {
  297. if (textureId == 0 || image.isInvalid())
  298. return;
  299. if (! setupCalled)
  300. {
  301. setupOpenGLImage(image, textureId);
  302. setupCalled = true;
  303. }
  304. glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  305. glEnable(GL_TEXTURE_2D);
  306. glBindTexture(GL_TEXTURE_2D, textureId);
  307. glBegin(GL_QUADS);
  308. {
  309. const int x = pos.getX();
  310. const int y = pos.getY();
  311. const int w = static_cast<int>(image.getWidth());
  312. const int h = static_cast<int>(image.getHeight());
  313. glTexCoord2f(0.0f, 0.0f);
  314. glVertex2d(x, y);
  315. glTexCoord2f(1.0f, 0.0f);
  316. glVertex2d(x+w, y);
  317. glTexCoord2f(1.0f, 1.0f);
  318. glVertex2d(x+w, y+h);
  319. glTexCoord2f(0.0f, 1.0f);
  320. glVertex2d(x, y+h);
  321. }
  322. glEnd();
  323. glBindTexture(GL_TEXTURE_2D, 0);
  324. glDisable(GL_TEXTURE_2D);
  325. }
  326. void OpenGLImage::drawAt(const GraphicsContext&, const Point<int>& pos)
  327. {
  328. drawOpenGLImage(*this, pos, textureId, setupCalled);
  329. }
  330. #ifdef DGL_ALLOW_DEPRECATED_METHODS
  331. void OpenGLImage::draw()
  332. {
  333. drawOpenGLImage(*this, Point<int>(0, 0), textureId, setupCalled);
  334. }
  335. void OpenGLImage::drawAt(const int x, const int y)
  336. {
  337. drawOpenGLImage(*this, Point<int>(x, y), textureId, setupCalled);
  338. }
  339. void OpenGLImage::drawAt(const Point<int>& pos)
  340. {
  341. drawOpenGLImage(*this, pos, textureId, setupCalled);
  342. }
  343. #endif
  344. // --------------------------------------------------------------------------------------------------------------------
  345. // ImageBaseAboutWindow
  346. #if 0
  347. template <>
  348. void ImageBaseAboutWindow<OpenGLImage>::onDisplay()
  349. {
  350. const GraphicsContext& context(getGraphicsContext());
  351. img.draw(context);
  352. }
  353. #endif
  354. template class ImageBaseAboutWindow<OpenGLImage>;
  355. // --------------------------------------------------------------------------------------------------------------------
  356. // ImageBaseButton
  357. template class ImageBaseButton<OpenGLImage>;
  358. // --------------------------------------------------------------------------------------------------------------------
  359. // ImageBaseKnob
  360. template <>
  361. void ImageBaseKnob<OpenGLImage>::PrivateData::init()
  362. {
  363. glTextureId = 0;
  364. glGenTextures(1, &glTextureId);
  365. }
  366. template <>
  367. void ImageBaseKnob<OpenGLImage>::PrivateData::cleanup()
  368. {
  369. if (glTextureId == 0)
  370. return;
  371. glDeleteTextures(1, &glTextureId);
  372. glTextureId = 0;
  373. }
  374. template <>
  375. void ImageBaseKnob<OpenGLImage>::onDisplay()
  376. {
  377. const GraphicsContext& context(getGraphicsContext());
  378. const float normValue = getNormalizedValue();
  379. glEnable(GL_TEXTURE_2D);
  380. glBindTexture(GL_TEXTURE_2D, pData->glTextureId);
  381. if (! pData->isReady)
  382. {
  383. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  384. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  385. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  386. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
  387. static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
  388. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);
  389. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  390. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  391. uint imageDataOffset = 0;
  392. if (pData->rotationAngle == 0)
  393. {
  394. DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,);
  395. DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);
  396. const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight);
  397. const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth);
  398. // TODO kImageFormatGreyscale
  399. const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA ||
  400. pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3);
  401. /* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1));
  402. }
  403. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
  404. static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
  405. asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset);
  406. pData->isReady = true;
  407. }
  408. const int w = static_cast<int>(getWidth());
  409. const int h = static_cast<int>(getHeight());
  410. if (pData->rotationAngle != 0)
  411. {
  412. glPushMatrix();
  413. const int w2 = w/2;
  414. const int h2 = h/2;
  415. glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
  416. glRotatef(normValue*static_cast<float>(pData->rotationAngle), 0.0f, 0.0f, 1.0f);
  417. Rectangle<int>(-w2, -h2, w, h).draw(context);
  418. glPopMatrix();
  419. }
  420. else
  421. {
  422. Rectangle<int>(0, 0, w, h).draw(context);
  423. }
  424. glBindTexture(GL_TEXTURE_2D, 0);
  425. glDisable(GL_TEXTURE_2D);
  426. }
  427. template class ImageBaseKnob<OpenGLImage>;
  428. // --------------------------------------------------------------------------------------------------------------------
  429. // ImageBaseSlider
  430. template class ImageBaseSlider<OpenGLImage>;
  431. // --------------------------------------------------------------------------------------------------------------------
  432. // ImageBaseSwitch
  433. template class ImageBaseSwitch<OpenGLImage>;
  434. // --------------------------------------------------------------------------------------------------------------------
  435. void Window::PrivateData::createContextIfNeeded()
  436. {
  437. }
  438. void Window::PrivateData::destroyContext()
  439. {
  440. }
  441. void Window::PrivateData::startContext()
  442. {
  443. }
  444. void Window::PrivateData::endContext()
  445. {
  446. }
  447. // --------------------------------------------------------------------------------------------------------------------
  448. END_NAMESPACE_DGL