Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Side by Side Diff: Source/core/html/canvas/WebGLRenderingContext.cpp

Issue 14217005: Limit the number of WebGL contexts that are active at any given time (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Discovered I was doing RefPtr's wrong while debugging Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 #include <wtf/OwnArrayPtr.h> 77 #include <wtf/OwnArrayPtr.h>
78 #include <wtf/PassOwnArrayPtr.h> 78 #include <wtf/PassOwnArrayPtr.h>
79 #include <wtf/Uint16Array.h> 79 #include <wtf/Uint16Array.h>
80 #include <wtf/Uint32Array.h> 80 #include <wtf/Uint32Array.h>
81 #include <wtf/text/StringBuilder.h> 81 #include <wtf/text/StringBuilder.h>
82 82
83 namespace WebCore { 83 namespace WebCore {
84 84
85 const double secondsBetweenRestoreAttempts = 1.0; 85 const double secondsBetweenRestoreAttempts = 1.0;
86 const int maxGLErrorsAllowedToConsole = 256; 86 const int maxGLErrorsAllowedToConsole = 256;
87 const int maxGLActiveContexts = 20;
88
89 Vector<WebGLRenderingContext*>& WebGLRenderingContext::activeContexts()
90 {
91 DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, activeContexts, ());
92 return activeContexts;
93 }
94
95 Vector<WebGLRenderingContext*>& WebGLRenderingContext::forciblyEvictedContexts()
96 {
97 DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, forciblyEvictedContexts, ());
98 return forciblyEvictedContexts;
99 }
100
101 void WebGLRenderingContext::forciblyLoseOldestContext()
102 {
103 if (activeContexts().size()) {
104 WebGLRenderingContext* oldestActiveContext = activeContexts().first();
105 activeContexts().remove(0);
106
107 // This will call deactivateContext once the context has actually been l ost
108 oldestActiveContext->forceLostContext(WebGLRenderingContext::SyntheticLo stContext);
109 }
110 }
111
112 IntSize WebGLRenderingContext::oldestContextSize()
113 {
114 IntSize size;
115
116 if (activeContexts().size()) {
117 WebGLRenderingContext* oldestActiveContext = activeContexts().first();
118 size.setWidth(oldestActiveContext->drawingBufferWidth());
119 size.setHeight(oldestActiveContext->drawingBufferHeight());
120 }
121
122 return size;
123 }
124
125 void WebGLRenderingContext::activateContext(WebGLRenderingContext* context)
126 {
127 if (!activeContexts().contains(context))
128 activeContexts().append(context);
129
130 if (activeContexts().size() > maxGLActiveContexts)
131 forciblyLoseOldestContext();
132 }
133
134 void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bo ol addToEvictedList)
135 {
136 size_t position = activeContexts().find(context);
137 if (position != WTF::notFound)
138 activeContexts().remove(position);
139
140 if (addToEvictedList && !forciblyEvictedContexts().contains(context))
141 forciblyEvictedContexts().append(context);
142 }
143
144 void WebGLRenderingContext::willDestroyContext(WebGLRenderingContext* context)
145 {
146 size_t position = forciblyEvictedContexts().find(context);
147 if (position != WTF::notFound)
148 forciblyEvictedContexts().remove(position);
149
150 deactivateContext(context, false);
151
152 // Try to re-enable the oldest inactive contexts
153 while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContex ts().size()) {
154 WebGLRenderingContext* evictedContext = forciblyEvictedContexts().first( );
155 if (!evictedContext->m_restoreAllowed) {
156 forciblyEvictedContexts().remove(0);
157 continue;
158 }
159
160 IntSize desiredSize = evictedContext->m_drawingBuffer->adjustSize(evicte dContext->clampedCanvasSize());
161
162 // If there's room in the pixel budget for this context, restore it!
163 if (!desiredSize.isEmpty()) {
164 forciblyEvictedContexts().remove(0);
165 evictedContext->forceRestoreContext();
166 activeContexts().append(evictedContext);
167 }
168 break;
169 }
170 }
171
172 class WebGLRenderingContextEvictionManager : public ContextEvictionManager {
173 public:
174 void forciblyLoseOldestContext() {
175 WebGLRenderingContext::forciblyLoseOldestContext();
176 };
177 IntSize oldestContextSize() {
178 return WebGLRenderingContext::oldestContextSize();
179 };
180 };
87 181
88 namespace { 182 namespace {
89 183
90 class ScopedDrawingBufferBinder { 184 class ScopedDrawingBufferBinder {
91 public: 185 public:
92 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer * framebufferBinding) 186 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer * framebufferBinding)
93 : m_drawingBuffer(drawingBuffer) 187 : m_drawingBuffer(drawingBuffer)
94 , m_framebufferBinding(framebufferBinding) 188 , m_framebufferBinding(framebufferBinding)
95 { 189 {
96 // Commit DrawingBuffer if needed (e.g., for multisampling) 190 // Commit DrawingBuffer if needed (e.g., for multisampling)
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 { 561 {
468 ASSERT(m_context); 562 ASSERT(m_context);
469 ScriptWrappable::init(this); 563 ScriptWrappable::init(this);
470 564
471 m_contextGroup = WebGLContextGroup::create(); 565 m_contextGroup = WebGLContextGroup::create();
472 m_contextGroup->addContext(this); 566 m_contextGroup->addContext(this);
473 567
474 m_maxViewportDims[0] = m_maxViewportDims[1] = 0; 568 m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
475 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDi ms); 569 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDi ms);
476 570
571 RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptR ef(new WebGLRenderingContextEvictionManager());
572
477 // Create the DrawingBuffer and initialize the platform layer. 573 // Create the DrawingBuffer and initialize the platform layer.
478 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; 574 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
479 m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize() , preserve); 575 m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize() , preserve, contextEvictionManager.get());
Ken Russell (switch to Gerrit) 2013/04/24 01:30:57 Use PassRefPtr in the callee (see the comment else
480 576
481 if (!m_drawingBuffer->isZeroSized()) { 577 if (!m_drawingBuffer->isZeroSized()) {
482 m_drawingBuffer->bind(); 578 m_drawingBuffer->bind();
483 setupFlags(); 579 setupFlags();
484 initializeNewContext(); 580 initializeNewContext();
485 } 581 }
486 } 582 }
487 583
488 void WebGLRenderingContext::initializeNewContext() 584 void WebGLRenderingContext::initializeNewContext()
489 { 585 {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 652
557 IntSize canvasSize = clampedCanvasSize(); 653 IntSize canvasSize = clampedCanvasSize();
558 m_drawingBuffer->reset(canvasSize); 654 m_drawingBuffer->reset(canvasSize);
559 655
560 m_context->reshape(canvasSize.width(), canvasSize.height()); 656 m_context->reshape(canvasSize.width(), canvasSize.height());
561 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height()); 657 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
562 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height()); 658 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
563 659
564 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCall back(this))); 660 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCall back(this)));
565 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMe ssageCallback(this))); 661 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMe ssageCallback(this)));
662
663 activateContext(this);
566 } 664 }
567 665
568 void WebGLRenderingContext::setupFlags() 666 void WebGLRenderingContext::setupFlags()
569 { 667 {
570 ASSERT(m_context); 668 ASSERT(m_context);
571 669
572 Page* p = canvas()->document()->page(); 670 Page* p = canvas()->document()->page();
573 if (p) 671 if (p)
574 m_synthesizedErrorsToConsole = p->settings()->webGLErrorsToConsoleEnable d(); 672 m_synthesizedErrorsToConsole = p->settings()->webGLErrorsToConsoleEnable d();
575 673
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 m_textureUnits[i].m_texture2DBinding = 0; 714 m_textureUnits[i].m_texture2DBinding = 0;
617 m_textureUnits[i].m_textureCubeMapBinding = 0; 715 m_textureUnits[i].m_textureCubeMapBinding = 0;
618 } 716 }
619 717
620 m_blackTexture2D = 0; 718 m_blackTexture2D = 0;
621 m_blackTextureCubeMap = 0; 719 m_blackTextureCubeMap = 0;
622 720
623 detachAndRemoveAllObjects(); 721 detachAndRemoveAllObjects();
624 destroyGraphicsContext3D(); 722 destroyGraphicsContext3D();
625 m_contextGroup->removeContext(this); 723 m_contextGroup->removeContext(this);
724
725 willDestroyContext(this);
626 } 726 }
627 727
628 void WebGLRenderingContext::destroyGraphicsContext3D() 728 void WebGLRenderingContext::destroyGraphicsContext3D()
629 { 729 {
630 // The drawing buffer holds a context reference. It must also be destroyed 730 // The drawing buffer holds a context reference. It must also be destroyed
631 // in order for the context to be released. 731 // in order for the context to be released.
632 m_drawingBuffer.clear(); 732 m_drawingBuffer.clear();
633 733
634 if (m_context) { 734 if (m_context) {
635 m_context->setContextLostCallback(nullptr); 735 m_context->setContextLostCallback(nullptr);
(...skipping 5112 matching lines...) Expand 10 before | Expand all | Expand 10 after
5748 m_context->vertexAttribPointer(0, state.size, state.type, state.normaliz ed, state.originalStride, state.offset); 5848 m_context->vertexAttribPointer(0, state.size, state.type, state.normaliz ed, state.originalStride, state.offset);
5749 } 5849 }
5750 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundA rrayBuffer.get())); 5850 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundA rrayBuffer.get()));
5751 } 5851 }
5752 5852
5753 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext >*) 5853 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext >*)
5754 { 5854 {
5755 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().web glcontextlostEvent, false, true, ""); 5855 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().web glcontextlostEvent, false, true, "");
5756 canvas()->dispatchEvent(event); 5856 canvas()->dispatchEvent(event);
5757 m_restoreAllowed = event->defaultPrevented(); 5857 m_restoreAllowed = event->defaultPrevented();
5858 deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAll owed);
5758 if (m_contextLostMode == RealLostContext && m_restoreAllowed) 5859 if (m_contextLostMode == RealLostContext && m_restoreAllowed)
5759 m_restoreTimer.startOneShot(0); 5860 m_restoreTimer.startOneShot(0);
5760 } 5861 }
5761 5862
5762 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*) 5863 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
5763 { 5864 {
5764 ASSERT(m_contextLost); 5865 ASSERT(m_contextLost);
5765 if (!m_contextLost) 5866 if (!m_contextLost)
5766 return; 5867 return;
5767 5868
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
5824 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, ho stWindow)); 5925 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, ho stWindow));
5825 if (!context) { 5926 if (!context) {
5826 if (m_contextLostMode == RealLostContext) 5927 if (m_contextLostMode == RealLostContext)
5827 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); 5928 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
5828 else 5929 else
5829 // This likely shouldn't happen but is the best way to report it to the WebGL app. 5930 // This likely shouldn't happen but is the best way to report it to the WebGL app.
5830 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error r estoring context"); 5931 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error r estoring context");
5831 return; 5932 return;
5832 } 5933 }
5833 5934
5935 RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptR ef(new WebGLRenderingContextEvictionManager());
5936
5834 // Construct a new drawing buffer with the new GraphicsContext3D. 5937 // Construct a new drawing buffer with the new GraphicsContext3D.
5835 m_drawingBuffer->clear(); 5938 m_drawingBuffer->clear();
5836 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; 5939 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
5837 m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve); 5940 m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve, contextEvictionManager.get());
5838 5941
5839 if (m_drawingBuffer->isZeroSized()) 5942 if (m_drawingBuffer->isZeroSized())
5840 return; 5943 return;
5841 5944
5842 m_drawingBuffer->bind(); 5945 m_drawingBuffer->bind();
5843 5946
5844 m_context = context; 5947 m_context = context;
5845 m_contextLost = false; 5948 m_contextLost = false;
5846 setupFlags(); 5949 setupFlags();
5847 initializeNewContext(); 5950 initializeNewContext();
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
6002 bool WebGLRenderingContext::supportsDrawBuffers() 6105 bool WebGLRenderingContext::supportsDrawBuffers()
6003 { 6106 {
6004 if (!m_drawBuffersWebGLRequirementsChecked) { 6107 if (!m_drawBuffersWebGLRequirementsChecked) {
6005 m_drawBuffersWebGLRequirementsChecked = true; 6108 m_drawBuffersWebGLRequirementsChecked = true;
6006 m_drawBuffersSupported = EXTDrawBuffers::supported(this); 6109 m_drawBuffersSupported = EXTDrawBuffers::supported(this);
6007 } 6110 }
6008 return m_drawBuffersSupported; 6111 return m_drawBuffersSupported;
6009 } 6112 }
6010 6113
6011 } // namespace WebCore 6114 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698