mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Updated the OpenGLComponent so that it can render sub-components when using a background thread, and changed the demo to use this mode (which is faster).
This commit is contained in:
parent
c38916b675
commit
a997490f17
12 changed files with 253 additions and 244 deletions
|
|
@ -519,6 +519,7 @@ private:
|
|||
{
|
||||
public:
|
||||
DemoOpenGLComp (Component* contentComp)
|
||||
: OpenGLComponent (useBackgroundThread | allowSubComponents)
|
||||
{
|
||||
addAndMakeVisible (contentComp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1062,7 +1062,7 @@ public:
|
|||
Window editorWnd = (Window) editorComp->getWindowHandle();
|
||||
XReparentWindow (display, editorWnd, hostWindow, 0, 0);
|
||||
#else
|
||||
hostWindow = attachComponentToWindowRef (editorComp, (WindowRef) ptr);
|
||||
hostWindow = attachComponentToWindowRef (editorComp, ptr);
|
||||
#endif
|
||||
editorComp->setVisible (true);
|
||||
|
||||
|
|
|
|||
|
|
@ -241,27 +241,23 @@ private:
|
|||
|
||||
//==============================================================================
|
||||
MessageManagerLock::MessageManagerLock (Thread* const threadToCheck)
|
||||
: locked (false)
|
||||
: blockingMessage(), locked (attemptLock (threadToCheck, nullptr))
|
||||
{
|
||||
init (threadToCheck, nullptr);
|
||||
}
|
||||
|
||||
MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal)
|
||||
: locked (false)
|
||||
: blockingMessage(), locked (attemptLock (nullptr, jobToCheckForExitSignal))
|
||||
{
|
||||
init (nullptr, jobToCheckForExitSignal);
|
||||
}
|
||||
|
||||
void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const job)
|
||||
bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob* const job)
|
||||
{
|
||||
if (MessageManager::instance != nullptr)
|
||||
{
|
||||
if (MessageManager::instance == nullptr)
|
||||
return false;
|
||||
|
||||
if (MessageManager::instance->currentThreadHasLockedMessageManager())
|
||||
{
|
||||
locked = true; // either we're on the message thread, or this is a re-entrant call.
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
|
||||
if (threadToCheck == nullptr && job == nullptr)
|
||||
{
|
||||
MessageManager::instance->lockingLock.enter();
|
||||
|
|
@ -272,7 +268,7 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
|
|||
{
|
||||
if ((threadToCheck != nullptr && threadToCheck->threadShouldExit())
|
||||
|| (job != nullptr && job->shouldExit()))
|
||||
return;
|
||||
return false;
|
||||
|
||||
Thread::sleep (1);
|
||||
}
|
||||
|
|
@ -289,16 +285,14 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
|
|||
blockingMessage->releaseEvent.signal();
|
||||
blockingMessage = nullptr;
|
||||
MessageManager::instance->lockingLock.exit();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
jassert (MessageManager::instance->threadWithLock == 0);
|
||||
|
||||
MessageManager::instance->threadWithLock = Thread::getCurrentThreadId();
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageManagerLock::~MessageManagerLock() noexcept
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ public:
|
|||
@endcode
|
||||
|
||||
*/
|
||||
MessageManagerLock (Thread* threadToCheckForExitSignal = 0);
|
||||
MessageManagerLock (Thread* threadToCheckForExitSignal = nullptr);
|
||||
|
||||
//==============================================================================
|
||||
/** This has the same behaviour as the other constructor, but takes a ThreadPoolJob
|
||||
|
|
@ -304,7 +304,7 @@ private:
|
|||
ReferenceCountedObjectPtr<BlockingMessage> blockingMessage;
|
||||
bool locked;
|
||||
|
||||
void init (Thread* thread, ThreadPoolJob* job);
|
||||
bool attemptLock (Thread*, ThreadPoolJob*);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (MessageManagerLock);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -549,9 +549,9 @@ void ComponentPeer::clearMaskedRegion()
|
|||
maskedRegion.clear();
|
||||
}
|
||||
|
||||
void ComponentPeer::addMaskedRegion (int x, int y, int w, int h)
|
||||
void ComponentPeer::addMaskedRegion (const Rectangle<int>& area)
|
||||
{
|
||||
maskedRegion.add (x, y, w, h);
|
||||
maskedRegion.add (area);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ public:
|
|||
The masked region is cleared each time before a paint happens, so a component
|
||||
will have to make sure it calls this every time it's painted.
|
||||
*/
|
||||
void addMaskedRegion (int x, int y, int w, int h);
|
||||
void addMaskedRegion (const Rectangle<int>& area);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of currently-active peers.
|
||||
|
|
|
|||
|
|
@ -230,6 +230,8 @@ OpenGLContext* OpenGLComponent::createContext()
|
|||
|
||||
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
|
||||
{
|
||||
const ScopedLock sl (contextLock);
|
||||
|
||||
if (context != nullptr)
|
||||
static_cast <GLESContext*> (context.get())->updateWindowPosition (bounds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,8 @@ OpenGLContext* OpenGLComponent::createContext()
|
|||
|
||||
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
|
||||
{
|
||||
const ScopedLock sl (contextLock);
|
||||
|
||||
if (context != nullptr)
|
||||
{
|
||||
Window embeddedWindow = static_cast<WindowedGLContext*> (context.get())->embeddedWindow;
|
||||
|
|
|
|||
|
|
@ -282,6 +282,8 @@ void* OpenGLComponent::getNativeWindowHandle() const
|
|||
|
||||
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
|
||||
{
|
||||
const ScopedLock sl (contextLock);
|
||||
|
||||
if (context != nullptr)
|
||||
{
|
||||
ComponentPeer* peer = static_cast<WindowedGLContext*> (context.get())->nativeWindow;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,108 @@ OpenGLContext* OpenGLContext::getCurrentContext()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class OpenGLComponent::OpenGLCachedComponentImage : public CachedComponentImage,
|
||||
public Timer // N.B. using a Timer rather than an AsyncUpdater
|
||||
// to avoid scheduling problems on Windows
|
||||
{
|
||||
public:
|
||||
OpenGLCachedComponentImage (OpenGLComponent& owner_)
|
||||
: owner (owner_)
|
||||
{
|
||||
}
|
||||
|
||||
void paint (Graphics&)
|
||||
{
|
||||
ComponentPeer* const peer = owner.getPeer();
|
||||
|
||||
if (peer != nullptr)
|
||||
peer->addMaskedRegion (owner.getScreenBounds() - peer->getScreenPosition());
|
||||
|
||||
if (owner.isUsingDedicatedThread())
|
||||
{
|
||||
if (peer != nullptr && owner.isShowing())
|
||||
{
|
||||
#if ! JUCE_LINUX
|
||||
owner.updateContext();
|
||||
#endif
|
||||
|
||||
if (! owner.threadStarted)
|
||||
{
|
||||
owner.threadStarted = true;
|
||||
owner.startRenderThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.updateContext();
|
||||
|
||||
if (isTimerRunning())
|
||||
timerCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void invalidateAll()
|
||||
{
|
||||
validArea.clear();
|
||||
triggerRepaint();
|
||||
}
|
||||
|
||||
void invalidate (const Rectangle<int>& area)
|
||||
{
|
||||
validArea.subtract (area);
|
||||
triggerRepaint();
|
||||
}
|
||||
|
||||
void releaseResources()
|
||||
{
|
||||
frameBuffer.release();
|
||||
}
|
||||
|
||||
void timerCallback()
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
owner.performRender();
|
||||
owner.releaseAsRenderingTarget();
|
||||
}
|
||||
|
||||
void triggerRepaint()
|
||||
{
|
||||
owner.needToRepaint = true;
|
||||
|
||||
if (! owner.isUsingDedicatedThread())
|
||||
startTimer (1000 / 70);
|
||||
}
|
||||
|
||||
OpenGLFrameBuffer& getFrameBuffer (int width, int height)
|
||||
{
|
||||
const int fbW = frameBuffer.getWidth();
|
||||
const int fbH = frameBuffer.getHeight();
|
||||
|
||||
if (fbW < width
|
||||
|| fbH < height
|
||||
|| fbW > width + 128
|
||||
|| fbH > height + 128
|
||||
|| ! frameBuffer.isValid())
|
||||
{
|
||||
frameBuffer.initialise (width, height);
|
||||
validArea.clear();
|
||||
}
|
||||
|
||||
return frameBuffer;
|
||||
}
|
||||
|
||||
RectangleList validArea;
|
||||
|
||||
private:
|
||||
OpenGLComponent& owner;
|
||||
OpenGLFrameBuffer frameBuffer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLCachedComponentImage);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher
|
||||
{
|
||||
|
|
@ -174,11 +276,11 @@ public:
|
|||
{
|
||||
const uint32 startOfRendering = Time::getMillisecondCounter();
|
||||
|
||||
if (! owner.renderAndSwapBuffers())
|
||||
if (! owner.performRender())
|
||||
break;
|
||||
|
||||
const int elapsed = (int) (Time::getMillisecondCounter() - startOfRendering);
|
||||
Thread::sleep (jmax (1, 20 - elapsed));
|
||||
Thread::sleep (jmax (1, (1000 / 60) - elapsed));
|
||||
}
|
||||
|
||||
#if JUCE_LINUX
|
||||
|
|
@ -213,176 +315,18 @@ void OpenGLComponent::stopRenderThread()
|
|||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class OpenGLComponent::OpenGLCachedComponentImage : public CachedComponentImage,
|
||||
public Timer // N.B. using a Timer rather than an AsyncUpdater
|
||||
// to avoid scheduling problems on Windows
|
||||
{
|
||||
public:
|
||||
OpenGLCachedComponentImage (OpenGLComponent& owner_)
|
||||
: owner (owner_)
|
||||
{
|
||||
}
|
||||
|
||||
void paint (Graphics&)
|
||||
{
|
||||
ComponentPeer* const peer = owner.getPeer();
|
||||
|
||||
if (peer != nullptr)
|
||||
{
|
||||
const Point<int> topLeft (owner.getScreenPosition() - peer->getScreenPosition());
|
||||
peer->addMaskedRegion (topLeft.x, topLeft.y, owner.getWidth(), owner.getHeight());
|
||||
}
|
||||
|
||||
if (owner.isUsingDedicatedThread())
|
||||
{
|
||||
if (peer != nullptr && owner.isShowing())
|
||||
{
|
||||
#if ! JUCE_LINUX
|
||||
owner.updateContext();
|
||||
#endif
|
||||
|
||||
if (! owner.threadStarted)
|
||||
{
|
||||
owner.threadStarted = true;
|
||||
owner.startRenderThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.updateContext();
|
||||
|
||||
if (isTimerRunning())
|
||||
timerCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void invalidateAll()
|
||||
{
|
||||
validArea.clear();
|
||||
triggerRepaint();
|
||||
}
|
||||
|
||||
void invalidate (const Rectangle<int>& area)
|
||||
{
|
||||
validArea.subtract (area);
|
||||
triggerRepaint();
|
||||
}
|
||||
|
||||
void releaseResources()
|
||||
{
|
||||
frameBuffer.release();
|
||||
}
|
||||
|
||||
void timerCallback()
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
if (! owner.makeCurrentRenderingTarget())
|
||||
return;
|
||||
|
||||
const Rectangle<int> bounds (owner.getLocalBounds());
|
||||
|
||||
const int fbW = frameBuffer.getWidth();
|
||||
const int fbH = frameBuffer.getHeight();
|
||||
|
||||
if (fbW < bounds.getWidth()
|
||||
|| fbH < bounds.getHeight()
|
||||
|| fbW > bounds.getWidth() + 128
|
||||
|| fbH > bounds.getHeight() + 128
|
||||
|| ! frameBuffer.isValid())
|
||||
{
|
||||
frameBuffer.initialise (bounds.getWidth(), bounds.getHeight());
|
||||
validArea.clear();
|
||||
}
|
||||
|
||||
owner.renderOpenGL();
|
||||
|
||||
if ((owner.flags & allowSubComponents) != 0)
|
||||
{
|
||||
{
|
||||
RectangleList invalid (bounds);
|
||||
invalid.subtract (validArea);
|
||||
validArea = bounds;
|
||||
|
||||
if (! invalid.isEmpty())
|
||||
{
|
||||
OpenGLGraphicsContext g (frameBuffer);
|
||||
g.clipToRectangleList (invalid);
|
||||
|
||||
g.setFill (Colours::transparentBlack);
|
||||
g.fillRect (bounds, true);
|
||||
g.setFill (Colours::black);
|
||||
|
||||
paintOwner (g);
|
||||
}
|
||||
}
|
||||
|
||||
owner.makeCurrentRenderingTarget();
|
||||
OpenGLHelpers::prepareFor2D (bounds.getWidth(), bounds.getHeight());
|
||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable (GL_BLEND);
|
||||
glColor4f (1.0f, 1.0f, 1.0f, owner.getAlpha());
|
||||
frameBuffer.drawAt (0, (float) (bounds.getHeight() - frameBuffer.getHeight()));
|
||||
}
|
||||
|
||||
owner.swapBuffers();
|
||||
owner.releaseAsRenderingTarget();
|
||||
}
|
||||
|
||||
void triggerRepaint()
|
||||
{
|
||||
if (! owner.isUsingDedicatedThread())
|
||||
startTimer (1000 / 70);
|
||||
}
|
||||
|
||||
private:
|
||||
void paintOwner (OpenGLGraphicsContext& glRenderer)
|
||||
{
|
||||
Graphics g (&glRenderer);
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
OpenGLComponent& owner;
|
||||
OpenGLFrameBuffer frameBuffer;
|
||||
RectangleList validArea;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLCachedComponentImage);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
OpenGLComponent::OpenGLComponent (const int flags_)
|
||||
: flags (flags_),
|
||||
contextToShareListsWith (nullptr),
|
||||
needToUpdateViewport (true),
|
||||
needToDeleteContext (false),
|
||||
threadStarted (false)
|
||||
threadStarted (false),
|
||||
needToRepaint (true)
|
||||
{
|
||||
setOpaque (true);
|
||||
setCachedComponentImage (cachedImage = new OpenGLCachedComponentImage (*this));
|
||||
componentWatcher = new OpenGLComponentWatcher (*this);
|
||||
setCachedComponentImage (new OpenGLCachedComponentImage (*this));
|
||||
}
|
||||
|
||||
OpenGLComponent::~OpenGLComponent()
|
||||
|
|
@ -492,11 +436,8 @@ void OpenGLComponent::updateContextPosition()
|
|||
Component* const topComp = getTopLevelComponent();
|
||||
|
||||
if (topComp->getPeer() != nullptr)
|
||||
{
|
||||
const ScopedLock sl (contextLock);
|
||||
updateEmbeddedPosition (topComp->getLocalArea (this, getLocalBounds()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLComponent::stopBackgroundThread()
|
||||
|
|
@ -508,7 +449,24 @@ void OpenGLComponent::stopBackgroundThread()
|
|||
}
|
||||
}
|
||||
|
||||
bool OpenGLComponent::renderAndSwapBuffers()
|
||||
void OpenGLComponent::triggerRepaint()
|
||||
{
|
||||
// you mustn't set your own cached image object for an OpenGLComponent!
|
||||
jassert (dynamic_cast<OpenGLCachedComponentImage*> (getCachedComponentImage()) == cachedImage);
|
||||
|
||||
cachedImage->triggerRepaint();
|
||||
}
|
||||
|
||||
void OpenGLComponent::paint (Graphics&)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int OpenGLComponent::getFrameBufferID() const
|
||||
{
|
||||
return context != nullptr ? context->getFrameBufferID() : 0;
|
||||
}
|
||||
|
||||
bool OpenGLComponent::performRender()
|
||||
{
|
||||
const ScopedLock sl (contextLock);
|
||||
|
||||
|
|
@ -528,28 +486,80 @@ bool OpenGLComponent::renderAndSwapBuffers()
|
|||
}
|
||||
|
||||
renderOpenGL();
|
||||
|
||||
if (needToRepaint && (flags & allowSubComponents) != 0)
|
||||
{
|
||||
needToRepaint = false;
|
||||
|
||||
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());
|
||||
|
||||
{
|
||||
RectangleList invalid (bounds);
|
||||
invalid.subtract (cachedImage->validArea);
|
||||
cachedImage->validArea = bounds;
|
||||
|
||||
if (! invalid.isEmpty())
|
||||
{
|
||||
OpenGLGraphicsContext g (frameBuffer);
|
||||
g.clipToRectangleList (invalid);
|
||||
|
||||
g.setFill (Colours::transparentBlack);
|
||||
g.fillRect (bounds, true);
|
||||
g.setFill (Colours::black);
|
||||
|
||||
paintSelf (g);
|
||||
|
||||
makeCurrentRenderingTarget();
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLHelpers::prepareFor2D (bounds.getWidth(), bounds.getHeight());
|
||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable (GL_BLEND);
|
||||
glColor4f (1.0f, 1.0f, 1.0f, getAlpha());
|
||||
frameBuffer.drawAt (0, (float) (bounds.getHeight() - frameBuffer.getHeight()));
|
||||
}
|
||||
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLComponent::triggerRepaint()
|
||||
void OpenGLComponent::paintSelf (OpenGLGraphicsContext& glRenderer)
|
||||
{
|
||||
OpenGLCachedComponentImage* const c
|
||||
= dynamic_cast<OpenGLCachedComponentImage*> (getCachedComponentImage());
|
||||
Graphics g (&glRenderer);
|
||||
|
||||
jassert (c != nullptr); // you mustn't set your own cached image object for an OpenGLComponent!
|
||||
#if JUCE_ENABLE_REPAINT_DEBUGGING
|
||||
g.saveState();
|
||||
#endif
|
||||
|
||||
if (c != nullptr)
|
||||
c->triggerRepaint();
|
||||
}
|
||||
|
||||
void OpenGLComponent::paint (Graphics&)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int OpenGLComponent::getFrameBufferID() const
|
||||
{
|
||||
return context != nullptr ? context->getFrameBufferID() : 0;
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
typedef Component OpenGLBaseType;
|
||||
#endif
|
||||
|
||||
class OpenGLGraphicsContext;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A component that contains an OpenGL canvas.
|
||||
|
|
@ -202,12 +204,6 @@ public:
|
|||
void triggerRepaint();
|
||||
|
||||
//==============================================================================
|
||||
/** Calls the rendering callback, and swaps the buffers afterwards.
|
||||
This is called automatically by paint() when the component needs to be rendered.
|
||||
Returns true if the operation succeeded.
|
||||
*/
|
||||
virtual bool renderAndSwapBuffers();
|
||||
|
||||
/** 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
|
||||
|
|
@ -269,10 +265,11 @@ private:
|
|||
|
||||
CriticalSection contextLock;
|
||||
OpenGLPixelFormat preferredPixelFormat;
|
||||
bool needToUpdateViewport, needToDeleteContext, threadStarted;
|
||||
bool needToUpdateViewport, needToDeleteContext, threadStarted, needToRepaint;
|
||||
|
||||
class OpenGLCachedComponentImage;
|
||||
friend class OpenGLCachedComponentImage;
|
||||
OpenGLCachedComponentImage* cachedImage;
|
||||
|
||||
OpenGLContext* createContext();
|
||||
void updateContext();
|
||||
|
|
@ -280,6 +277,10 @@ private:
|
|||
void stopBackgroundThread();
|
||||
void recreateContextAsync();
|
||||
void updateEmbeddedPosition (const Rectangle<int>&);
|
||||
bool performRender();
|
||||
void paintSelf (OpenGLGraphicsContext&);
|
||||
|
||||
int renderAndSwapBuffers(); // (This method has been deprecated)
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -809,10 +809,7 @@ void DirectShowComponent::paint (Graphics& g)
|
|||
ComponentPeer* const peer = getPeer();
|
||||
|
||||
if (peer != nullptr)
|
||||
{
|
||||
const Point<int> topLeft (getScreenPosition() - peer->getScreenPosition());
|
||||
peer->addMaskedRegion (topLeft.getX(), topLeft.getY(), getWidth(), getHeight());
|
||||
}
|
||||
peer->addMaskedRegion (getScreenBounds() - peer->getScreenPosition());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue