mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 980178 - Clean up context loss handling code. - r=kamidphish
This commit is contained in:
parent
f4fa67e2d0
commit
5a68eb9ec0
@ -83,18 +83,21 @@ WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
|
|||||||
|
|
||||||
if (!mContext->mCanLoseContextInForeground &&
|
if (!mContext->mCanLoseContextInForeground &&
|
||||||
ProcessPriorityManager::CurrentProcessIsForeground())
|
ProcessPriorityManager::CurrentProcessIsForeground())
|
||||||
|
{
|
||||||
wantToLoseContext = false;
|
wantToLoseContext = false;
|
||||||
else if (!nsCRT::strcmp(aSomeData,
|
} else if (!nsCRT::strcmp(aSomeData,
|
||||||
MOZ_UTF16("heap-minimize")))
|
MOZ_UTF16("heap-minimize")))
|
||||||
|
{
|
||||||
wantToLoseContext = mContext->mLoseContextOnHeapMinimize;
|
wantToLoseContext = mContext->mLoseContextOnHeapMinimize;
|
||||||
|
}
|
||||||
|
|
||||||
if (wantToLoseContext)
|
if (wantToLoseContext) {
|
||||||
mContext->ForceLoseContext();
|
mContext->ForceLoseContext();
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WebGLContextOptions::WebGLContextOptions()
|
WebGLContextOptions::WebGLContextOptions()
|
||||||
: alpha(true), depth(true), stencil(false),
|
: alpha(true), depth(true), stencil(false),
|
||||||
premultipliedAlpha(true), antialias(true),
|
premultipliedAlpha(true), antialias(true),
|
||||||
@ -168,12 +171,12 @@ WebGLContext::WebGLContext()
|
|||||||
|
|
||||||
WebGLMemoryTracker::AddWebGLContext(this);
|
WebGLMemoryTracker::AddWebGLContext(this);
|
||||||
|
|
||||||
mAllowRestore = true;
|
mAllowContextRestore = true;
|
||||||
|
mLastLossWasSimulated = false;
|
||||||
mContextLossTimerRunning = false;
|
mContextLossTimerRunning = false;
|
||||||
mDrawSinceContextLossTimerSet = false;
|
mRunContextLossTimerAgain = false;
|
||||||
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
|
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
|
||||||
mContextStatus = ContextNotLost;
|
mContextStatus = ContextNotLost;
|
||||||
mContextLostErrorSet = false;
|
|
||||||
mLoseContextOnHeapMinimize = false;
|
mLoseContextOnHeapMinimize = false;
|
||||||
mCanLoseContextInForeground = true;
|
mCanLoseContextInForeground = true;
|
||||||
|
|
||||||
@ -571,11 +574,8 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
|||||||
mResetLayer = true;
|
mResetLayer = true;
|
||||||
mOptionsFrozen = true;
|
mOptionsFrozen = true;
|
||||||
|
|
||||||
mHasRobustness = gl->HasRobustness();
|
|
||||||
|
|
||||||
// increment the generation number
|
// increment the generation number
|
||||||
++mGeneration;
|
++mGeneration;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (mGeneration > 0) {
|
if (mGeneration > 0) {
|
||||||
// XXX dispatch context lost event
|
// XXX dispatch context lost event
|
||||||
@ -1110,6 +1110,96 @@ WebGLContext::DummyFramebufferOperation(const char *info)
|
|||||||
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckContextLost(GLContext* gl, bool* out_isGuilty)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(gl);
|
||||||
|
MOZ_ASSERT(out_isGuilty);
|
||||||
|
|
||||||
|
bool isEGL = gl->GetContextType() == gl::GLContextType::EGL;
|
||||||
|
|
||||||
|
GLenum resetStatus = LOCAL_GL_NO_ERROR;
|
||||||
|
if (gl->HasRobustness()) {
|
||||||
|
gl->MakeCurrent();
|
||||||
|
resetStatus = gl->fGetGraphicsResetStatus();
|
||||||
|
} else if (isEGL) {
|
||||||
|
// Simulate a ARB_robustness guilty context loss for when we
|
||||||
|
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
|
||||||
|
// but we can't make any distinction.
|
||||||
|
if (!gl->MakeCurrent(true) && gl->IsContextLost()) {
|
||||||
|
resetStatus = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resetStatus == LOCAL_GL_NO_ERROR) {
|
||||||
|
*out_isGuilty = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume guilty unless we find otherwise!
|
||||||
|
bool isGuilty = true;
|
||||||
|
switch (resetStatus) {
|
||||||
|
case LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB:
|
||||||
|
// Either nothing wrong, or not our fault.
|
||||||
|
isGuilty = false;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_GUILTY_CONTEXT_RESET_ARB:
|
||||||
|
NS_WARNING("WebGL content on the page definitely caused the graphics"
|
||||||
|
" card to reset.");
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB:
|
||||||
|
NS_WARNING("WebGL content on the page might have caused the graphics"
|
||||||
|
" card to reset");
|
||||||
|
// If we can't tell, assume guilty.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT(false, "Unreachable.");
|
||||||
|
// If we do get here, let's pretend to be guilty as an escape plan.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGuilty) {
|
||||||
|
NS_WARNING("WebGL context on this page is considered guilty, and will"
|
||||||
|
" not be restored.");
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_isGuilty = isGuilty;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WebGLContext::TryToRestoreContext()
|
||||||
|
{
|
||||||
|
if (NS_FAILED(SetDimensions(mWidth, mHeight)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateContextLossStatusTask : public nsRunnable
|
||||||
|
{
|
||||||
|
WebGLContext* const mContext;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UpdateContextLossStatusTask(WebGLContext* context)
|
||||||
|
: mContext(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
mContext->UpdateContextLossStatus();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
WebGLContext::EnqueueUpdateContextLossStatus()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIRunnable> task = new UpdateContextLossStatusTask(this);
|
||||||
|
NS_DispatchToCurrentThread(task);
|
||||||
|
}
|
||||||
|
|
||||||
// We use this timer for many things. Here are the things that it is activated for:
|
// We use this timer for many things. Here are the things that it is activated for:
|
||||||
// 1) If a script is using the MOZ_WEBGL_lose_context extension.
|
// 1) If a script is using the MOZ_WEBGL_lose_context extension.
|
||||||
// 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
|
// 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
|
||||||
@ -1125,137 +1215,123 @@ WebGLContext::DummyFramebufferOperation(const char *info)
|
|||||||
// At a bare minimum, from context lost to context restores, it would take 3
|
// At a bare minimum, from context lost to context restores, it would take 3
|
||||||
// full timer iterations: detection, webglcontextlost, webglcontextrestored.
|
// full timer iterations: detection, webglcontextlost, webglcontextrestored.
|
||||||
void
|
void
|
||||||
WebGLContext::RobustnessTimerCallback(nsITimer* timer)
|
WebGLContext::UpdateContextLossStatus()
|
||||||
{
|
{
|
||||||
TerminateContextLossTimer();
|
|
||||||
|
|
||||||
if (!mCanvasElement) {
|
if (!mCanvasElement) {
|
||||||
// the canvas is gone. That happens when the page was closed before we got
|
// the canvas is gone. That happens when the page was closed before we got
|
||||||
// this timer event. In this case, there's nothing to do here, just don't crash.
|
// this timer event. In this case, there's nothing to do here, just don't crash.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mContextStatus == ContextNotLost) {
|
||||||
|
// We don't know that we're lost, but we might be, so we need to
|
||||||
|
// check. If we're guilty, don't allow restores, though.
|
||||||
|
|
||||||
|
bool isGuilty = true;
|
||||||
|
bool isContextLost = CheckContextLost(gl, &isGuilty);
|
||||||
|
|
||||||
|
if (isContextLost) {
|
||||||
|
if (isGuilty)
|
||||||
|
mAllowContextRestore = false;
|
||||||
|
|
||||||
|
ForceLoseContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall through.
|
||||||
|
}
|
||||||
|
|
||||||
// If the context has been lost and we're waiting for it to be restored, do
|
|
||||||
// that now.
|
|
||||||
if (mContextStatus == ContextLostAwaitingEvent) {
|
if (mContextStatus == ContextLostAwaitingEvent) {
|
||||||
bool defaultAction;
|
// The context has been lost and we haven't yet triggered the
|
||||||
|
// callback, so do that now.
|
||||||
|
|
||||||
|
bool useDefaultHandler;
|
||||||
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
||||||
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
|
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
|
||||||
NS_LITERAL_STRING("webglcontextlost"),
|
NS_LITERAL_STRING("webglcontextlost"),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
&defaultAction);
|
&useDefaultHandler);
|
||||||
|
// We sent the callback, so we're just 'regular lost' now.
|
||||||
|
mContextStatus = ContextLost;
|
||||||
|
// If we're told to use the default handler, it means the script
|
||||||
|
// didn't bother to handle the event. In this case, we shouldn't
|
||||||
|
// auto-restore the context.
|
||||||
|
if (useDefaultHandler)
|
||||||
|
mAllowContextRestore = false;
|
||||||
|
|
||||||
// If the script didn't handle the event, we don't allow restores.
|
// Fall through.
|
||||||
if (defaultAction)
|
}
|
||||||
mAllowRestore = false;
|
|
||||||
|
|
||||||
// If the script handled the event and we are allowing restores, then
|
if (mContextStatus == ContextLost) {
|
||||||
// mark it to be restored. Otherwise, leave it as context lost
|
// Context is lost, and we've already sent the callback. We
|
||||||
// (unusable).
|
// should try to restore the context if we're both allowed to,
|
||||||
if (!defaultAction && mAllowRestore) {
|
// and supposed to.
|
||||||
ForceRestoreContext();
|
|
||||||
// Restart the timer so that it will be restored on the next
|
// Are we allowed to restore the context?
|
||||||
// callback.
|
if (!mAllowContextRestore)
|
||||||
SetupContextLossTimer();
|
return;
|
||||||
} else {
|
|
||||||
|
// If we're only simulated-lost, we shouldn't auto-restore, and
|
||||||
|
// instead we should wait for restoreContext() to be called.
|
||||||
|
if (mLastLossWasSimulated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ForceRestoreContext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mContextStatus == ContextLostAwaitingRestore) {
|
||||||
|
// Context is lost, but we should try to restore it.
|
||||||
|
|
||||||
|
if (!mAllowContextRestore) {
|
||||||
|
// We might decide this after thinking we'd be OK restoring
|
||||||
|
// the context, so downgrade.
|
||||||
mContextStatus = ContextLost;
|
mContextStatus = ContextLost;
|
||||||
}
|
|
||||||
} else if (mContextStatus == ContextLostAwaitingRestore) {
|
|
||||||
// Try to restore the context. If it fails, try again later.
|
|
||||||
if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
|
|
||||||
SetupContextLossTimer();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!TryToRestoreContext()) {
|
||||||
|
// Failed to restore. Try again later.
|
||||||
|
RunContextLossTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revival!
|
||||||
mContextStatus = ContextNotLost;
|
mContextStatus = ContextNotLost;
|
||||||
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
||||||
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
|
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
|
||||||
NS_LITERAL_STRING("webglcontextrestored"),
|
NS_LITERAL_STRING("webglcontextrestored"),
|
||||||
true,
|
true,
|
||||||
true);
|
true);
|
||||||
// Set all flags back to the state they were in before the context was
|
|
||||||
// lost.
|
|
||||||
mEmitContextLostErrorOnce = true;
|
mEmitContextLostErrorOnce = true;
|
||||||
mAllowRestore = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeRestoreContext();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
WebGLContext::MaybeRestoreContext()
|
|
||||||
{
|
|
||||||
// Don't try to handle it if we already know it's busted.
|
|
||||||
if (mContextStatus != ContextNotLost || gl == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool isEGL = gl->GetContextType() == gl::GLContextType::EGL,
|
|
||||||
isANGLE = gl->IsANGLE();
|
|
||||||
|
|
||||||
GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
|
|
||||||
if (mHasRobustness) {
|
|
||||||
gl->MakeCurrent();
|
|
||||||
resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
|
|
||||||
} else if (isEGL) {
|
|
||||||
// Simulate a ARB_robustness guilty context loss for when we
|
|
||||||
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
|
|
||||||
// but we can't make any distinction, so we must assume the worst
|
|
||||||
// case.
|
|
||||||
if (!gl->MakeCurrent(true) && gl->IsContextLost()) {
|
|
||||||
resetStatus = GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
|
|
||||||
// It's already lost, but clean up after it and signal to JS that it is
|
|
||||||
// lost.
|
|
||||||
ForceLoseContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (resetStatus) {
|
|
||||||
case GLContext::CONTEXT_NO_ERROR:
|
|
||||||
// If there has been activity since the timer was set, it's possible
|
|
||||||
// that we did or are going to miss something, so clear this flag and
|
|
||||||
// run it again some time later.
|
|
||||||
if (mDrawSinceContextLossTimerSet)
|
|
||||||
SetupContextLossTimer();
|
|
||||||
break;
|
|
||||||
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
|
|
||||||
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
|
|
||||||
mAllowRestore = false;
|
|
||||||
break;
|
|
||||||
case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
|
|
||||||
break;
|
|
||||||
case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
|
|
||||||
NS_WARNING("WebGL content on the page might have caused the graphics card to reset");
|
|
||||||
if (isEGL && isANGLE) {
|
|
||||||
// If we're using ANGLE, we ONLY get back UNKNOWN context resets, including for guilty contexts.
|
|
||||||
// This means that we can't restore it or risk restoring a guilty context. Should this ever change,
|
|
||||||
// we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the
|
|
||||||
// only use for it. See ANGLE issue 261.
|
|
||||||
mAllowRestore = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGLContext::ForceLoseContext()
|
WebGLContext::ForceLoseContext()
|
||||||
{
|
{
|
||||||
if (mContextStatus == ContextLostAwaitingEvent)
|
printf_stderr("WebGL(%p)::ForceLoseContext\n", this);
|
||||||
return;
|
MOZ_ASSERT(!IsContextLost());
|
||||||
|
|
||||||
mContextStatus = ContextLostAwaitingEvent;
|
mContextStatus = ContextLostAwaitingEvent;
|
||||||
// Queue up a task to restore the event.
|
mContextLostErrorSet = false;
|
||||||
SetupContextLossTimer();
|
mLastLossWasSimulated = false;
|
||||||
|
|
||||||
|
// Burn it all!
|
||||||
DestroyResourcesAndContext();
|
DestroyResourcesAndContext();
|
||||||
|
|
||||||
|
// Queue up a task, since we know the status changed.
|
||||||
|
EnqueueUpdateContextLossStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGLContext::ForceRestoreContext()
|
WebGLContext::ForceRestoreContext()
|
||||||
{
|
{
|
||||||
|
printf_stderr("WebGL(%p)::ForceRestoreContext\n", this);
|
||||||
mContextStatus = ContextLostAwaitingRestore;
|
mContextStatus = ContextLostAwaitingRestore;
|
||||||
|
mAllowContextRestore = true; // Hey, you did say 'force'.
|
||||||
|
|
||||||
|
// Queue up a task, since we know the status changed.
|
||||||
|
EnqueueUpdateContextLossStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -202,9 +202,6 @@ public:
|
|||||||
int32_t x, int32_t y, int32_t w, int32_t h)
|
int32_t x, int32_t y, int32_t w, int32_t h)
|
||||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
|
||||||
bool LoseContext();
|
|
||||||
bool RestoreContext();
|
|
||||||
|
|
||||||
void SynthesizeGLError(GLenum err);
|
void SynthesizeGLError(GLenum err);
|
||||||
void SynthesizeGLError(GLenum err, const char *fmt, ...);
|
void SynthesizeGLError(GLenum err, const char *fmt, ...);
|
||||||
|
|
||||||
@ -261,11 +258,14 @@ public:
|
|||||||
|
|
||||||
bool MinCapabilityMode() const { return mMinCapability; }
|
bool MinCapabilityMode() const { return mMinCapability; }
|
||||||
|
|
||||||
void RobustnessTimerCallback(nsITimer* timer);
|
void UpdateContextLossStatus();
|
||||||
static void RobustnessTimerCallbackStatic(nsITimer* timer, void *thisPointer);
|
void EnqueueUpdateContextLossStatus();
|
||||||
void SetupContextLossTimer();
|
static void ContextLossCallbackStatic(nsITimer* timer, void* thisPointer);
|
||||||
|
void RunContextLossTimer();
|
||||||
void TerminateContextLossTimer();
|
void TerminateContextLossTimer();
|
||||||
|
|
||||||
|
bool TryToRestoreContext();
|
||||||
|
|
||||||
void AssertCachedBindings();
|
void AssertCachedBindings();
|
||||||
void AssertCachedState();
|
void AssertCachedState();
|
||||||
|
|
||||||
@ -666,8 +666,12 @@ public:
|
|||||||
bool ValidateSamplerUniformSetter(const char* info,
|
bool ValidateSamplerUniformSetter(const char* info,
|
||||||
WebGLUniformLocation *location,
|
WebGLUniformLocation *location,
|
||||||
GLint value);
|
GLint value);
|
||||||
|
|
||||||
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// WEBGL_lose_context
|
||||||
|
public:
|
||||||
|
void LoseContext();
|
||||||
|
void RestoreContext();
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Asynchronous Queries (WebGLContextAsyncQueries.cpp)
|
// Asynchronous Queries (WebGLContextAsyncQueries.cpp)
|
||||||
@ -869,7 +873,6 @@ protected:
|
|||||||
bool mOptionsFrozen;
|
bool mOptionsFrozen;
|
||||||
bool mMinCapability;
|
bool mMinCapability;
|
||||||
bool mDisableExtensions;
|
bool mDisableExtensions;
|
||||||
bool mHasRobustness;
|
|
||||||
bool mIsMesa;
|
bool mIsMesa;
|
||||||
bool mLoseContextOnHeapMinimize;
|
bool mLoseContextOnHeapMinimize;
|
||||||
bool mCanLoseContextInForeground;
|
bool mCanLoseContextInForeground;
|
||||||
@ -1116,7 +1119,6 @@ protected:
|
|||||||
GLenum type,
|
GLenum type,
|
||||||
const GLvoid *data);
|
const GLvoid *data);
|
||||||
|
|
||||||
void MaybeRestoreContext();
|
|
||||||
void ForceLoseContext();
|
void ForceLoseContext();
|
||||||
void ForceRestoreContext();
|
void ForceRestoreContext();
|
||||||
|
|
||||||
@ -1178,7 +1180,7 @@ protected:
|
|||||||
|
|
||||||
GLint mStencilRefFront, mStencilRefBack;
|
GLint mStencilRefFront, mStencilRefBack;
|
||||||
GLuint mStencilValueMaskFront, mStencilValueMaskBack,
|
GLuint mStencilValueMaskFront, mStencilValueMaskBack,
|
||||||
mStencilWriteMaskFront, mStencilWriteMaskBack;
|
mStencilWriteMaskFront, mStencilWriteMaskBack;
|
||||||
realGLboolean mColorWriteMask[4];
|
realGLboolean mColorWriteMask[4];
|
||||||
realGLboolean mDepthWriteMask;
|
realGLboolean mDepthWriteMask;
|
||||||
GLfloat mColorClearValue[4];
|
GLfloat mColorClearValue[4];
|
||||||
@ -1192,9 +1194,10 @@ protected:
|
|||||||
bool mAlreadyWarnedAboutViewportLargerThanDest;
|
bool mAlreadyWarnedAboutViewportLargerThanDest;
|
||||||
|
|
||||||
nsCOMPtr<nsITimer> mContextRestorer;
|
nsCOMPtr<nsITimer> mContextRestorer;
|
||||||
bool mAllowRestore;
|
bool mAllowContextRestore;
|
||||||
|
bool mLastLossWasSimulated;
|
||||||
bool mContextLossTimerRunning;
|
bool mContextLossTimerRunning;
|
||||||
bool mDrawSinceContextLossTimerSet;
|
bool mRunContextLossTimerAgain;
|
||||||
ContextStatus mContextStatus;
|
ContextStatus mContextStatus;
|
||||||
bool mContextLostErrorSet;
|
bool mContextLostErrorSet;
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
|
|||||||
if (!DrawArrays_check(first, count, 1, "drawArrays"))
|
if (!DrawArrays_check(first, count, 1, "drawArrays"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SetupContextLossTimer();
|
RunContextLossTimer();
|
||||||
gl->fDrawArrays(mode, first, count);
|
gl->fDrawArrays(mode, first, count);
|
||||||
|
|
||||||
Draw_cleanup();
|
Draw_cleanup();
|
||||||
@ -149,7 +149,7 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
|
|||||||
if (!DrawInstanced_check("drawArraysInstanced"))
|
if (!DrawInstanced_check("drawArraysInstanced"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SetupContextLossTimer();
|
RunContextLossTimer();
|
||||||
gl->fDrawArraysInstanced(mode, first, count, primcount);
|
gl->fDrawArraysInstanced(mode, first, count, primcount);
|
||||||
|
|
||||||
Draw_cleanup();
|
Draw_cleanup();
|
||||||
@ -296,7 +296,7 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupContextLossTimer();
|
RunContextLossTimer();
|
||||||
|
|
||||||
if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
|
if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
|
||||||
gl->fDrawRangeElements(mode, 0, upperBound,
|
gl->fDrawRangeElements(mode, 0, upperBound,
|
||||||
@ -324,7 +324,7 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
|||||||
if (!DrawInstanced_check("drawElementsInstanced"))
|
if (!DrawInstanced_check("drawElementsInstanced"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SetupContextLossTimer();
|
RunContextLossTimer();
|
||||||
gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount);
|
gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount);
|
||||||
|
|
||||||
Draw_cleanup();
|
Draw_cleanup();
|
||||||
|
@ -3857,27 +3857,34 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
|
|||||||
WebGLTexelFormat::RGBA8, false);
|
WebGLTexelFormat::RGBA8, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
WebGLContext::LoseContext()
|
WebGLContext::LoseContext()
|
||||||
{
|
{
|
||||||
if (IsContextLost())
|
if (IsContextLost())
|
||||||
return false;
|
return ErrorInvalidOperation("loseContext: Context is already lost.");
|
||||||
|
|
||||||
ForceLoseContext();
|
ForceLoseContext();
|
||||||
|
mLastLossWasSimulated = true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
WebGLContext::RestoreContext()
|
WebGLContext::RestoreContext()
|
||||||
{
|
{
|
||||||
if (!IsContextLost() || !mAllowRestore) {
|
if (!IsContextLost())
|
||||||
return false;
|
return ErrorInvalidOperation("restoreContext: Context is not lost.");
|
||||||
|
|
||||||
|
if (!mLastLossWasSimulated) {
|
||||||
|
return ErrorInvalidOperation("restoreContext: Context loss was not simulated."
|
||||||
|
" Cannot simulate restore.");
|
||||||
}
|
}
|
||||||
|
// If we're currently lost, and the last loss was simulated, then
|
||||||
|
// we're currently only simulated-lost, allowing us to call
|
||||||
|
// restoreContext().
|
||||||
|
|
||||||
|
if (!mAllowContextRestore)
|
||||||
|
return ErrorInvalidOperation("restoreContext: Context cannot be restored.");
|
||||||
|
|
||||||
ForceRestoreContext();
|
ForceRestoreContext();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -8,33 +8,45 @@
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
WebGLContext::RobustnessTimerCallbackStatic(nsITimer* timer, void *thisPointer) {
|
WebGLContext::ContextLossCallbackStatic(nsITimer* timer, void* thisPointer)
|
||||||
static_cast<WebGLContext*>(thisPointer)->RobustnessTimerCallback(timer);
|
{
|
||||||
|
(void)timer;
|
||||||
|
WebGLContext* context = static_cast<WebGLContext*>(thisPointer);
|
||||||
|
|
||||||
|
context->TerminateContextLossTimer();
|
||||||
|
|
||||||
|
context->UpdateContextLossStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGLContext::SetupContextLossTimer() {
|
WebGLContext::RunContextLossTimer()
|
||||||
|
{
|
||||||
// If the timer was already running, don't restart it here. Instead,
|
// If the timer was already running, don't restart it here. Instead,
|
||||||
// wait until the previous call is done, then fire it one more time.
|
// wait until the previous call is done, then fire it one more time.
|
||||||
// This is an optimization to prevent unnecessary cross-communication
|
// This is an optimization to prevent unnecessary
|
||||||
// between threads.
|
// cross-communication between threads.
|
||||||
if (mContextLossTimerRunning) {
|
if (mContextLossTimerRunning) {
|
||||||
mDrawSinceContextLossTimerSet = true;
|
mRunContextLossTimerAgain = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mContextRestorer->InitWithFuncCallback(ContextLossCallbackStatic,
|
||||||
mContextRestorer->InitWithFuncCallback(RobustnessTimerCallbackStatic,
|
static_cast<void*>(this),
|
||||||
static_cast<void*>(this),
|
1000,
|
||||||
1000,
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
nsITimer::TYPE_ONE_SHOT);
|
|
||||||
mContextLossTimerRunning = true;
|
mContextLossTimerRunning = true;
|
||||||
mDrawSinceContextLossTimerSet = false;
|
mRunContextLossTimerAgain = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGLContext::TerminateContextLossTimer() {
|
WebGLContext::TerminateContextLossTimer()
|
||||||
if (mContextLossTimerRunning) {
|
{
|
||||||
mContextRestorer->Cancel();
|
if (!mContextLossTimerRunning)
|
||||||
mContextLossTimerRunning = false;
|
return;
|
||||||
|
|
||||||
|
mContextRestorer->Cancel();
|
||||||
|
mContextLossTimerRunning = false;
|
||||||
|
|
||||||
|
if (mRunContextLossTimerAgain) {
|
||||||
|
RunContextLossTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,13 @@ WebGLExtensionLoseContext::~WebGLExtensionLoseContext()
|
|||||||
void
|
void
|
||||||
WebGLExtensionLoseContext::LoseContext()
|
WebGLExtensionLoseContext::LoseContext()
|
||||||
{
|
{
|
||||||
if (!mContext->LoseContext())
|
mContext->LoseContext();
|
||||||
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGLExtensionLoseContext::RestoreContext()
|
WebGLExtensionLoseContext::RestoreContext()
|
||||||
{
|
{
|
||||||
if (!mContext->RestoreContext())
|
mContext->RestoreContext();
|
||||||
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext)
|
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext)
|
||||||
|
@ -99,7 +99,7 @@ function testLosingAndRestoringContext()
|
|||||||
// restore the context after this event has exited.
|
// restore the context after this event has exited.
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.restoreContext()");
|
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.restoreContext()");
|
||||||
// The context should still be lost. It will not get restored until the
|
// The context should still be lost. It will not get restored until the
|
||||||
// webglrestorecontext event is fired.
|
// webglrestorecontext event is fired.
|
||||||
shouldBeTrue("gl.isContextLost()");
|
shouldBeTrue("gl.isContextLost()");
|
||||||
shouldBe("gl.getError()", "gl.NO_ERROR");
|
shouldBe("gl.getError()", "gl.NO_ERROR");
|
||||||
|
@ -2699,19 +2699,6 @@ public:
|
|||||||
|
|
||||||
GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
|
GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Context reset constants.
|
|
||||||
* These are used to determine who is guilty when a context reset
|
|
||||||
* happens.
|
|
||||||
*/
|
|
||||||
enum ContextResetARB {
|
|
||||||
CONTEXT_NO_ERROR = 0,
|
|
||||||
CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
|
|
||||||
CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
|
|
||||||
CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::map<GLuint, SharedSurface_GL*> mFBOMapping;
|
std::map<GLuint, SharedSurface_GL*> mFBOMapping;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user