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.

343 lines
15KB

  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. #pragma once
  20. //==============================================================================
  21. /**
  22. Creates an OpenGL context, which can be attached to a component.
  23. To render some OpenGL, you should create an instance of an OpenGLContext,
  24. and call attachTo() to make it use a component as its render target.
  25. To provide threaded rendering, you can supply an OpenGLRenderer object that
  26. will be used to render each frame.
  27. Before your target component or OpenGLRenderer is deleted, you MUST call
  28. detach() or delete the OpenGLContext to allow the background thread to
  29. stop and the native resources to be freed safely.
  30. @see OpenGLRenderer
  31. */
  32. class JUCE_API OpenGLContext
  33. {
  34. public:
  35. OpenGLContext();
  36. /** Destructor. */
  37. ~OpenGLContext();
  38. //==============================================================================
  39. /** Gives the context an OpenGLRenderer to use to do the drawing.
  40. The object that you give it will not be owned by the context, so it's the caller's
  41. responsibility to manage its lifetime and make sure that it doesn't get deleted
  42. while the context may be using it. To stop the context using a renderer, just call
  43. this method with a null pointer.
  44. Note: This must be called BEFORE attaching your context to a target component!
  45. */
  46. void setRenderer (OpenGLRenderer*) noexcept;
  47. /** Attaches the context to a target component.
  48. If the component is not fully visible, this call will wait until the component
  49. is shown before actually creating a native context for it.
  50. When a native context is created, a thread is started, and will be used to call
  51. the OpenGLRenderer methods. The context will be floated above the target component,
  52. and when the target moves, it will track it. If the component is hidden/shown, the
  53. context may be deleted and re-created.
  54. */
  55. void attachTo (Component&);
  56. /** Detaches the context from its target component and deletes any native resources.
  57. If the context has not been attached, this will do nothing. Otherwise, it will block
  58. until the context and its thread have been cleaned up.
  59. */
  60. void detach();
  61. /** Returns true if the context is attached to a component and is on-screen.
  62. Note that if you call attachTo() for a non-visible component, this method will
  63. return false until the component is made visible.
  64. */
  65. bool isAttached() const noexcept;
  66. /** Returns the component to which this context is currently attached, or nullptr. */
  67. Component* getTargetComponent() const noexcept;
  68. /** If the given component has an OpenGLContext attached, then this will return it. */
  69. static OpenGLContext* getContextAttachedTo (Component& component) noexcept;
  70. //==============================================================================
  71. /** Sets the pixel format which you'd like to use for the target GL surface.
  72. Note: This must be called BEFORE attaching your context to a target component!
  73. */
  74. void setPixelFormat (const OpenGLPixelFormat& preferredPixelFormat) noexcept;
  75. /** Provides a context with which you'd like this context's resources to be shared.
  76. The object passed-in here is a platform-dependent native context object, and
  77. must not be deleted while this context may still be using it! To turn off sharing,
  78. you can call this method with a null pointer.
  79. Note: This must be called BEFORE attaching your context to a target component!
  80. */
  81. void setNativeSharedContext (void* nativeContextToShareWith) noexcept;
  82. /** Enables multisampling on platforms where this is implemented.
  83. If enabling this, you must call this method before attachTo().
  84. */
  85. void setMultisamplingEnabled (bool) noexcept;
  86. /** Returns true if shaders can be used in this context. */
  87. bool areShadersAvailable() const;
  88. /** OpenGL versions, used by setOpenGLVersionRequired(). */
  89. enum OpenGLVersion
  90. {
  91. defaultGLVersion = 0,
  92. openGL3_2
  93. };
  94. /** Sets a preference for the version of GL that this context should use, if possible.
  95. Some platforms may ignore this value.
  96. */
  97. void setOpenGLVersionRequired (OpenGLVersion) noexcept;
  98. /** Enables or disables the use of the GL context to perform 2D rendering
  99. of the component to which it is attached.
  100. If this is false, then only your OpenGLRenderer will be used to perform
  101. any rendering. If true, then each time your target's paint() method needs
  102. to be called, an OpenGLGraphicsContext will be used to render it, (after
  103. calling your OpenGLRenderer if there is one).
  104. By default this is set to true. If you're not using any paint() method functionality
  105. and are doing all your rendering in an OpenGLRenderer, you should disable it
  106. to improve performance.
  107. Note: This must be called BEFORE attaching your context to a target component!
  108. */
  109. void setComponentPaintingEnabled (bool shouldPaintComponent) noexcept;
  110. /** Enables or disables continuous repainting.
  111. If set to true, the context will run a loop, re-rendering itself without waiting
  112. for triggerRepaint() to be called, at a frequency determined by the swap interval
  113. (see setSwapInterval). If false, then after each render callback, it will wait for
  114. another call to triggerRepaint() before rendering again.
  115. This is disabled by default.
  116. @see setSwapInterval
  117. */
  118. void setContinuousRepainting (bool shouldContinuouslyRepaint) noexcept;
  119. /** Asynchronously causes a repaint to be made. */
  120. void triggerRepaint();
  121. //==============================================================================
  122. /** This retrieves an object that was previously stored with setAssociatedObject().
  123. If no object is found with the given name, this will return nullptr.
  124. This method must only be called from within the GL rendering methods.
  125. @see setAssociatedObject
  126. */
  127. ReferenceCountedObject* getAssociatedObject (const char* name) const;
  128. /** Attaches a named object to the context, which will be deleted when the context is
  129. destroyed.
  130. This allows you to store an object which will be released before the context is
  131. deleted. The main purpose is for caching GL objects such as shader programs, which
  132. will become invalid when the context is deleted.
  133. This method must only be called from within the GL rendering methods.
  134. */
  135. void setAssociatedObject (const char* name, ReferenceCountedObject* newObject);
  136. //==============================================================================
  137. /** Makes this context the currently active one.
  138. You should never need to call this in normal use - the context will already be
  139. active when OpenGLRenderer::renderOpenGL() is invoked.
  140. */
  141. bool makeActive() const noexcept;
  142. /** Returns true if this context is currently active for the calling thread. */
  143. bool isActive() const noexcept;
  144. /** If any context is active on the current thread, this deactivates it.
  145. Note that on some platforms, like Android, this isn't possible.
  146. */
  147. static void deactivateCurrentContext();
  148. /** Returns the context that's currently in active use by the calling thread, or
  149. nullptr if no context is active.
  150. */
  151. static OpenGLContext* getCurrentContext();
  152. //==============================================================================
  153. /** Swaps the buffers (if the context can do this).
  154. There's normally no need to call this directly - the buffers will be swapped
  155. automatically after your OpenGLRenderer::renderOpenGL() method has been called.
  156. */
  157. void swapBuffers();
  158. /** Sets whether the context checks the vertical sync before swapping.
  159. The value is the number of frames to allow between buffer-swapping. This is
  160. fairly system-dependent, but 0 turns off syncing, 1 makes it swap on frame-boundaries,
  161. and greater numbers indicate that it should swap less often.
  162. By default, this will be set to 1.
  163. Returns true if it sets the value successfully - some platforms won't support
  164. this setting.
  165. @see setContinuousRepainting
  166. */
  167. bool setSwapInterval (int numFramesPerSwap);
  168. /** Returns the current swap-sync interval.
  169. See setSwapInterval() for info about the value returned.
  170. */
  171. int getSwapInterval() const;
  172. //==============================================================================
  173. /** Execute a lambda, function or functor on the OpenGL thread with an active
  174. context.
  175. This method will attempt to execute functor on the OpenGL thread. If
  176. blockUntilFinished is true then the method will block until the functor
  177. has finished executing.
  178. This function can only be called if the context is attached to a component.
  179. Otherwise, this function will assert.
  180. This function is useful when you need to excute house-keeping tasks such
  181. as allocating, deallocating textures or framebuffers. As such, the functor
  182. will execute without locking the message thread. Therefore, it is not
  183. intended for any drawing commands or GUI code. Any GUI code should be
  184. executed in the OpenGLRenderer::renderOpenGL callback instead.
  185. */
  186. template <typename T>
  187. void executeOnGLThread (T&& functor, bool blockUntilFinished);
  188. //==============================================================================
  189. /** Returns the scale factor used by the display that is being rendered.
  190. The scale is that of the display - see Desktop::Displays::Display::scale
  191. Note that this should only be called during an OpenGLRenderer::renderOpenGL()
  192. callback - at other times the value it returns is undefined.
  193. */
  194. double getRenderingScale() const noexcept { return currentRenderScale; }
  195. //==============================================================================
  196. /** If this context is backed by a frame buffer, this returns its ID number,
  197. or 0 if the context does not use a framebuffer.
  198. */
  199. unsigned int getFrameBufferID() const noexcept;
  200. /** Returns an OS-dependent handle to some kind of underlting OS-provided GL context.
  201. The exact type of the value returned will depend on the OS and may change
  202. if the implementation changes. If you want to use this, digging around in the
  203. native code is probably the best way to find out what it is.
  204. */
  205. void* getRawContext() const noexcept;
  206. /** This structure holds a set of dynamically loaded GL functions for use on this context. */
  207. OpenGLExtensionFunctions extensions;
  208. //==============================================================================
  209. /** Draws the currently selected texture into this context at its original size.
  210. @param targetClipArea the target area to draw into (in top-left origin coords)
  211. @param anchorPosAndTextureSize the position of this rectangle is the texture's top-left
  212. anchor position in the target space, and the size must be
  213. the total size of the texture.
  214. @param contextWidth the width of the context or framebuffer that is being drawn into,
  215. used for scaling of the coordinates.
  216. @param contextHeight the height of the context or framebuffer that is being drawn into,
  217. used for vertical flipping of the y coordinates.
  218. @param textureOriginIsBottomLeft if true, the texture's origin is treated as being at
  219. (0, 0). If false, it is assumed to be (0, 1)
  220. */
  221. void copyTexture (const Rectangle<int>& targetClipArea,
  222. const Rectangle<int>& anchorPosAndTextureSize,
  223. int contextWidth, int contextHeight,
  224. bool textureOriginIsBottomLeft);
  225. /** Changes the amount of GPU memory that the internal cache for Images is allowed to use. */
  226. void setImageCacheSize (size_t cacheSizeBytes) noexcept;
  227. /** Returns the amount of GPU memory that the internal cache for Images is allowed to use. */
  228. size_t getImageCacheSize() const noexcept;
  229. //==============================================================================
  230. #ifndef DOXYGEN
  231. class NativeContext;
  232. #endif
  233. private:
  234. class CachedImage;
  235. class Attachment;
  236. NativeContext* nativeContext;
  237. OpenGLRenderer* renderer;
  238. double currentRenderScale;
  239. ScopedPointer<Attachment> attachment;
  240. OpenGLPixelFormat openGLPixelFormat;
  241. void* contextToShareWith;
  242. OpenGLVersion versionRequired;
  243. size_t imageCacheMaxSize;
  244. bool renderComponents, useMultisampling, continuousRepaint;
  245. //==============================================================================
  246. struct AsyncWorker : ReferenceCountedObject
  247. {
  248. typedef ReferenceCountedObjectPtr<AsyncWorker> Ptr;
  249. virtual void operator() (OpenGLContext&) = 0;
  250. virtual ~AsyncWorker() {}
  251. };
  252. template <typename T>
  253. struct AsyncWorkerFunctor : AsyncWorker
  254. {
  255. AsyncWorkerFunctor (T functorToUse) : functor (functorToUse) {}
  256. void operator() (OpenGLContext& callerContext) override { functor (callerContext); }
  257. T functor;
  258. JUCE_DECLARE_NON_COPYABLE(AsyncWorkerFunctor)
  259. };
  260. //==============================================================================
  261. CachedImage* getCachedImage() const noexcept;
  262. void execute (AsyncWorker::Ptr, bool);
  263. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLContext)
  264. };
  265. //==============================================================================
  266. #ifndef DOXYGEN
  267. template <typename T>
  268. void OpenGLContext::executeOnGLThread (T&& f, bool shouldBlock) { execute (new AsyncWorkerFunctor<T> (f), shouldBlock); }
  269. #endif