| Index: Source/core/html/canvas/WebGLRenderingContext.cpp
|
| diff --git a/Source/core/html/canvas/WebGLRenderingContext.cpp b/Source/core/html/canvas/WebGLRenderingContext.cpp
|
| index 5e4be277e3e9c4314adec09b8adda4a6bb2d565d..c66863859b0fbca9042eaa238c238e15668d012a 100644
|
| --- a/Source/core/html/canvas/WebGLRenderingContext.cpp
|
| +++ b/Source/core/html/canvas/WebGLRenderingContext.cpp
|
| @@ -84,6 +84,90 @@ namespace WebCore {
|
|
|
| const double secondsBetweenRestoreAttempts = 1.0;
|
| const int maxGLErrorsAllowedToConsole = 256;
|
| +const int maxGLActiveContexts = 20;
|
| +
|
| +Vector<WebGLRenderingContext*>& WebGLRenderingContext::activeContexts()
|
| +{
|
| + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, activeContexts, ());
|
| + return activeContexts;
|
| +}
|
| +
|
| +Vector<WebGLRenderingContext*>& WebGLRenderingContext::forciblyEvictedContexts()
|
| +{
|
| + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, forciblyEvictedContexts, ());
|
| + return forciblyEvictedContexts;
|
| +}
|
| +
|
| +void WebGLRenderingContext::forciblyLoseOldestContext()
|
| +{
|
| + if (activeContexts().size()) {
|
| + WebGLRenderingContext* oldestActiveContext = activeContexts().first();
|
| + activeContexts().remove(0);
|
| +
|
| + // This will call deactivateContext once the context has actually been lost
|
| + oldestActiveContext->forceLostContext(WebGLRenderingContext::SyntheticLostContext);
|
| + }
|
| +}
|
| +
|
| +IntSize WebGLRenderingContext::oldestContextSize()
|
| +{
|
| + IntSize size;
|
| +
|
| + if (activeContexts().size()) {
|
| + WebGLRenderingContext* oldestActiveContext = activeContexts().first();
|
| + size.setWidth(oldestActiveContext->drawingBufferWidth());
|
| + size.setHeight(oldestActiveContext->drawingBufferHeight());
|
| + }
|
| +
|
| + return size;
|
| +}
|
| +
|
| +void WebGLRenderingContext::activateContext(WebGLRenderingContext* context)
|
| +{
|
| + if (!activeContexts().contains(context))
|
| + activeContexts().append(context);
|
| +
|
| + if (activeContexts().size() > maxGLActiveContexts)
|
| + forciblyLoseOldestContext();
|
| +}
|
| +
|
| +void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bool addToEvictedList)
|
| +{
|
| + size_t position = activeContexts().find(context);
|
| + if (position != WTF::notFound)
|
| + activeContexts().remove(position);
|
| +
|
| + if (addToEvictedList && !forciblyEvictedContexts().contains(context))
|
| + forciblyEvictedContexts().append(context);
|
| +}
|
| +
|
| +void WebGLRenderingContext::willDestroyContext(WebGLRenderingContext* context)
|
| +{
|
| + size_t position = forciblyEvictedContexts().find(context);
|
| + if (position != WTF::notFound)
|
| + forciblyEvictedContexts().remove(position);
|
| +
|
| + deactivateContext(context, false);
|
| +
|
| + // Try to re-enable the oldest inactive contexts
|
| + while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContexts().size()) {
|
| + WebGLRenderingContext* evictedContext = forciblyEvictedContexts().first();
|
| + if (!evictedContext->m_restoreAllowed) {
|
| + forciblyEvictedContexts().remove(0);
|
| + continue;
|
| + }
|
| +
|
| + IntSize desiredSize = evictedContext->m_drawingBuffer->adjustSize(evictedContext->clampedCanvasSize());
|
| +
|
| + // If there's room in the pixel budget for this context, restore it!
|
| + if (!desiredSize.isEmpty()) {
|
| + forciblyEvictedContexts().remove(0);
|
| + evictedContext->forceRestoreContext();
|
| + activeContexts().append(evictedContext);
|
| + }
|
| + break;
|
| + }
|
| +}
|
|
|
| namespace {
|
|
|
| @@ -563,6 +647,8 @@ void WebGLRenderingContext::initializeNewContext()
|
|
|
| m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this)));
|
| m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMessageCallback(this)));
|
| +
|
| + activateContext(this);
|
| }
|
|
|
| void WebGLRenderingContext::setupFlags()
|
| @@ -623,6 +709,8 @@ WebGLRenderingContext::~WebGLRenderingContext()
|
| detachAndRemoveAllObjects();
|
| destroyGraphicsContext3D();
|
| m_contextGroup->removeContext(this);
|
| +
|
| + willDestroyContext(this);
|
| }
|
|
|
| void WebGLRenderingContext::destroyGraphicsContext3D()
|
| @@ -5755,6 +5843,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_contextLostMode != RealLostContext && m_restoreAllowed);
|
| if (m_contextLostMode == RealLostContext && m_restoreAllowed)
|
| m_restoreTimer.startOneShot(0);
|
| }
|
|
|