Add remaining files
[juce-lv2.git] / juce / source / src / gui / components / special / juce_OpenGLComponent.cpp
blob7afbdcd2813be0e3bd530a456f1e7ed3d7eda677
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
28 #if JUCE_OPENGL
30 BEGIN_JUCE_NAMESPACE
32 #include "juce_OpenGLComponent.h"
33 #include "../windows/juce_ComponentPeer.h"
34 #include "../layout/juce_ComponentMovementWatcher.h"
35 #include "../../../threads/juce_Thread.h"
38 //==============================================================================
39 extern void juce_glViewport (const int w, const int h);
42 //==============================================================================
43 OpenGLPixelFormat::OpenGLPixelFormat (const int bitsPerRGBComponent,
44 const int alphaBits_,
45 const int depthBufferBits_,
46 const int stencilBufferBits_)
47 : redBits (bitsPerRGBComponent),
48 greenBits (bitsPerRGBComponent),
49 blueBits (bitsPerRGBComponent),
50 alphaBits (alphaBits_),
51 depthBufferBits (depthBufferBits_),
52 stencilBufferBits (stencilBufferBits_),
53 accumulationBufferRedBits (0),
54 accumulationBufferGreenBits (0),
55 accumulationBufferBlueBits (0),
56 accumulationBufferAlphaBits (0),
57 fullSceneAntiAliasingNumSamples (0)
61 OpenGLPixelFormat::OpenGLPixelFormat (const OpenGLPixelFormat& other)
62 : redBits (other.redBits),
63 greenBits (other.greenBits),
64 blueBits (other.blueBits),
65 alphaBits (other.alphaBits),
66 depthBufferBits (other.depthBufferBits),
67 stencilBufferBits (other.stencilBufferBits),
68 accumulationBufferRedBits (other.accumulationBufferRedBits),
69 accumulationBufferGreenBits (other.accumulationBufferGreenBits),
70 accumulationBufferBlueBits (other.accumulationBufferBlueBits),
71 accumulationBufferAlphaBits (other.accumulationBufferAlphaBits),
72 fullSceneAntiAliasingNumSamples (other.fullSceneAntiAliasingNumSamples)
76 OpenGLPixelFormat& OpenGLPixelFormat::operator= (const OpenGLPixelFormat& other)
78 redBits = other.redBits;
79 greenBits = other.greenBits;
80 blueBits = other.blueBits;
81 alphaBits = other.alphaBits;
82 depthBufferBits = other.depthBufferBits;
83 stencilBufferBits = other.stencilBufferBits;
84 accumulationBufferRedBits = other.accumulationBufferRedBits;
85 accumulationBufferGreenBits = other.accumulationBufferGreenBits;
86 accumulationBufferBlueBits = other.accumulationBufferBlueBits;
87 accumulationBufferAlphaBits = other.accumulationBufferAlphaBits;
88 fullSceneAntiAliasingNumSamples = other.fullSceneAntiAliasingNumSamples;
89 return *this;
92 bool OpenGLPixelFormat::operator== (const OpenGLPixelFormat& other) const
94 return redBits == other.redBits
95 && greenBits == other.greenBits
96 && blueBits == other.blueBits
97 && alphaBits == other.alphaBits
98 && depthBufferBits == other.depthBufferBits
99 && stencilBufferBits == other.stencilBufferBits
100 && accumulationBufferRedBits == other.accumulationBufferRedBits
101 && accumulationBufferGreenBits == other.accumulationBufferGreenBits
102 && accumulationBufferBlueBits == other.accumulationBufferBlueBits
103 && accumulationBufferAlphaBits == other.accumulationBufferAlphaBits
104 && fullSceneAntiAliasingNumSamples == other.fullSceneAntiAliasingNumSamples;
107 //==============================================================================
108 static Array<OpenGLContext*> knownContexts;
110 OpenGLContext::OpenGLContext() noexcept
112 knownContexts.add (this);
115 OpenGLContext::~OpenGLContext()
117 knownContexts.removeValue (this);
120 OpenGLContext* OpenGLContext::getCurrentContext()
122 for (int i = knownContexts.size(); --i >= 0;)
124 OpenGLContext* const oglc = knownContexts.getUnchecked(i);
126 if (oglc->isActive())
127 return oglc;
130 return nullptr;
133 //==============================================================================
134 class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher
136 public:
137 //==============================================================================
138 OpenGLComponentWatcher (OpenGLComponent* const owner_)
139 : ComponentMovementWatcher (owner_),
140 owner (owner_)
144 //==============================================================================
145 void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
147 owner->updateContextPosition();
150 void componentPeerChanged()
152 owner->recreateContextAsync();
155 void componentVisibilityChanged()
157 if (! owner->isShowing())
158 owner->stopBackgroundThread();
161 //==============================================================================
162 private:
163 OpenGLComponent* const owner;
165 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
168 //==============================================================================
169 class OpenGLComponent::OpenGLComponentRenderThread : public Thread
171 public:
172 OpenGLComponentRenderThread (OpenGLComponent& owner_)
173 : Thread ("OpenGL Render"),
174 owner (owner_)
178 void run()
180 while (! threadShouldExit())
182 const uint32 startOfRendering = Time::getMillisecondCounter();
184 if (! owner.renderAndSwapBuffers())
185 break;
187 const int elapsed = Time::getMillisecondCounter() - startOfRendering;
188 Thread::sleep (jmax (1, 20 - elapsed));
191 #if JUCE_LINUX
192 owner.deleteContext();
193 #endif
196 private:
197 OpenGLComponent& owner;
199 JUCE_DECLARE_NON_COPYABLE (OpenGLComponentRenderThread);
202 void OpenGLComponent::startRenderThread()
204 if (renderThread == nullptr)
205 renderThread = new OpenGLComponentRenderThread (*this);
207 renderThread->startThread (6);
210 void OpenGLComponent::stopRenderThread()
212 if (renderThread != nullptr)
214 renderThread->stopThread (5000);
215 renderThread = nullptr;
218 #if ! JUCE_LINUX
219 deleteContext();
220 #endif
223 //==============================================================================
224 OpenGLComponent::OpenGLComponent (const OpenGLType type_, const bool useBackgroundThread)
225 : type (type_),
226 contextToShareListsWith (nullptr),
227 needToUpdateViewport (true),
228 needToDeleteContext (false),
229 threadStarted (false),
230 useThread (useBackgroundThread)
232 setOpaque (true);
233 componentWatcher = new OpenGLComponentWatcher (this);
236 OpenGLComponent::~OpenGLComponent()
238 stopBackgroundThread();
239 componentWatcher = nullptr;
242 const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
244 OpenGLPixelFormat pf;
246 const ScopedLock sl (contextLock);
247 if (context != nullptr)
248 pf = context->getPixelFormat();
250 return pf;
253 void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
255 if (! (preferredPixelFormat == formatToUse))
257 const ScopedLock sl (contextLock);
258 preferredPixelFormat = formatToUse;
259 recreateContextAsync();
263 void OpenGLComponent::shareWith (OpenGLContext* c)
265 if (contextToShareListsWith != c)
267 const ScopedLock sl (contextLock);
268 contextToShareListsWith = c;
269 recreateContextAsync();
273 void OpenGLComponent::recreateContextAsync()
275 const ScopedLock sl (contextLock);
276 needToDeleteContext = true;
277 repaint();
280 bool OpenGLComponent::makeCurrentContextActive()
282 return context != nullptr && context->makeActive();
285 void OpenGLComponent::makeCurrentContextInactive()
287 if (context != nullptr)
288 context->makeInactive();
291 bool OpenGLComponent::isActiveContext() const noexcept
293 return context != nullptr && context->isActive();
296 void OpenGLComponent::swapBuffers()
298 if (context != nullptr)
299 context->swapBuffers();
302 void OpenGLComponent::updateContext()
304 if (needToDeleteContext)
305 deleteContext();
307 if (context == nullptr)
309 const ScopedLock sl (contextLock);
311 if (context == nullptr)
313 context = createContext();
315 if (context != nullptr)
317 #if JUCE_LINUX
318 if (! useThread)
319 #endif
320 updateContextPosition();
322 if (context->makeActive())
324 newOpenGLContextCreated();
325 context->makeInactive();
332 void OpenGLComponent::deleteContext()
334 const ScopedLock sl (contextLock);
335 if (context != nullptr)
337 if (context->makeActive())
339 releaseOpenGLContext();
340 context->makeInactive();
343 context = nullptr;
346 needToDeleteContext = false;
349 void OpenGLComponent::updateContextPosition()
351 needToUpdateViewport = true;
353 if (getWidth() > 0 && getHeight() > 0)
355 Component* const topComp = getTopLevelComponent();
357 if (topComp->getPeer() != nullptr)
359 const ScopedLock sl (contextLock);
361 if (context != nullptr)
362 context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds()));
367 void OpenGLComponent::stopBackgroundThread()
369 if (threadStarted)
371 stopRenderThread();
372 threadStarted = false;
376 void OpenGLComponent::paint (Graphics&)
378 ComponentPeer* const peer = getPeer();
380 if (useThread)
382 if (peer != nullptr && isShowing())
384 #if ! JUCE_LINUX
385 updateContext();
386 #endif
388 if (! threadStarted)
390 threadStarted = true;
391 startRenderThread();
395 else
397 updateContext();
399 if (! renderAndSwapBuffers())
400 return;
403 if (peer != nullptr)
405 const Point<int> topLeft (getScreenPosition() - peer->getScreenPosition());
406 peer->addMaskedRegion (topLeft.getX(), topLeft.getY(), getWidth(), getHeight());
410 bool OpenGLComponent::renderAndSwapBuffers()
412 const ScopedLock sl (contextLock);
414 #if JUCE_LINUX
415 updateContext();
416 #endif
418 if (context != nullptr)
420 if (! makeCurrentContextActive())
421 return false;
423 if (needToUpdateViewport)
425 needToUpdateViewport = false;
426 juce_glViewport (getWidth(), getHeight());
429 renderOpenGL();
430 swapBuffers();
433 return true;
436 void OpenGLComponent::internalRepaint (int x, int y, int w, int h)
438 Component::internalRepaint (x, y, w, h);
440 if (context != nullptr)
441 context->repaint();
445 END_JUCE_NAMESPACE
447 #endif