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