Browse Source

OpenGL refactoring. Removed a couple of minor methods from OpenGLComponent.

tags/2021-05-28
jules 13 years ago
parent
commit
cd711a5c44
10 changed files with 224 additions and 301 deletions
  1. +1
    -1
      modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm
  2. +0
    -8
      modules/juce_opengl/native/juce_android_OpenGLComponent.cpp
  3. +0
    -8
      modules/juce_opengl/native/juce_ios_OpenGLComponent.mm
  4. +0
    -8
      modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp
  5. +2
    -4
      modules/juce_opengl/native/juce_mac_OpenGLComponent.mm
  6. +8
    -14
      modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp
  7. +203
    -230
      modules/juce_opengl/opengl/juce_OpenGLComponent.cpp
  8. +2
    -24
      modules/juce_opengl/opengl/juce_OpenGLComponent.h
  9. +3
    -0
      modules/juce_opengl/opengl/juce_OpenGLContext.h
  10. +5
    -4
      modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp

+ 1
- 1
modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm View File

@@ -705,7 +705,7 @@ void UIViewComponentPeer::toBehind (ComponentPeer* other)
}
else
{
jassertfalse; // don't know how to do this
// don't know how to do this
}
}
}


+ 0
- 8
modules/juce_opengl/native/juce_android_OpenGLComponent.cpp View File

@@ -190,14 +190,6 @@ OpenGLContext* OpenGLComponent::createContext()
return nullptr;
}
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
{
const ScopedLock sl (contextLock);
if (context != nullptr)
static_cast <AndroidGLContext*> (context.get())->updateWindowPosition (bounds);
}
bool OpenGLHelpers::isContextActive()
{
return AndroidGLContext::isAnyContextActive();


+ 0
- 8
modules/juce_opengl/native/juce_ios_OpenGLComponent.mm View File

@@ -229,14 +229,6 @@ OpenGLContext* OpenGLComponent::createContext()
return nullptr;
}
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
{
const ScopedLock sl (contextLock);
if (context != nullptr)
static_cast <GLESContext*> (context.get())->updateWindowPosition (bounds);
}
//==============================================================================
bool OpenGLHelpers::isContextActive()
{


+ 0
- 8
modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp View File

@@ -199,14 +199,6 @@ OpenGLContext* OpenGLComponent::createContext()
return (c->renderContext != 0) ? c.release() : nullptr;
}
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
{
const ScopedLock sl (contextLock);
if (context != nullptr)
static_cast<WindowedGLContext*> (context.get())->updateWindowPosition (bounds);
}
//==============================================================================
bool OpenGLHelpers::isContextActive()
{


+ 2
- 4
modules/juce_opengl/native/juce_mac_OpenGLComponent.mm View File

@@ -199,6 +199,8 @@ public:
int getWidth() const { return [view frame].size.width; }
int getHeight() const { return [view frame].size.height; }
void updateWindowPosition (const Rectangle<int>&) {}
void swapBuffers()
{
[renderContext flushBuffer];
@@ -244,10 +246,6 @@ void* OpenGLComponent::getNativeWindowHandle() const
: nullptr;
}
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>&)
{
}
//==============================================================================
bool OpenGLHelpers::isContextActive()
{


+ 8
- 14
modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp View File

@@ -99,6 +99,14 @@ public:
int getWidth() const { return component->getWidth(); }
int getHeight() const { return component->getHeight(); }
void updateWindowPosition (const Rectangle<int>& bounds)
{
if (nativeWindow != nullptr)
SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0,
bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
bool setPixelFormat (const OpenGLPixelFormat& pixelFormat)
{
makeActive();
@@ -274,20 +282,6 @@ void* OpenGLComponent::getNativeWindowHandle() const
return context != nullptr ? static_cast<WindowedGLContext*> (context.get())->getNativeWindowHandle() : nullptr;
}
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
{
const ScopedLock sl (contextLock);
if (context != nullptr)
{
ComponentPeer* peer = static_cast<WindowedGLContext*> (context.get())->nativeWindow;
SetWindowPos ((HWND) peer->getNativeHandle(), 0,
bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
}
//==============================================================================
bool OpenGLHelpers::isContextActive()
{


+ 203
- 230
modules/juce_opengl/opengl/juce_OpenGLComponent.cpp View File

@@ -28,12 +28,15 @@
#endif
class OpenGLComponent::OpenGLCachedComponentImage : public CachedComponentImage,
public Thread,
public Timer // N.B. using a Timer rather than an AsyncUpdater
// to avoid scheduling problems on Windows
{
public:
OpenGLCachedComponentImage (OpenGLComponent& owner_)
: owner (owner_)
OpenGLCachedComponentImage (OpenGLComponent& owner_, bool renderComponents_)
: Thread ("OpenGL Rendering"),
owner (owner_), needToRepaint (true),
renderComponents (renderComponents_)
{}
void paint (Graphics&)
@@ -82,21 +85,22 @@ public:
void releaseResources()
{
owner.makeCurrentRenderingTarget();
frameBuffer.release();
cachedImageFrameBuffer.release();
owner.releaseAsRenderingTarget();
}
//==============================================================================
void timerCallback()
{
stopTimer();
owner.performRender();
renderFrame();
owner.releaseAsRenderingTarget();
}
void triggerRepaint()
{
owner.needToRepaint = true;
needToRepaint = true;
#if JUCE_ANDROID
triggerAndroidOpenGLRepaint (owner.getCurrentContext());
@@ -106,19 +110,37 @@ public:
#endif
}
OpenGLFrameBuffer& getFrameBuffer (int width, int height)
void updateContextPosition()
{
const int fbW = frameBuffer.getWidth();
const int fbH = frameBuffer.getHeight();
if (owner.getWidth() > 0 && owner.getHeight() > 0)
{
Component* const topComp = owner.getTopLevelComponent();
if (topComp->getPeer() != nullptr)
{
const Rectangle<int> bounds (topComp->getLocalArea (&owner, owner.getLocalBounds()));
const ScopedLock sl (owner.contextLock);
if (owner.context != nullptr)
owner.context->updateWindowPosition (bounds);
}
}
}
//==============================================================================
void ensureFrameBufferSize (int width, int height)
{
const int fbW = cachedImageFrameBuffer.getWidth();
const int fbH = cachedImageFrameBuffer.getHeight();
if (fbW != width || fbH != height || ! frameBuffer.isValid())
if (fbW != width || fbH != height || ! cachedImageFrameBuffer.isValid())
{
jassert (owner.getCurrentContext() != nullptr);
frameBuffer.initialise (*owner.getCurrentContext(), width, height);
cachedImageFrameBuffer.initialise (*owner.getCurrentContext(), width, height);
validArea.clear();
JUCE_CHECK_OPENGL_ERROR
}
return frameBuffer;
}
void clearRegionInFrameBuffer (const RectangleList& list)
@@ -127,7 +149,7 @@ public:
glEnable (GL_SCISSOR_TEST);
const GLuint previousFrameBufferTarget = OpenGLFrameBuffer::getCurrentFrameBufferTarget();
frameBuffer.makeCurrentRenderingTarget();
cachedImageFrameBuffer.makeCurrentRenderingTarget();
for (RectangleList::Iterator i (list); i.next();)
{
@@ -141,60 +163,132 @@ public:
JUCE_CHECK_OPENGL_ERROR
}
RectangleList validArea;
bool renderFrame()
{
const ScopedLock sl (owner.contextLock);
private:
OpenGLComponent& owner;
OpenGLFrameBuffer frameBuffer;
#if JUCE_LINUX
owner.updateContext();
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLCachedComponentImage);
};
OpenGLContext* const context = owner.getCurrentContext();
//==============================================================================
class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher
{
public:
OpenGLComponentWatcher (OpenGLComponent& owner_)
: ComponentMovementWatcher (&owner_),
owner (owner_)
{
if (context != nullptr)
{
if (! context->makeActive())
return false;
JUCE_CHECK_OPENGL_ERROR
glViewport (0, 0, owner.getWidth(), owner.getHeight());
owner.renderOpenGL();
JUCE_CHECK_OPENGL_ERROR
if (renderComponents)
paintComponent (context);
context->swapBuffers();
}
return true;
}
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
void paintComponent (OpenGLContext* const context)
{
owner.updateContextPosition();
jassert (context != nullptr);
owner.contextLock.exit(); // (MM must be locked before the context lock)
MessageManagerLock mmLock (this);
owner.contextLock.enter();
if (! mmLock.lockWasGained())
return;
// you mustn't set your own cached image object for an OpenGLComponent!
jassert (dynamic_cast<OpenGLCachedComponentImage*> (owner.getCachedComponentImage()) == this);
const Rectangle<int> bounds (owner.getLocalBounds());
ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight());
if (needToRepaint)
{
needToRepaint = false;
RectangleList invalid (bounds);
invalid.subtract (validArea);
validArea = bounds;
if (! invalid.isEmpty())
{
clearRegionInFrameBuffer (invalid);
{
ScopedPointer<LowLevelGraphicsContext> g (createOpenGLGraphicsContext (*context, cachedImageFrameBuffer));
g->clipToRectangleList (invalid);
paintOwner (*g);
JUCE_CHECK_OPENGL_ERROR
}
context->makeActive();
}
}
JUCE_CHECK_OPENGL_ERROR
#if ! JUCE_ANDROID
glEnable (GL_TEXTURE_2D);
#endif
context->extensions.glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, cachedImageFrameBuffer.getTextureID());
jassert (bounds.getPosition() == Point<int>());
context->copyTexture (bounds, bounds, context->getWidth(), context->getHeight());
glBindTexture (GL_TEXTURE_2D, 0);
JUCE_CHECK_OPENGL_ERROR
}
void componentPeerChanged()
void paintOwner (LowLevelGraphicsContext& context)
{
owner.recreateContextAsync();
Graphics g (&context);
#if JUCE_ENABLE_REPAINT_DEBUGGING
g.saveState();
#endif
JUCE_TRY
{
owner.paintEntireComponent (g, false);
}
JUCE_CATCH_EXCEPTION
#if JUCE_ENABLE_REPAINT_DEBUGGING
// enabling this code will fill all areas that get repainted with a colour overlay, to show
// clearly when things are being repainted.
g.restoreState();
static Random rng;
g.fillAll (Colour ((uint8) rng.nextInt (255),
(uint8) rng.nextInt (255),
(uint8) rng.nextInt (255),
(uint8) 0x50));
#endif
}
void componentVisibilityChanged()
//==============================================================================
void run()
{
if (owner.isShowing())
owner.triggerRepaint();
else
owner.stopRenderThread();
}
initialise();
private:
OpenGLComponent& owner;
while (! threadShouldExit())
{
const uint32 frameRenderStartTime = Time::getMillisecondCounter();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};
if (renderFrame())
waitForNextFrame (frameRenderStartTime);
}
//==============================================================================
class OpenGLComponent::OpenGLComponentRenderThread : public Thread
{
public:
OpenGLComponentRenderThread (OpenGLComponent& owner_)
: Thread ("OpenGL Render"),
owner (owner_)
{
shutdown();
}
virtual void initialise()
void initialise()
{
#if JUCE_LINUX
MessageManagerLock mml (this);
@@ -202,24 +296,19 @@ public:
if (mml.lockWasGained())
{
owner.updateContext();
owner.updateContextPosition();
updateContextPosition();
}
#endif
}
virtual void shutdown()
void shutdown()
{
#if JUCE_LINUX
owner.deleteContext();
#endif
}
virtual bool renderFrame()
{
return owner.performRender();
}
virtual void waitForNextFrame (const uint32 frameRenderStartTime)
void waitForNextFrame (const uint32 frameRenderStartTime)
{
const int defaultFPS = 60;
@@ -227,50 +316,49 @@ public:
Thread::sleep (jmax (1, (1000 / defaultFPS) - elapsed));
}
void run()
{
initialise();
while (! threadShouldExit())
{
const uint32 frameRenderStartTime = Time::getMillisecondCounter();
if (! renderFrame())
break;
waitForNextFrame (frameRenderStartTime);
}
shutdown();
}
private:
//==============================================================================
RectangleList validArea;
OpenGLComponent& owner;
OpenGLFrameBuffer cachedImageFrameBuffer;
bool needToRepaint;
const bool renderComponents;
JUCE_DECLARE_NON_COPYABLE (OpenGLComponentRenderThread);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLCachedComponentImage);
};
void OpenGLComponent::startRenderThread()
//==============================================================================
class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher
{
if (renderThread == nullptr)
public:
OpenGLComponentWatcher (OpenGLComponent& owner_)
: ComponentMovementWatcher (&owner_), owner (owner_)
{
renderThread = new OpenGLComponentRenderThread (*this);
renderThread->startThread (6);
}
}
void OpenGLComponent::stopRenderThread()
{
if (renderThread != nullptr)
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
renderThread->stopThread (5000);
renderThread = nullptr;
if (owner.cachedImage != nullptr)
owner.cachedImage->updateContextPosition();
}
#if ! JUCE_LINUX
deleteContext();
#endif
}
void componentPeerChanged()
{
owner.recreateContextAsync();
}
void componentVisibilityChanged()
{
if (owner.isShowing())
owner.triggerRepaint();
else
owner.stopRenderThread();
}
private:
OpenGLComponent& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};
//==============================================================================
OpenGLComponent::OpenGLComponent (const int flags_)
@@ -280,9 +368,7 @@ OpenGLComponent::OpenGLComponent (const int flags_)
: flags (flags_),
#endif
contextToShareListsWith (nullptr),
needToUpdateViewport (true),
needToDeleteContext (false),
needToRepaint (true),
cachedImage (nullptr)
{
setOpaque (true);
@@ -299,7 +385,7 @@ OpenGLComponent::~OpenGLComponent()
be running while your sub-class isbeing destroyed, and so may make a call
to your subclass's renderOpenGL() method when it no longer exists!
*/
jassert (renderThread == nullptr);
jassert (! getGLCachedImage()->isThreadRunning());
stopRenderThread();
}
@@ -331,6 +417,20 @@ void OpenGLComponent::shareWith (OpenGLContext* c)
}
}
void OpenGLComponent::startRenderThread()
{
getGLCachedImage()->startThread (6);
}
void OpenGLComponent::stopRenderThread()
{
getGLCachedImage()->stopThread (5000);
#if ! JUCE_LINUX
deleteContext();
#endif
}
void OpenGLComponent::recreateContextAsync()
{
const ScopedLock sl (contextLock);
@@ -373,7 +473,7 @@ void OpenGLComponent::updateContext()
#if JUCE_LINUX
if (! isUsingDedicatedThread())
#endif
updateContextPosition();
getGLCachedImage()->updateContextPosition();
if (context->makeActive())
{
@@ -413,150 +513,23 @@ bool OpenGLComponent::rebuildContext()
return context != nullptr && context->makeActive();
}
void OpenGLComponent::updateContextPosition()
{
needToUpdateViewport = true;
if (getWidth() > 0 && getHeight() > 0)
{
Component* const topComp = getTopLevelComponent();
if (topComp->getPeer() != nullptr)
updateEmbeddedPosition (topComp->getLocalArea (this, getLocalBounds()));
}
}
void OpenGLComponent::triggerRepaint()
OpenGLComponent::OpenGLCachedComponentImage* OpenGLComponent::getGLCachedImage()
{
// you mustn't set your own cached image object for an OpenGLComponent!
jassert (cachedImage == nullptr
|| dynamic_cast<OpenGLCachedComponentImage*> (getCachedComponentImage()) == cachedImage);
if (cachedImage == nullptr)
setCachedComponentImage (cachedImage = new OpenGLCachedComponentImage (*this));
setCachedComponentImage (cachedImage = new OpenGLCachedComponentImage (*this, (flags & allowSubComponents) != 0));
cachedImage->triggerRepaint();
}
void OpenGLComponent::newOpenGLContextCreated() {}
void OpenGLComponent::releaseOpenGLContext() {}
void OpenGLComponent::paint (Graphics&) {}
unsigned int OpenGLComponent::getFrameBufferID() const
{
return context != nullptr ? context->getFrameBufferID() : 0;
return cachedImage;
}
bool OpenGLComponent::performRender()
void OpenGLComponent::triggerRepaint()
{
const ScopedLock sl (contextLock);
#if JUCE_LINUX
updateContext();
#endif
if (context != nullptr)
{
if (! makeCurrentRenderingTarget())
return false;
JUCE_CHECK_OPENGL_ERROR
if (needToUpdateViewport)
{
needToUpdateViewport = false;
glViewport (0, 0, getWidth(), getHeight());
}
JUCE_CHECK_OPENGL_ERROR
renderOpenGL();
JUCE_CHECK_OPENGL_ERROR
if ((flags & allowSubComponents) != 0)
{
contextLock.exit(); // (MM must be locked before the context lock)
MessageManagerLock mmLock (renderThread);
contextLock.enter();
if (! mmLock.lockWasGained())
return false;
// you mustn't set your own cached image object for an OpenGLComponent!
jassert (dynamic_cast<OpenGLCachedComponentImage*> (getCachedComponentImage()) == cachedImage);
const Rectangle<int> bounds (getLocalBounds());
OpenGLFrameBuffer& frameBuffer = cachedImage->getFrameBuffer (bounds.getWidth(), bounds.getHeight());
JUCE_CHECK_OPENGL_ERROR
if (needToRepaint)
{
needToRepaint = false;
RectangleList invalid (bounds);
invalid.subtract (cachedImage->validArea);
cachedImage->validArea = bounds;
if (! invalid.isEmpty())
{
jassert (getCurrentContext() != nullptr);
cachedImage->clearRegionInFrameBuffer (invalid);
{
ScopedPointer<LowLevelGraphicsContext> g (createOpenGLGraphicsContext (*getCurrentContext(), frameBuffer));
JUCE_CHECK_OPENGL_ERROR
g->clipToRectangleList (invalid);
paintSelf (*g);
JUCE_CHECK_OPENGL_ERROR
}
makeCurrentRenderingTarget();
}
}
JUCE_CHECK_OPENGL_ERROR
#if ! JUCE_ANDROID
glEnable (GL_TEXTURE_2D);
#endif
context->extensions.glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, frameBuffer.getTextureID());
jassert (bounds.getPosition() == Point<int>());
context->copyTexture (bounds, bounds, context->getWidth(), context->getHeight());
glBindTexture (GL_TEXTURE_2D, 0);
JUCE_CHECK_OPENGL_ERROR
}
swapBuffers();
}
return true;
getGLCachedImage()->triggerRepaint();
}
void OpenGLComponent::paintSelf (LowLevelGraphicsContext& context)
{
Graphics g (&context);
#if JUCE_ENABLE_REPAINT_DEBUGGING
g.saveState();
#endif
JUCE_TRY
{
paintEntireComponent (g, false);
}
JUCE_CATCH_EXCEPTION
#if JUCE_ENABLE_REPAINT_DEBUGGING
// enabling this code will fill all areas that get repainted with a colour overlay, to show
// clearly when things are being repainted.
g.restoreState();
static Random rng;
g.fillAll (Colour ((uint8) rng.nextInt (255),
(uint8) rng.nextInt (255),
(uint8) rng.nextInt (255),
(uint8) 0x50));
#endif
}
void OpenGLComponent::newOpenGLContextCreated() {}
void OpenGLComponent::releaseOpenGLContext() {}
void OpenGLComponent::paint (Graphics&) {}

+ 2
- 24
modules/juce_opengl/opengl/juce_OpenGLComponent.h View File

@@ -217,15 +217,6 @@ public:
void triggerRepaint();
//==============================================================================
/** This returns a critical section that can be used to lock the current context.
Because the context that is used by this component can change, e.g. when the
component is shown or hidden, then if you're rendering to it on a background
thread, this allows you to lock the context for the duration of your rendering
routine.
*/
CriticalSection& getContextLock() noexcept { return contextLock; }
/** Delete the context.
You should only need to call this if you've written a custom thread - if so, make
sure that your thread calls this before it terminates.
@@ -243,11 +234,6 @@ public:
*/
bool rebuildContext();
/** If this component is backed by a frame buffer, this returns its ID number, or
0 if the component has no accessible framebuffer.
*/
unsigned int getFrameBufferID() const;
//==============================================================================
/** Returns the native handle of an embedded heavyweight window, if there is one.
@@ -262,11 +248,6 @@ public:
private:
const int flags;
class OpenGLComponentRenderThread;
friend class OpenGLComponentRenderThread;
friend class ScopedPointer <OpenGLComponentRenderThread>;
ScopedPointer <OpenGLComponentRenderThread> renderThread;
class OpenGLComponentWatcher;
friend class OpenGLComponentWatcher;
friend class ScopedPointer <OpenGLComponentWatcher>;
@@ -276,20 +257,17 @@ private:
CriticalSection contextLock;
OpenGLPixelFormat preferredPixelFormat;
bool needToUpdateViewport, needToDeleteContext, needToRepaint;
bool needToDeleteContext;
class OpenGLCachedComponentImage;
friend class OpenGLCachedComponentImage;
OpenGLCachedComponentImage* cachedImage;
OpenGLCachedComponentImage* getGLCachedImage();
OpenGLContext* createContext();
void updateContext();
void updateContextPosition();
void recreateContextAsync();
void updateEmbeddedPosition (const Rectangle<int>&);
void startRenderThread();
bool performRender();
void paintSelf (LowLevelGraphicsContext&);
int renderAndSwapBuffers(); // (This method has been deprecated)


+ 3
- 0
modules/juce_opengl/opengl/juce_OpenGLContext.h View File

@@ -82,6 +82,9 @@ public:
/** Returns the height of this context */
virtual int getHeight() const = 0;
/** Updates the native context's area within its parent. */
virtual void updateWindowPosition (const Rectangle<int>&) = 0;
/** If this context is backed by a frame buffer, this returns its ID number, or
0 if the context has no accessible framebuffer.
*/


+ 5
- 4
modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp View File

@@ -2212,7 +2212,7 @@ private:
LowLevelGraphicsContext* createOpenGLContext (const Target& target)
{
#if JUCE_USE_OPENGL_SHADERSxxx
#if JUCE_USE_OPENGL_SHADERS
if (target.context.areShadersAvailable())
return new ShaderContext (target);
#endif
@@ -2226,10 +2226,11 @@ LowLevelGraphicsContext* createOpenGLContext (const Target& target)
//==============================================================================
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLComponent& target)
{
jassert (target.getCurrentContext() != nullptr); // must have a valid context when this is called!
OpenGLContext* const context = target.getCurrentContext();
jassert (context != nullptr); // must have a valid context when this is called!
return createOpenGLGraphicsContext (*target.getCurrentContext(), target.getFrameBufferID(),
target.getWidth(), target.getHeight());
return createOpenGLGraphicsContext (*context, context->getFrameBufferID(),
context->getWidth(), context->getHeight());
}
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context, OpenGLFrameBuffer& target)


Loading…
Cancel
Save