| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |