rhi: gl: Pick up context loss

...and change the return value of makeThreadLocalNativeContextCurrent() to
a bool since we expect this to mirror QOpenGLContext::makeCurrent().

Change-Id: I339507152e461fe28fcf7fe777165e6d0072f055
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
This commit is contained in:
Laszlo Agocs 2019-09-12 16:09:36 +02:00
parent af1c3bf884
commit 39b0a6f152
13 changed files with 76 additions and 31 deletions

View File

@ -468,7 +468,7 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\value FrameOpDeviceLost The graphics device was lost. This can be
recoverable by attempting to repeat the operation (such as, beginFrame())
after releasing and reinitializing all objects backed by native graphics
resources.
resources. See isDeviceLost().
*/
/*!
@ -5022,10 +5022,17 @@ const QRhiNativeHandles *QRhi::nativeHandles()
has to ensure external OpenGL code provided by the application can still
run like it did before with direct usage of OpenGL, as long as the QRhi is
using the OpenGL backend.
\return false when failed, similarly to QOpenGLContext::makeCurrent(). When
the operation failed, isDeviceLost() can be called to determine if there
was a loss of context situation. Such a check is equivalent to checking via
QOpenGLContext::isValid().
\sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
*/
void QRhi::makeThreadLocalNativeContextCurrent()
bool QRhi::makeThreadLocalNativeContextCurrent()
{
d->makeThreadLocalNativeContextCurrent();
return d->makeThreadLocalNativeContextCurrent();
}
/*!
@ -5092,6 +5099,12 @@ void QRhi::releaseCachedResources()
reinitialized then. However, applications and libraries working directly
with QRhi are expected to be prepared to check and handle device loss
situations themselves.
\note With OpenGL, applications may need to opt-in to context reset
notifications by setting QSurfaceFormat::ResetNotification on the
QOpenGLContext. This is typically done by enabling the flag in
QRhiGles2InitParams::format. Keep in mind however that some systems may
generate context resets situations even when this flag is not set.
*/
bool QRhi::isDeviceLost() const
{
@ -5259,7 +5272,17 @@ QRhiSwapChain *QRhi::newSwapChain()
\endlist
\sa endFrame(), beginOffscreenFrame()
\return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
value on failure. Some of these should be treated as soft, "try again
later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
the swapchain is to be resized or updated by calling
QRhiSwapChain::buildOrResize(). The application should then attempt to
generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
lost but this may also be recoverable by releasing all resources, including
the QRhi itself, and then recreating all resources. See isDeviceLost() for
further discussion.
\sa endFrame(), beginOffscreenFrame(), isDeviceLost()
*/
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
{
@ -5284,7 +5307,17 @@ QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags f
Passing QRhi::SkipPresent skips queuing the Present command or calling
swapBuffers.
\sa beginFrame()
\return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
value on failure. Some of these should be treated as soft, "try again
later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
the swapchain is to be resized or updated by calling
QRhiSwapChain::buildOrResize(). The application should then attempt to
generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
lost but this may also be recoverable by releasing all resources, including
the QRhi itself, and then recreating all resources. See isDeviceLost() for
further discussion.
\sa beginFrame(), isDeviceLost()
*/
QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
{

View File

@ -1414,7 +1414,7 @@ public:
int resourceLimit(ResourceLimit limit) const;
const QRhiNativeHandles *nativeHandles();
void makeThreadLocalNativeContextCurrent();
bool makeThreadLocalNativeContextCurrent();
QRhiProfiler *profiler();

View File

@ -156,7 +156,7 @@ public:
virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
virtual const QRhiNativeHandles *nativeHandles() = 0;
virtual void sendVMemStatsToProfiler() = 0;
virtual void makeThreadLocalNativeContextCurrent() = 0;
virtual bool makeThreadLocalNativeContextCurrent() = 0;
virtual void releaseCachedResources() = 0;
virtual bool isDeviceLost() const = 0;

View File

@ -502,9 +502,10 @@ void QRhiD3D11::sendVMemStatsToProfiler()
// nothing to do here
}
void QRhiD3D11::makeThreadLocalNativeContextCurrent()
bool QRhiD3D11::makeThreadLocalNativeContextCurrent()
{
// nothing to do here
// not applicable
return false;
}
void QRhiD3D11::releaseCachedResources()

View File

@ -631,7 +631,7 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
void makeThreadLocalNativeContextCurrent() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
bool isDeviceLost() const override;

View File

@ -371,7 +371,12 @@ bool QRhiGles2::ensureContext(QSurface *surface) const
return true;
if (!ctx->makeCurrent(surface)) {
qWarning("QRhiGles2: Failed to make context current. Expect bad things to happen.");
if (ctx->isValid()) {
qWarning("QRhiGles2: Failed to make context current. Expect bad things to happen.");
} else {
qWarning("QRhiGles2: Context is lost.");
contextLost = true;
}
return false;
}
@ -491,6 +496,8 @@ bool QRhiGles2::create(QRhi::Flags flags)
nativeHandlesStruct.context = ctx;
contextLost = false;
return true;
}
@ -753,12 +760,12 @@ void QRhiGles2::sendVMemStatsToProfiler()
// nothing to do here
}
void QRhiGles2::makeThreadLocalNativeContextCurrent()
bool QRhiGles2::makeThreadLocalNativeContextCurrent()
{
if (inFrame && !ofr.active)
ensureContext(currentSwapChain->surface);
return ensureContext(currentSwapChain->surface);
else
ensureContext();
return ensureContext();
}
void QRhiGles2::releaseCachedResources()
@ -774,7 +781,7 @@ void QRhiGles2::releaseCachedResources()
bool QRhiGles2::isDeviceLost() const
{
return false;
return contextLost;
}
QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@ -1161,7 +1168,7 @@ QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
if (!ensureContext(swapChainD->surface))
return QRhi::FrameOpError;
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
currentSwapChain = swapChainD;
@ -1184,7 +1191,7 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::EndFrame);
if (!ensureContext(swapChainD->surface))
return QRhi::FrameOpError;
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&swapChainD->cb);
@ -1208,7 +1215,7 @@ QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
{
Q_UNUSED(flags);
if (!ensureContext())
return QRhi::FrameOpError;
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
ofr.active = true;
@ -1230,7 +1237,7 @@ QRhi::FrameOpResult QRhiGles2::endOffscreenFrame(QRhi::EndFrameFlags flags)
addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::EndFrame);
if (!ensureContext())
return QRhi::FrameOpError;
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&ofr.cbWrapper);
@ -1244,14 +1251,14 @@ QRhi::FrameOpResult QRhiGles2::finish()
Q_ASSERT(!currentSwapChain);
Q_ASSERT(ofr.cbWrapper.recordingPass == QGles2CommandBuffer::NoPass);
if (!ensureContext())
return QRhi::FrameOpError;
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&ofr.cbWrapper);
ofr.cbWrapper.resetCommands();
} else {
Q_ASSERT(currentSwapChain);
Q_ASSERT(currentSwapChain->cb.recordingPass == QGles2CommandBuffer::NoPass);
if (!ensureContext(currentSwapChain->surface))
return QRhi::FrameOpError;
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&currentSwapChain->cb);
currentSwapChain->cb.resetCommands();
}

View File

@ -664,7 +664,7 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
void makeThreadLocalNativeContextCurrent() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
bool isDeviceLost() const override;
@ -770,6 +770,7 @@ public:
QVector<GLint> supportedCompressedFormats;
mutable QVector<int> supportedSampleCountList;
QRhiGles2NativeHandles nativeHandlesStruct;
mutable bool contextLost = false;
struct DeferredReleaseEntry {
enum Type {

View File

@ -583,9 +583,10 @@ void QRhiMetal::sendVMemStatsToProfiler()
// nothing to do here
}
void QRhiMetal::makeThreadLocalNativeContextCurrent()
bool QRhiMetal::makeThreadLocalNativeContextCurrent()
{
// nothing to do here
// not applicable
return false;
}
void QRhiMetal::releaseCachedResources()

View File

@ -416,7 +416,7 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
void makeThreadLocalNativeContextCurrent() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
bool isDeviceLost() const override;

View File

@ -169,9 +169,10 @@ void QRhiNull::sendVMemStatsToProfiler()
// nothing to do here
}
void QRhiNull::makeThreadLocalNativeContextCurrent()
bool QRhiNull::makeThreadLocalNativeContextCurrent()
{
// nothing to do here
// not applicable
return false;
}
void QRhiNull::releaseCachedResources()

View File

@ -282,7 +282,7 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
void makeThreadLocalNativeContextCurrent() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
bool isDeviceLost() const override;

View File

@ -3767,9 +3767,10 @@ void QRhiVulkan::sendVMemStatsToProfiler()
quint32(stats.total.usedBytes), quint32(stats.total.unusedBytes)));
}
void QRhiVulkan::makeThreadLocalNativeContextCurrent()
bool QRhiVulkan::makeThreadLocalNativeContextCurrent()
{
// nothing to do here
// not applicable
return false;
}
void QRhiVulkan::releaseCachedResources()

View File

@ -711,7 +711,7 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
void makeThreadLocalNativeContextCurrent() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
bool isDeviceLost() const override;