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.

186 lines
5.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. static int getAllowedTextureSize (int x)
  18. {
  19. #if JUCE_OPENGL_ALLOW_NON_POWER_OF_TWO_TEXTURES
  20. return x;
  21. #else
  22. return nextPowerOfTwo (x);
  23. #endif
  24. }
  25. OpenGLTexture::OpenGLTexture()
  26. : textureID (0), width (0), height (0), ownerContext (nullptr)
  27. {
  28. }
  29. OpenGLTexture::~OpenGLTexture()
  30. {
  31. release();
  32. }
  33. bool OpenGLTexture::isValidSize (int width, int height)
  34. {
  35. return isPowerOfTwo (width) && isPowerOfTwo (height);
  36. }
  37. void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum type, bool topLeft)
  38. {
  39. ownerContext = OpenGLContext::getCurrentContext();
  40. // Texture objects can only be created when the current thread has an active OpenGL
  41. // context. You'll need to create this object in one of the OpenGLContext's callbacks.
  42. jassert (ownerContext != nullptr);
  43. if (textureID == 0)
  44. {
  45. JUCE_CHECK_OPENGL_ERROR
  46. glGenTextures (1, &textureID);
  47. glBindTexture (GL_TEXTURE_2D, textureID);
  48. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  49. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  50. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  51. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  52. JUCE_CHECK_OPENGL_ERROR
  53. }
  54. else
  55. {
  56. glBindTexture (GL_TEXTURE_2D, textureID);
  57. JUCE_CHECK_OPENGL_ERROR;
  58. }
  59. glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  60. JUCE_CHECK_OPENGL_ERROR
  61. width = getAllowedTextureSize (w);
  62. height = getAllowedTextureSize (h);
  63. const GLint internalformat = type == GL_ALPHA ? GL_ALPHA : GL_RGBA;
  64. if (width != w || height != h)
  65. {
  66. glTexImage2D (GL_TEXTURE_2D, 0, internalformat,
  67. width, height, 0, type, GL_UNSIGNED_BYTE, nullptr);
  68. glTexSubImage2D (GL_TEXTURE_2D, 0, 0, topLeft ? (height - h) : 0, w, h,
  69. type, GL_UNSIGNED_BYTE, pixels);
  70. }
  71. else
  72. {
  73. glTexImage2D (GL_TEXTURE_2D, 0, internalformat,
  74. w, h, 0, type, GL_UNSIGNED_BYTE, pixels);
  75. }
  76. JUCE_CHECK_OPENGL_ERROR
  77. }
  78. template <class PixelType>
  79. struct Flipper
  80. {
  81. static void flip (HeapBlock<PixelARGB>& dataCopy, const uint8* srcData, const int lineStride,
  82. const int w, const int h)
  83. {
  84. dataCopy.malloc ((size_t) (w * h));
  85. for (int y = 0; y < h; ++y)
  86. {
  87. const PixelType* src = (const PixelType*) srcData;
  88. PixelARGB* const dst = (PixelARGB*) (dataCopy + w * (h - 1 - y));
  89. for (int x = 0; x < w; ++x)
  90. dst[x].set (src[x]);
  91. srcData += lineStride;
  92. }
  93. }
  94. };
  95. void OpenGLTexture::loadImage (const Image& image)
  96. {
  97. const int imageW = image.getWidth();
  98. const int imageH = image.getHeight();
  99. HeapBlock<PixelARGB> dataCopy;
  100. Image::BitmapData srcData (image, Image::BitmapData::readOnly);
  101. switch (srcData.pixelFormat)
  102. {
  103. case Image::ARGB: Flipper<PixelARGB> ::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH); break;
  104. case Image::RGB: Flipper<PixelRGB> ::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH); break;
  105. case Image::SingleChannel: Flipper<PixelAlpha>::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH); break;
  106. default: break;
  107. }
  108. create (imageW, imageH, dataCopy, JUCE_RGBA_FORMAT, true);
  109. }
  110. void OpenGLTexture::loadARGB (const PixelARGB* pixels, const int w, const int h)
  111. {
  112. create (w, h, pixels, JUCE_RGBA_FORMAT, false);
  113. }
  114. void OpenGLTexture::loadAlpha (const uint8* pixels, int w, int h)
  115. {
  116. create (w, h, pixels, GL_ALPHA, false);
  117. }
  118. void OpenGLTexture::loadARGBFlipped (const PixelARGB* pixels, int w, int h)
  119. {
  120. HeapBlock<PixelARGB> flippedCopy;
  121. Flipper<PixelARGB>::flip (flippedCopy, (const uint8*) pixels, 4 * w, w, h);
  122. create (w, h, flippedCopy, JUCE_RGBA_FORMAT, true);
  123. }
  124. void OpenGLTexture::release()
  125. {
  126. if (textureID != 0)
  127. {
  128. // If the texture is deleted while the owner context is not active, it's
  129. // impossible to delete it, so this will be a leak until the context itself
  130. // is deleted.
  131. jassert (ownerContext == OpenGLContext::getCurrentContext());
  132. if (ownerContext == OpenGLContext::getCurrentContext())
  133. {
  134. glDeleteTextures (1, &textureID);
  135. textureID = 0;
  136. width = 0;
  137. height = 0;
  138. }
  139. }
  140. }
  141. void OpenGLTexture::bind() const
  142. {
  143. glBindTexture (GL_TEXTURE_2D, textureID);
  144. }
  145. void OpenGLTexture::unbind() const
  146. {
  147. glBindTexture (GL_TEXTURE_2D, 0);
  148. }