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

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: Rebased to latest master 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/text/StringBuilder.h> 79 #include <wtf/text/StringBuilder.h>
80 #include <wtf/Uint16Array.h> 80 #include <wtf/Uint16Array.h>
81 #include <wtf/Uint32Array.h> 81 #include <wtf/Uint32Array.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 = 16;
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(const String& reason)
102 {
103 if (activeContexts().size()) {
104 WebGLRenderingContext* oldestActiveContext = activeContexts().first();
105 activeContexts().remove(0);
106
107 oldestActiveContext->printWarningToConsole(reason);
108
109 // This will call deactivateContext once the context has actually been l ost.
110 oldestActiveContext->forceLostContext(WebGLRenderingContext::SyntheticLo stContext);
111 }
112 }
113
114 IntSize WebGLRenderingContext::oldestContextSize()
115 {
116 IntSize size;
117
118 if (activeContexts().size()) {
119 WebGLRenderingContext* oldestActiveContext = activeContexts().first();
120 size.setWidth(oldestActiveContext->drawingBufferWidth());
121 size.setHeight(oldestActiveContext->drawingBufferHeight());
122 }
123
124 return size;
125 }
126
127 void WebGLRenderingContext::activateContext(WebGLRenderingContext* context)
128 {
129 if (!activeContexts().contains(context))
130 activeContexts().append(context);
131
132 if (activeContexts().size() > maxGLActiveContexts)
133 forciblyLoseOldestContext("WARNING: Too many active WebGL contexts. Olde st context will be lost.");
134 }
135
136 void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bo ol addToEvictedList)
137 {
138 size_t position = activeContexts().find(context);
139 if (position != WTF::notFound)
140 activeContexts().remove(position);
141
142 if (addToEvictedList && !forciblyEvictedContexts().contains(context))
143 forciblyEvictedContexts().append(context);
144 }
145
146 void WebGLRenderingContext::willDestroyContext(WebGLRenderingContext* context)
147 {
148 size_t position = forciblyEvictedContexts().find(context);
149 if (position != WTF::notFound)
150 forciblyEvictedContexts().remove(position);
151
152 deactivateContext(context, false);
153
154 // Try to re-enable the oldest inactive contexts.
155 while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContex ts().size()) {
156 WebGLRenderingContext* evictedContext = forciblyEvictedContexts().first( );
157 if (!evictedContext->m_restoreAllowed) {
158 forciblyEvictedContexts().remove(0);
159 continue;
160 }
161
162 IntSize desiredSize = evictedContext->m_drawingBuffer->adjustSize(evicte dContext->clampedCanvasSize());
163
164 // If there's room in the pixel budget for this context, restore it.
165 if (!desiredSize.isEmpty()) {
166 forciblyEvictedContexts().remove(0);
167 evictedContext->forceRestoreContext();
168 activeContexts().append(evictedContext);
169 }
170 break;
171 }
172 }
173
174 class WebGLRenderingContextEvictionManager : public ContextEvictionManager {
175 public:
176 void forciblyLoseOldestContext(const String& reason) {
177 WebGLRenderingContext::forciblyLoseOldestContext(reason);
178 };
179 IntSize oldestContextSize() {
180 return WebGLRenderingContext::oldestContextSize();
181 };
182 };
87 183
88 namespace { 184 namespace {
89 185
90 class ScopedDrawingBufferBinder { 186 class ScopedDrawingBufferBinder {
91 public: 187 public:
92 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer * framebufferBinding) 188 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer * framebufferBinding)
93 : m_drawingBuffer(drawingBuffer) 189 : m_drawingBuffer(drawingBuffer)
94 , m_framebufferBinding(framebufferBinding) 190 , m_framebufferBinding(framebufferBinding)
95 { 191 {
96 // Commit DrawingBuffer if needed (e.g., for multisampling) 192 // Commit DrawingBuffer if needed (e.g., for multisampling)
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 { 563 {
468 ASSERT(m_context); 564 ASSERT(m_context);
469 ScriptWrappable::init(this); 565 ScriptWrappable::init(this);
470 566
471 m_contextGroup = WebGLContextGroup::create(); 567 m_contextGroup = WebGLContextGroup::create();
472 m_contextGroup->addContext(this); 568 m_contextGroup->addContext(this);
473 569
474 m_maxViewportDims[0] = m_maxViewportDims[1] = 0; 570 m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
475 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDi ms); 571 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDi ms);
476 572
573 RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptR ef(new WebGLRenderingContextEvictionManager());
574
477 // Create the DrawingBuffer and initialize the platform layer. 575 // Create the DrawingBuffer and initialize the platform layer.
478 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; 576 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
479 m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize() , preserve); 577 m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize() , preserve, contextEvictionManager.release());
480 578
481 if (!m_drawingBuffer->isZeroSized()) { 579 if (!m_drawingBuffer->isZeroSized()) {
482 m_drawingBuffer->bind(); 580 m_drawingBuffer->bind();
483 setupFlags(); 581 setupFlags();
484 initializeNewContext(); 582 initializeNewContext();
485 } 583 }
486 } 584 }
487 585
488 void WebGLRenderingContext::initializeNewContext() 586 void WebGLRenderingContext::initializeNewContext()
489 { 587 {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 654
557 IntSize canvasSize = clampedCanvasSize(); 655 IntSize canvasSize = clampedCanvasSize();
558 m_drawingBuffer->reset(canvasSize); 656 m_drawingBuffer->reset(canvasSize);
559 657
560 m_context->reshape(canvasSize.width(), canvasSize.height()); 658 m_context->reshape(canvasSize.width(), canvasSize.height());
561 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height()); 659 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
562 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height()); 660 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
563 661
564 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCall back(this))); 662 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCall back(this)));
565 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMe ssageCallback(this))); 663 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMe ssageCallback(this)));
664
665 activateContext(this);
566 } 666 }
567 667
568 void WebGLRenderingContext::setupFlags() 668 void WebGLRenderingContext::setupFlags()
569 { 669 {
570 ASSERT(m_context); 670 ASSERT(m_context);
571 671
572 Page* p = canvas()->document()->page(); 672 Page* p = canvas()->document()->page();
573 if (p) 673 if (p)
574 m_synthesizedErrorsToConsole = p->settings()->webGLErrorsToConsoleEnable d(); 674 m_synthesizedErrorsToConsole = p->settings()->webGLErrorsToConsoleEnable d();
575 675
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 m_textureUnits[i].m_texture2DBinding = 0; 716 m_textureUnits[i].m_texture2DBinding = 0;
617 m_textureUnits[i].m_textureCubeMapBinding = 0; 717 m_textureUnits[i].m_textureCubeMapBinding = 0;
618 } 718 }
619 719
620 m_blackTexture2D = 0; 720 m_blackTexture2D = 0;
621 m_blackTextureCubeMap = 0; 721 m_blackTextureCubeMap = 0;
622 722
623 detachAndRemoveAllObjects(); 723 detachAndRemoveAllObjects();
624 destroyGraphicsContext3D(); 724 destroyGraphicsContext3D();
625 m_contextGroup->removeContext(this); 725 m_contextGroup->removeContext(this);
726
727 willDestroyContext(this);
626 } 728 }
627 729
628 void WebGLRenderingContext::destroyGraphicsContext3D() 730 void WebGLRenderingContext::destroyGraphicsContext3D()
629 { 731 {
630 // The drawing buffer holds a context reference. It must also be destroyed 732 // The drawing buffer holds a context reference. It must also be destroyed
631 // in order for the context to be released. 733 // in order for the context to be released.
632 m_drawingBuffer.clear(); 734 m_drawingBuffer.clear();
633 735
634 if (m_context) { 736 if (m_context) {
635 m_context->setContextLostCallback(nullptr); 737 m_context->setContextLostCallback(nullptr);
(...skipping 5098 matching lines...) Expand 10 before | Expand all | Expand 10 after
5734 m_context->vertexAttribPointer(0, state.size, state.type, state.normaliz ed, state.originalStride, state.offset); 5836 m_context->vertexAttribPointer(0, state.size, state.type, state.normaliz ed, state.originalStride, state.offset);
5735 } 5837 }
5736 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundA rrayBuffer.get())); 5838 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundA rrayBuffer.get()));
5737 } 5839 }
5738 5840
5739 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext >*) 5841 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext >*)
5740 { 5842 {
5741 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().web glcontextlostEvent, false, true, ""); 5843 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().web glcontextlostEvent, false, true, "");
5742 canvas()->dispatchEvent(event); 5844 canvas()->dispatchEvent(event);
5743 m_restoreAllowed = event->defaultPrevented(); 5845 m_restoreAllowed = event->defaultPrevented();
5846 deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAll owed);
5744 if (m_contextLostMode == RealLostContext && m_restoreAllowed) 5847 if (m_contextLostMode == RealLostContext && m_restoreAllowed)
5745 m_restoreTimer.startOneShot(0); 5848 m_restoreTimer.startOneShot(0);
5746 } 5849 }
5747 5850
5748 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*) 5851 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
5749 { 5852 {
5750 ASSERT(m_contextLost); 5853 ASSERT(m_contextLost);
5751 if (!m_contextLost) 5854 if (!m_contextLost)
5752 return; 5855 return;
5753 5856
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
5810 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, ho stWindow)); 5913 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, ho stWindow));
5811 if (!context) { 5914 if (!context) {
5812 if (m_contextLostMode == RealLostContext) 5915 if (m_contextLostMode == RealLostContext)
5813 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); 5916 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
5814 else 5917 else
5815 // This likely shouldn't happen but is the best way to report it to the WebGL app. 5918 // This likely shouldn't happen but is the best way to report it to the WebGL app.
5816 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error r estoring context"); 5919 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error r estoring context");
5817 return; 5920 return;
5818 } 5921 }
5819 5922
5923 RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptR ef(new WebGLRenderingContextEvictionManager());
5924
5820 // Construct a new drawing buffer with the new GraphicsContext3D. 5925 // Construct a new drawing buffer with the new GraphicsContext3D.
5821 m_drawingBuffer->clear(); 5926 m_drawingBuffer->clear();
5822 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; 5927 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
5823 m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve); 5928 m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release());
5824 5929
5825 if (m_drawingBuffer->isZeroSized()) 5930 if (m_drawingBuffer->isZeroSized())
5826 return; 5931 return;
5827 5932
5828 m_drawingBuffer->bind(); 5933 m_drawingBuffer->bind();
5829 5934
5830 m_context = context; 5935 m_context = context;
5831 m_contextLost = false; 5936 m_contextLost = false;
5832 setupFlags(); 5937 setupFlags();
5833 initializeNewContext(); 5938 initializeNewContext();
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
5988 bool WebGLRenderingContext::supportsDrawBuffers() 6093 bool WebGLRenderingContext::supportsDrawBuffers()
5989 { 6094 {
5990 if (!m_drawBuffersWebGLRequirementsChecked) { 6095 if (!m_drawBuffersWebGLRequirementsChecked) {
5991 m_drawBuffersWebGLRequirementsChecked = true; 6096 m_drawBuffersWebGLRequirementsChecked = true;
5992 m_drawBuffersSupported = EXTDrawBuffers::supported(this); 6097 m_drawBuffersSupported = EXTDrawBuffers::supported(this);
5993 } 6098 }
5994 return m_drawBuffersSupported; 6099 return m_drawBuffersSupported;
5995 } 6100 }
5996 6101
5997 } // namespace WebCore 6102 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/html/canvas/WebGLRenderingContext.h ('k') | Source/core/platform/graphics/gpu/DrawingBuffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698