Chromium Code Reviews| Index: Source/WebCore/html/canvas/WebGLRenderingContext.cpp |
| diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp |
| index 08fc484f861952d2f2de26a3bb5e576dc732186e..c95ef680bcac29cf367c24ed10d145526e30cc71 100644 |
| --- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp |
| +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp |
| @@ -84,6 +84,69 @@ namespace WebCore { |
| const double secondsBetweenRestoreAttempts = 1.0; |
| const int maxGLErrorsAllowedToConsole = 256; |
| +const int maxGLActiveContexts = 16; |
| + |
| +Vector<WebGLRenderingContext*>& WebGLRenderingContext::activeContexts() |
| +{ |
| + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, activeContexts, ()); |
| + return activeContexts; |
| +} |
| + |
| +Vector<WebGLRenderingContext*>& WebGLRenderingContext::inactiveContexts() |
| +{ |
| + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, inactiveContexts, ()); |
| + return inactiveContexts; |
| +} |
| + |
| +void WebGLRenderingContext::forceLostOldestContext() |
| +{ |
| + if(activeContexts().size()) { |
|
Ken Russell (switch to Gerrit)
2013/04/16 02:57:52
Add space between if and ( everywhere please.
|
| + WebGLRenderingContext* oldestActiveContext = activeContexts().first(); |
| + activeContexts().remove(0); |
|
Ken Russell (switch to Gerrit)
2013/04/16 02:57:52
The implicit assumption here is that contexts' age
|
| + |
| + // This will call deactivateContext once the context has actually been lost |
| + oldestActiveContext->forceLostContext(WebGLRenderingContext::SyntheticLostContext); |
| + } |
| +} |
| + |
| +void WebGLRenderingContext::activateContext(WebGLRenderingContext* context) |
| +{ |
| + if(!activeContexts().contains(context)) |
| + activeContexts().append(context); |
| + |
| + if(activeContexts().size() > maxGLActiveContexts) |
| + forceLostOldestContext(); |
| +} |
| + |
| +void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bool addToInactiveList) |
| +{ |
| + size_t position = activeContexts().find(context); |
| + if(position != WTF::notFound) |
| + activeContexts().remove(position); |
| + |
| + if(addToInactiveList && !inactiveContexts().contains(context)) |
| + inactiveContexts().append(context); |
| +} |
| + |
| +void WebGLRenderingContext::removeContext(WebGLRenderingContext* context) |
| +{ |
| + size_t position = inactiveContexts().find(context); |
| + if(position != WTF::notFound) |
| + inactiveContexts().remove(position); |
| + |
| + deactivateContext(context, false); |
| + |
| + // Try to re-enable the oldest inactive contexts |
| + while(activeContexts().size() < maxGLActiveContexts && inactiveContexts().size() > 0) { |
| + WebGLRenderingContext* oldestInactiveContext = inactiveContexts().first(); |
| + inactiveContexts().remove(0); |
| + |
| + if(oldestInactiveContext->m_restoreAllowed) { |
|
Ken Russell (switch to Gerrit)
2013/04/16 02:57:52
If restoration isn't allowed, we lose track of old
|
| + oldestInactiveContext->forceRestoreContext(); |
| + activeContexts().append(oldestInactiveContext); |
| + } |
| + } |
| +} |
| namespace { |
| @@ -407,7 +470,7 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen |
| return nullptr; |
| Settings* settings = frame->settings(); |
| - // The FrameLoaderClient might creation of a new WebGL context despite the page settings; in |
| + // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in |
| // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension. |
| if (!frame->loader()->client()->allowWebGL(settings && settings->webGLEnabled())) { |
| canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context.")); |
| @@ -565,6 +628,8 @@ void WebGLRenderingContext::initializeNewContext() |
| m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this))); |
| m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMessageCallback(this))); |
| + |
| + activateContext(this); |
| } |
| void WebGLRenderingContext::setupFlags() |
| @@ -625,6 +690,8 @@ WebGLRenderingContext::~WebGLRenderingContext() |
| detachAndRemoveAllObjects(); |
| destroyGraphicsContext3D(); |
| m_contextGroup->removeContext(this); |
| + |
| + removeContext(this); |
| } |
| void WebGLRenderingContext::destroyGraphicsContext3D() |
| @@ -4631,6 +4698,7 @@ void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMo |
| // Make absolutely sure we do not refer to an already-deleted texture or framebuffer. |
| m_drawingBuffer->setTexture2DBinding(0); |
| m_drawingBuffer->setFramebufferBinding(0); |
| + m_drawingBuffer->clear(); |
| } |
| // There is no direct way to clear errors from a GL implementation and |
| @@ -5794,6 +5862,7 @@ void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext |
| RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, ""); |
| canvas()->dispatchEvent(event); |
| m_restoreAllowed = event->defaultPrevented(); |
| + deactivateContext(this, m_restoreAllowed); |
|
Ken Russell (switch to Gerrit)
2013/04/16 02:57:52
This doesn't seem right. If a context receives a R
|
| if (m_contextLostMode == RealLostContext && m_restoreAllowed) |
| m_restoreTimer.startOneShot(0); |
| } |
| @@ -5962,7 +6031,6 @@ void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functi |
| m_context->synthesizeGLError(error); |
| } |
| - |
| void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description) |
| { |
| if (m_synthesizedErrorsToConsole) { |