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.

261 lines
9.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. extern XContext windowHandleXContext;
  21. //==============================================================================
  22. // Defined juce_linux_Windowing.cpp
  23. void juce_LinuxAddRepaintListener (ComponentPeer*, Component* dummy);
  24. void juce_LinuxRemoveRepaintListener (ComponentPeer*, Component* dummy);
  25. //==============================================================================
  26. class OpenGLContext::NativeContext
  27. {
  28. private:
  29. struct DummyComponent : public Component
  30. {
  31. DummyComponent (OpenGLContext::NativeContext& nativeParentContext)
  32. : native (nativeParentContext)
  33. {
  34. }
  35. void handleCommandMessage (int commandId) override
  36. {
  37. if (commandId == 0)
  38. native.triggerRepaint();
  39. }
  40. OpenGLContext::NativeContext& native;
  41. };
  42. public:
  43. NativeContext (Component& comp,
  44. const OpenGLPixelFormat& cPixelFormat,
  45. void* shareContext,
  46. bool /*useMultisampling*/,
  47. OpenGLVersion)
  48. : component (comp), contextToShareWith (shareContext), dummy (*this)
  49. {
  50. display = XWindowSystem::getInstance()->getDisplay();
  51. XWindowSystemUtilities::ScopedXLock xLock;
  52. X11Symbols::getInstance()->xSync (display, False);
  53. GLint attribs[] =
  54. {
  55. GLX_RGBA,
  56. GLX_DOUBLEBUFFER,
  57. GLX_RED_SIZE, cPixelFormat.redBits,
  58. GLX_GREEN_SIZE, cPixelFormat.greenBits,
  59. GLX_BLUE_SIZE, cPixelFormat.blueBits,
  60. GLX_ALPHA_SIZE, cPixelFormat.alphaBits,
  61. GLX_DEPTH_SIZE, cPixelFormat.depthBufferBits,
  62. GLX_STENCIL_SIZE, cPixelFormat.stencilBufferBits,
  63. GLX_ACCUM_RED_SIZE, cPixelFormat.accumulationBufferRedBits,
  64. GLX_ACCUM_GREEN_SIZE, cPixelFormat.accumulationBufferGreenBits,
  65. GLX_ACCUM_BLUE_SIZE, cPixelFormat.accumulationBufferBlueBits,
  66. GLX_ACCUM_ALPHA_SIZE, cPixelFormat.accumulationBufferAlphaBits,
  67. None
  68. };
  69. bestVisual = glXChooseVisual (display, X11Symbols::getInstance()->xDefaultScreen (display), attribs);
  70. if (bestVisual == nullptr)
  71. return;
  72. auto* peer = component.getPeer();
  73. jassert (peer != nullptr);
  74. auto windowH = (Window) peer->getNativeHandle();
  75. auto colourMap = X11Symbols::getInstance()->xCreateColormap (display, windowH, bestVisual->visual, AllocNone);
  76. XSetWindowAttributes swa;
  77. swa.colormap = colourMap;
  78. swa.border_pixel = 0;
  79. swa.event_mask = ExposureMask | StructureNotifyMask;
  80. auto glBounds = component.getTopLevelComponent()
  81. ->getLocalArea (&component, component.getLocalBounds());
  82. glBounds = Desktop::getInstance().getDisplays().logicalToPhysical (glBounds);
  83. embeddedWindow = X11Symbols::getInstance()->xCreateWindow (display, windowH,
  84. glBounds.getX(), glBounds.getY(),
  85. (unsigned int) jmax (1, glBounds.getWidth()),
  86. (unsigned int) jmax (1, glBounds.getHeight()),
  87. 0, bestVisual->depth,
  88. InputOutput,
  89. bestVisual->visual,
  90. CWBorderPixel | CWColormap | CWEventMask,
  91. &swa);
  92. X11Symbols::getInstance()->xSaveContext (display, (XID) embeddedWindow, windowHandleXContext, (XPointer) peer);
  93. X11Symbols::getInstance()->xMapWindow (display, embeddedWindow);
  94. X11Symbols::getInstance()->xFreeColormap (display, colourMap);
  95. X11Symbols::getInstance()->xSync (display, False);
  96. juce_LinuxAddRepaintListener (peer, &dummy);
  97. }
  98. ~NativeContext()
  99. {
  100. if (auto* peer = component.getPeer())
  101. {
  102. juce_LinuxRemoveRepaintListener (peer, &dummy);
  103. if (embeddedWindow != 0)
  104. {
  105. XWindowSystemUtilities::ScopedXLock xLock;
  106. X11Symbols::getInstance()->xUnmapWindow (display, embeddedWindow);
  107. X11Symbols::getInstance()->xDestroyWindow (display, embeddedWindow);
  108. X11Symbols::getInstance()->xSync (display, True);
  109. }
  110. }
  111. if (bestVisual != nullptr)
  112. X11Symbols::getInstance()->xFree (bestVisual);
  113. }
  114. bool initialiseOnRenderThread (OpenGLContext& c)
  115. {
  116. XWindowSystemUtilities::ScopedXLock xLock;
  117. renderContext = glXCreateContext (display, bestVisual, (GLXContext) contextToShareWith, GL_TRUE);
  118. c.makeActive();
  119. context = &c;
  120. return true;
  121. }
  122. void shutdownOnRenderThread()
  123. {
  124. XWindowSystemUtilities::ScopedXLock xLock;
  125. context = nullptr;
  126. deactivateCurrentContext();
  127. glXDestroyContext (display, renderContext);
  128. renderContext = nullptr;
  129. }
  130. bool makeActive() const noexcept
  131. {
  132. XWindowSystemUtilities::ScopedXLock xLock;
  133. return renderContext != nullptr
  134. && glXMakeCurrent (display, embeddedWindow, renderContext);
  135. }
  136. bool isActive() const noexcept
  137. {
  138. XWindowSystemUtilities::ScopedXLock xLock;
  139. return glXGetCurrentContext() == renderContext && renderContext != nullptr;
  140. }
  141. static void deactivateCurrentContext()
  142. {
  143. if (auto* display = XWindowSystem::getInstance()->getDisplay())
  144. {
  145. XWindowSystemUtilities::ScopedXLock xLock;
  146. glXMakeCurrent (display, None, nullptr);
  147. }
  148. }
  149. void swapBuffers()
  150. {
  151. XWindowSystemUtilities::ScopedXLock xLock;
  152. glXSwapBuffers (display, embeddedWindow);
  153. }
  154. void updateWindowPosition (Rectangle<int> newBounds)
  155. {
  156. bounds = newBounds;
  157. auto physicalBounds = Desktop::getInstance().getDisplays().logicalToPhysical (bounds);
  158. XWindowSystemUtilities::ScopedXLock xLock;
  159. X11Symbols::getInstance()->xMoveResizeWindow (display, embeddedWindow,
  160. physicalBounds.getX(), physicalBounds.getY(),
  161. (unsigned int) jmax (1, physicalBounds.getWidth()),
  162. (unsigned int) jmax (1, physicalBounds.getHeight()));
  163. }
  164. bool setSwapInterval (int numFramesPerSwap)
  165. {
  166. if (numFramesPerSwap == swapFrames)
  167. return true;
  168. if (auto GLXSwapIntervalSGI
  169. = (PFNGLXSWAPINTERVALSGIPROC) OpenGLHelpers::getExtensionFunction ("glXSwapIntervalSGI"))
  170. {
  171. XWindowSystemUtilities::ScopedXLock xLock;
  172. swapFrames = numFramesPerSwap;
  173. GLXSwapIntervalSGI (numFramesPerSwap);
  174. return true;
  175. }
  176. return false;
  177. }
  178. int getSwapInterval() const { return swapFrames; }
  179. bool createdOk() const noexcept { return true; }
  180. void* getRawContext() const noexcept { return renderContext; }
  181. GLuint getFrameBufferID() const noexcept { return 0; }
  182. void triggerRepaint()
  183. {
  184. if (context != nullptr)
  185. context->triggerRepaint();
  186. }
  187. struct Locker { Locker (NativeContext&) {} };
  188. private:
  189. Component& component;
  190. GLXContext renderContext = {};
  191. Window embeddedWindow = {};
  192. int swapFrames = 1;
  193. Rectangle<int> bounds;
  194. XVisualInfo* bestVisual = nullptr;
  195. void* contextToShareWith;
  196. OpenGLContext* context = nullptr;
  197. DummyComponent dummy;
  198. ::Display* display = nullptr;
  199. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
  200. };
  201. //==============================================================================
  202. bool OpenGLHelpers::isContextActive()
  203. {
  204. XWindowSystemUtilities::ScopedXLock xLock;
  205. return glXGetCurrentContext() != nullptr;
  206. }
  207. } // namespace juce