The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

216 lines
7.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. class OpenGLFrameBufferImage : public ImagePixelData
  22. {
  23. public:
  24. OpenGLFrameBufferImage (OpenGLContext& c, int w, int h)
  25. : ImagePixelData (Image::ARGB, w, h),
  26. context (c),
  27. pixelStride (4),
  28. lineStride (width * pixelStride)
  29. {
  30. }
  31. bool initialise()
  32. {
  33. if (! frameBuffer.initialise (context, width, height))
  34. return false;
  35. frameBuffer.clear (Colours::transparentBlack);
  36. return true;
  37. }
  38. std::unique_ptr<LowLevelGraphicsContext> createLowLevelContext() override
  39. {
  40. sendDataChangeMessage();
  41. return createOpenGLGraphicsContext (context, frameBuffer);
  42. }
  43. std::unique_ptr<ImageType> createType() const override { return std::make_unique<OpenGLImageType>(); }
  44. ImagePixelData::Ptr clone() override
  45. {
  46. std::unique_ptr<OpenGLFrameBufferImage> im (new OpenGLFrameBufferImage (context, width, height));
  47. if (! im->initialise())
  48. return ImagePixelData::Ptr();
  49. Image newImage (im.release());
  50. Graphics g (newImage);
  51. g.drawImageAt (Image (*this), 0, 0, false);
  52. return ImagePixelData::Ptr (newImage.getPixelData());
  53. }
  54. void initialiseBitmapData (Image::BitmapData& bitmapData, int x, int y, Image::BitmapData::ReadWriteMode mode) override
  55. {
  56. bitmapData.pixelFormat = pixelFormat;
  57. bitmapData.lineStride = lineStride;
  58. bitmapData.pixelStride = pixelStride;
  59. switch (mode)
  60. {
  61. case Image::BitmapData::writeOnly: DataReleaser<Dummy, Writer>::initialise (frameBuffer, bitmapData, x, y); break;
  62. case Image::BitmapData::readOnly: DataReleaser<Reader, Dummy> ::initialise (frameBuffer, bitmapData, x, y); break;
  63. case Image::BitmapData::readWrite: DataReleaser<Reader, Writer>::initialise (frameBuffer, bitmapData, x, y); break;
  64. default: jassertfalse; break;
  65. }
  66. if (mode != Image::BitmapData::readOnly)
  67. sendDataChangeMessage();
  68. }
  69. OpenGLContext& context;
  70. OpenGLFrameBuffer frameBuffer;
  71. private:
  72. int pixelStride, lineStride;
  73. struct Dummy
  74. {
  75. Dummy (OpenGLFrameBuffer&, int, int, int, int) noexcept {}
  76. static void read (OpenGLFrameBuffer&, Image::BitmapData& , int, int) noexcept {}
  77. static void write (const PixelARGB*) noexcept {}
  78. };
  79. struct Reader
  80. {
  81. static void read (OpenGLFrameBuffer& frameBuffer, Image::BitmapData& bitmapData, int x, int y)
  82. {
  83. frameBuffer.readPixels ((PixelARGB*) bitmapData.data,
  84. Rectangle<int> (x, frameBuffer.getHeight() - (y + bitmapData.height), bitmapData.width, bitmapData.height));
  85. verticalRowFlip ((PixelARGB*) bitmapData.data, bitmapData.width, bitmapData.height);
  86. }
  87. static void verticalRowFlip (PixelARGB* const data, const int w, const int h)
  88. {
  89. HeapBlock<PixelARGB> tempRow (w);
  90. auto rowSize = (size_t) w * sizeof (PixelARGB);
  91. for (int y = 0; y < h / 2; ++y)
  92. {
  93. PixelARGB* const row1 = data + y * w;
  94. PixelARGB* const row2 = data + (h - 1 - y) * w;
  95. memcpy (tempRow, row1, rowSize);
  96. memcpy (row1, row2, rowSize);
  97. memcpy (row2, tempRow, rowSize);
  98. }
  99. }
  100. };
  101. struct Writer
  102. {
  103. Writer (OpenGLFrameBuffer& fb, int x, int y, int w, int h) noexcept
  104. : frameBuffer (fb), area (x, y, w, h)
  105. {}
  106. void write (const PixelARGB* const data) const noexcept
  107. {
  108. HeapBlock<PixelARGB> invertedCopy (area.getWidth() * area.getHeight());
  109. auto rowSize = (size_t) area.getWidth() * sizeof (PixelARGB);
  110. for (int y = 0; y < area.getHeight(); ++y)
  111. memcpy (invertedCopy + area.getWidth() * y,
  112. data + area.getWidth() * (area.getHeight() - 1 - y), rowSize);
  113. frameBuffer.writePixels (invertedCopy, area);
  114. }
  115. OpenGLFrameBuffer& frameBuffer;
  116. const Rectangle<int> area;
  117. JUCE_DECLARE_NON_COPYABLE (Writer)
  118. };
  119. template <class ReaderType, class WriterType>
  120. struct DataReleaser : public Image::BitmapData::BitmapDataReleaser
  121. {
  122. DataReleaser (OpenGLFrameBuffer& fb, int x, int y, int w, int h)
  123. : data ((size_t) (w * h)),
  124. writer (fb, x, y, w, h)
  125. {}
  126. ~DataReleaser()
  127. {
  128. writer.write (data);
  129. }
  130. static void initialise (OpenGLFrameBuffer& frameBuffer, Image::BitmapData& bitmapData, int x, int y)
  131. {
  132. auto* r = new DataReleaser (frameBuffer, x, y, bitmapData.width, bitmapData.height);
  133. bitmapData.dataReleaser.reset (r);
  134. bitmapData.data = (uint8*) r->data.get();
  135. bitmapData.lineStride = (bitmapData.width * bitmapData.pixelStride + 3) & ~3;
  136. ReaderType::read (frameBuffer, bitmapData, x, y);
  137. }
  138. HeapBlock<PixelARGB> data;
  139. WriterType writer;
  140. };
  141. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLFrameBufferImage)
  142. };
  143. //==============================================================================
  144. OpenGLImageType::OpenGLImageType() {}
  145. OpenGLImageType::~OpenGLImageType() {}
  146. int OpenGLImageType::getTypeID() const
  147. {
  148. return 3;
  149. }
  150. ImagePixelData::Ptr OpenGLImageType::create (Image::PixelFormat, int width, int height, bool /*shouldClearImage*/) const
  151. {
  152. OpenGLContext* currentContext = OpenGLContext::getCurrentContext();
  153. jassert (currentContext != nullptr); // an OpenGL image can only be created when a valid context is active!
  154. std::unique_ptr<OpenGLFrameBufferImage> im (new OpenGLFrameBufferImage (*currentContext, width, height));
  155. if (! im->initialise())
  156. return ImagePixelData::Ptr();
  157. return *im.release();
  158. }
  159. OpenGLFrameBuffer* OpenGLImageType::getFrameBufferFrom (const Image& image)
  160. {
  161. if (OpenGLFrameBufferImage* const glImage = dynamic_cast<OpenGLFrameBufferImage*> (image.getPixelData()))
  162. return &(glImage->frameBuffer);
  163. return nullptr;
  164. }
  165. } // namespace juce