Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2010, Google Inc. All rights reserved. | 2 * Copyright (c) 2010, Google 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 are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 | 51 |
| 52 namespace WebCore { | 52 namespace WebCore { |
| 53 | 53 |
| 54 // Global resource ceiling (expressed in terms of pixels) for DrawingBuffer crea tion and resize. | 54 // Global resource ceiling (expressed in terms of pixels) for DrawingBuffer crea tion and resize. |
| 55 // When this limit is set, DrawingBuffer::create() and DrawingBuffer::reset() ca lls that would | 55 // When this limit is set, DrawingBuffer::create() and DrawingBuffer::reset() ca lls that would |
| 56 // exceed the global cap will instead clear the buffer. | 56 // exceed the global cap will instead clear the buffer. |
| 57 static const int s_maximumResourceUsePixels = 16 * 1024 * 1024; | 57 static const int s_maximumResourceUsePixels = 16 * 1024 * 1024; |
| 58 static int s_currentResourceUsePixels = 0; | 58 static int s_currentResourceUsePixels = 0; |
| 59 static const float s_resourceAdjustedRatio = 0.5; | 59 static const float s_resourceAdjustedRatio = 0.5; |
| 60 | 60 |
| 61 static const bool s_allowContextEvictionOnCreate = true; | |
| 62 static const int s_maxScaleAttempts = 3; | |
| 63 | |
| 61 class ScopedTextureUnit0BindingRestorer { | 64 class ScopedTextureUnit0BindingRestorer { |
| 62 public: | 65 public: |
| 63 ScopedTextureUnit0BindingRestorer(GraphicsContext3D* context, GC3Denum activ eTextureUnit, Platform3DObject textureUnitZeroId) | 66 ScopedTextureUnit0BindingRestorer(GraphicsContext3D* context, GC3Denum activ eTextureUnit, Platform3DObject textureUnitZeroId) |
| 64 : m_context(context) | 67 : m_context(context) |
| 65 , m_oldActiveTextureUnit(activeTextureUnit) | 68 , m_oldActiveTextureUnit(activeTextureUnit) |
| 66 , m_oldTextureUnitZeroId(textureUnitZeroId) | 69 , m_oldTextureUnitZeroId(textureUnitZeroId) |
| 67 { | 70 { |
| 68 m_context->activeTexture(GraphicsContext3D::TEXTURE0); | 71 m_context->activeTexture(GraphicsContext3D::TEXTURE0); |
| 69 } | 72 } |
| 70 ~ScopedTextureUnit0BindingRestorer() | 73 ~ScopedTextureUnit0BindingRestorer() |
| 71 { | 74 { |
| 72 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_oldTextureUnitZe roId); | 75 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_oldTextureUnitZe roId); |
| 73 m_context->activeTexture(m_oldActiveTextureUnit); | 76 m_context->activeTexture(m_oldActiveTextureUnit); |
| 74 } | 77 } |
| 75 | 78 |
| 76 private: | 79 private: |
| 77 GraphicsContext3D* m_context; | 80 GraphicsContext3D* m_context; |
| 78 GC3Denum m_oldActiveTextureUnit; | 81 GC3Denum m_oldActiveTextureUnit; |
| 79 Platform3DObject m_oldTextureUnitZeroId; | 82 Platform3DObject m_oldTextureUnitZeroId; |
| 80 }; | 83 }; |
| 81 | 84 |
| 82 PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, cons t IntSize& size, PreserveDrawingBuffer preserve) | 85 PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, cons t IntSize& size, PreserveDrawingBuffer preserve, ContextEvictionManager* context EvictionManager) |
| 83 { | 86 { |
| 84 Extensions3D* extensions = context->getExtensions(); | 87 Extensions3D* extensions = context->getExtensions(); |
| 85 bool multisampleSupported = extensions->maySupportMultisampling() | 88 bool multisampleSupported = extensions->maySupportMultisampling() |
| 86 && extensions->supports("GL_ANGLE_framebuffer_blit") | 89 && extensions->supports("GL_ANGLE_framebuffer_blit") |
| 87 && extensions->supports("GL_ANGLE_framebuffer_multisample") | 90 && extensions->supports("GL_ANGLE_framebuffer_multisample") |
| 88 && extensions->supports("GL_OES_rgb8_rgba8"); | 91 && extensions->supports("GL_OES_rgb8_rgba8"); |
| 89 if (multisampleSupported) { | 92 if (multisampleSupported) { |
| 90 extensions->ensureEnabled("GL_ANGLE_framebuffer_blit"); | 93 extensions->ensureEnabled("GL_ANGLE_framebuffer_blit"); |
| 91 extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); | 94 extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); |
| 92 extensions->ensureEnabled("GL_OES_rgb8_rgba8"); | 95 extensions->ensureEnabled("GL_OES_rgb8_rgba8"); |
| 93 } | 96 } |
| 94 bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth _stencil"); | 97 bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth _stencil"); |
| 95 if (packedDepthStencilSupported) | 98 if (packedDepthStencilSupported) |
| 96 extensions->ensureEnabled("GL_OES_packed_depth_stencil"); | 99 extensions->ensureEnabled("GL_OES_packed_depth_stencil"); |
| 97 | 100 |
| 98 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, si ze, multisampleSupported, packedDepthStencilSupported, preserve)); | 101 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, si ze, multisampleSupported, packedDepthStencilSupported, preserve, contextEviction Manager)); |
| 99 return drawingBuffer.release(); | 102 return drawingBuffer.release(); |
| 100 } | 103 } |
| 101 | 104 |
| 102 DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, | 105 DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, |
| 103 const IntSize& size, | 106 const IntSize& size, |
| 104 bool multisampleExtensionSupported, | 107 bool multisampleExtensionSupported, |
| 105 bool packedDepthStencilExtensionSupported, | 108 bool packedDepthStencilExtensionSupported, |
| 106 PreserveDrawingBuffer preserve) | 109 PreserveDrawingBuffer preserve, |
| 110 ContextEvictionManager* contextEvictionManager) | |
| 107 : m_preserveDrawingBuffer(preserve) | 111 : m_preserveDrawingBuffer(preserve) |
| 108 , m_scissorEnabled(false) | 112 , m_scissorEnabled(false) |
| 109 , m_texture2DBinding(0) | 113 , m_texture2DBinding(0) |
| 110 , m_framebufferBinding(0) | 114 , m_framebufferBinding(0) |
| 111 , m_activeTextureUnit(GraphicsContext3D::TEXTURE0) | 115 , m_activeTextureUnit(GraphicsContext3D::TEXTURE0) |
| 112 , m_context(context) | 116 , m_context(context) |
| 113 , m_size(-1, -1) | 117 , m_size(-1, -1) |
| 114 , m_multisampleExtensionSupported(multisampleExtensionSupported) | 118 , m_multisampleExtensionSupported(multisampleExtensionSupported) |
| 115 , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupporte d) | 119 , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupporte d) |
| 116 , m_fbo(0) | 120 , m_fbo(0) |
| 117 , m_colorBuffer(0) | 121 , m_colorBuffer(0) |
| 118 , m_frontColorBuffer(0) | 122 , m_frontColorBuffer(0) |
| 119 , m_separateFrontTexture(false) | 123 , m_separateFrontTexture(false) |
| 120 , m_depthStencilBuffer(0) | 124 , m_depthStencilBuffer(0) |
| 121 , m_depthBuffer(0) | 125 , m_depthBuffer(0) |
| 122 , m_stencilBuffer(0) | 126 , m_stencilBuffer(0) |
| 123 , m_multisampleFBO(0) | 127 , m_multisampleFBO(0) |
| 124 , m_multisampleColorBuffer(0) | 128 , m_multisampleColorBuffer(0) |
| 125 , m_contentsChanged(true) | 129 , m_contentsChanged(true) |
| 126 , m_internalColorFormat(0) | 130 , m_internalColorFormat(0) |
| 127 , m_colorFormat(0) | 131 , m_colorFormat(0) |
| 128 , m_internalRenderbufferFormat(0) | 132 , m_internalRenderbufferFormat(0) |
| 133 , m_contextEvictionManager(contextEvictionManager) | |
| 129 { | 134 { |
| 130 // Used by browser tests to detect the use of a DrawingBuffer. | 135 // Used by browser tests to detect the use of a DrawingBuffer. |
| 131 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation"); | 136 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation"); |
| 132 #if !USES_MAILBOX | 137 #if !USES_MAILBOX |
| 133 // We need a separate front and back textures if ... | 138 // We need a separate front and back textures if ... |
| 134 m_separateFrontTexture = m_preserveDrawingBuffer == Preserve // ... we have to preserve contents after compositing, which is done with a copy or ... | 139 m_separateFrontTexture = m_preserveDrawingBuffer == Preserve // ... we have to preserve contents after compositing, which is done with a copy or ... |
| 135 || WebKit::Platform::current()->isThreadedCompositi ngEnabled(); // ... if we're in threaded mode and need to double buffer. | 140 || WebKit::Platform::current()->isThreadedCompositi ngEnabled(); // ... if we're in threaded mode and need to double buffer. |
| 136 #endif // USES_MAILBOX | 141 #endif // USES_MAILBOX |
| 137 initialize(size); | 142 initialize(size); |
| 138 } | 143 } |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 setSize(IntSize()); | 449 setSize(IntSize()); |
| 445 | 450 |
| 446 m_colorBuffer = 0; | 451 m_colorBuffer = 0; |
| 447 m_frontColorBuffer = 0; | 452 m_frontColorBuffer = 0; |
| 448 m_multisampleColorBuffer = 0; | 453 m_multisampleColorBuffer = 0; |
| 449 m_depthStencilBuffer = 0; | 454 m_depthStencilBuffer = 0; |
| 450 m_depthBuffer = 0; | 455 m_depthBuffer = 0; |
| 451 m_stencilBuffer = 0; | 456 m_stencilBuffer = 0; |
| 452 m_multisampleFBO = 0; | 457 m_multisampleFBO = 0; |
| 453 m_fbo = 0; | 458 m_fbo = 0; |
| 459 m_contextEvictionManager.clear(); | |
|
Ken Russell (switch to Gerrit)
2013/04/24 01:30:57
Shouldn't the eviction manager be used across mult
bajones
2013/04/24 03:37:08
It is. clear() is only called when the DrawingBuff
| |
| 454 | 460 |
| 455 #if USES_MAILBOX | 461 #if USES_MAILBOX |
| 456 m_lastColorBuffer.clear(); | 462 m_lastColorBuffer.clear(); |
| 457 m_recycledMailboxes.clear(); | 463 m_recycledMailboxes.clear(); |
| 458 m_textureMailboxes.clear(); | 464 m_textureMailboxes.clear(); |
| 459 #endif // USES_MAILBOX | 465 #endif // USES_MAILBOX |
| 460 } | 466 } |
| 461 | 467 |
| 462 unsigned DrawingBuffer::createColorTexture(const IntSize& size) | 468 unsigned DrawingBuffer::createColorTexture(const IntSize& size) |
| 463 { | 469 { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 if (multisample()) | 576 if (multisample()) |
| 571 m_context->getExtensions()->renderbufferStorageMultisample(Graph icsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, size .width(), size.height()); | 577 m_context->getExtensions()->renderbufferStorageMultisample(Graph icsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, size .width(), size.height()); |
| 572 else | 578 else |
| 573 m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height()); | 579 m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height()); |
| 574 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, G raphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencil Buffer); | 580 m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, G raphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencil Buffer); |
| 575 } | 581 } |
| 576 } | 582 } |
| 577 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); | 583 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); |
| 578 } | 584 } |
| 579 | 585 |
| 586 | |
| 587 | |
| 580 void DrawingBuffer::clearFramebuffers(GC3Dbitfield clearMask) | 588 void DrawingBuffer::clearFramebuffers(GC3Dbitfield clearMask) |
| 581 { | 589 { |
| 582 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); | 590 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); |
| 583 | 591 |
| 584 m_context->clear(clearMask); | 592 m_context->clear(clearMask); |
| 585 | 593 |
| 586 // The multisample fbo was just cleared, but we also need to clear the non-m ultisampled buffer too. | 594 // The multisample fbo was just cleared, but we also need to clear the non-m ultisampled buffer too. |
| 587 if (m_multisampleFBO) { | 595 if (m_multisampleFBO) { |
| 588 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); | 596 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| 589 m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); | 597 m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 // Clamp if the desired size is greater than the maximum texture size for th e device. | 649 // Clamp if the desired size is greater than the maximum texture size for th e device. |
| 642 int maxTextureSize = 0; | 650 int maxTextureSize = 0; |
| 643 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize) ; | 651 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize) ; |
| 644 if (adjustedSize.height() > maxTextureSize) | 652 if (adjustedSize.height() > maxTextureSize) |
| 645 adjustedSize.setHeight(maxTextureSize); | 653 adjustedSize.setHeight(maxTextureSize); |
| 646 | 654 |
| 647 if (adjustedSize.width() > maxTextureSize) | 655 if (adjustedSize.width() > maxTextureSize) |
| 648 adjustedSize.setWidth(maxTextureSize); | 656 adjustedSize.setWidth(maxTextureSize); |
| 649 | 657 |
| 650 // Try progressively smaller sizes until we find a size that fits or reach a scale limit. | 658 // Try progressively smaller sizes until we find a size that fits or reach a scale limit. |
| 659 int scaleAttempts = 0; | |
| 651 while ((s_currentResourceUsePixels + pixelDelta(adjustedSize)) > s_maximumRe sourceUsePixels) { | 660 while ((s_currentResourceUsePixels + pixelDelta(adjustedSize)) > s_maximumRe sourceUsePixels) { |
| 661 scaleAttempts++; | |
| 662 if(s_maxScaleAttempts > -1 && scaleAttempts > s_maxScaleAttempts) | |
|
Ken Russell (switch to Gerrit)
2013/04/24 01:30:57
Is it strictly necessary to look for s_maxScaleAtt
bajones
2013/04/24 03:37:08
I swear I WILL remember this style rule eventually
| |
| 663 return IntSize(); | |
| 664 | |
| 652 adjustedSize.scale(s_resourceAdjustedRatio); | 665 adjustedSize.scale(s_resourceAdjustedRatio); |
| 653 | 666 |
| 654 if (adjustedSize.isEmpty()) | 667 if (adjustedSize.isEmpty()) |
| 655 return IntSize(); | 668 return IntSize(); |
| 656 } | 669 } |
| 670 | |
| 671 return adjustedSize; | |
| 672 } | |
| 673 | |
| 674 IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool& evictContext) { | |
| 675 IntSize adjustedSize = adjustSize(size); | |
| 676 if(!adjustedSize.isEmpty()) { | |
| 677 evictContext = false; | |
| 678 return adjustedSize; // Buffer fits without evicting a context | |
|
Ken Russell (switch to Gerrit)
2013/04/24 01:30:57
Please end comments in with periods here and throu
bajones
2013/04/24 03:37:08
This one too. Years of habit working against me. *
| |
| 679 } | |
| 680 | |
| 681 // Speculatively adjust the pixel budget to see if the buffer would fit shou ld the oldest context be evicted | |
| 682 IntSize oldestSize = m_contextEvictionManager->oldestContextSize(); | |
| 683 int pixelDelta = oldestSize.width() * oldestSize.height(); | |
| 684 | |
| 685 s_currentResourceUsePixels -= pixelDelta; | |
| 686 adjustedSize = adjustSize(size); | |
| 687 s_currentResourceUsePixels += pixelDelta; | |
| 688 | |
| 689 evictContext = !adjustedSize.isEmpty(); | |
| 657 return adjustedSize; | 690 return adjustedSize; |
| 658 } | 691 } |
| 659 | 692 |
| 660 void DrawingBuffer::reset(const IntSize& newSize) | 693 void DrawingBuffer::reset(const IntSize& newSize) |
| 661 { | 694 { |
| 662 IntSize adjustedSize = adjustSize(newSize); | 695 IntSize adjustedSize; |
| 696 bool evictContext = false; | |
| 697 bool isNewContext = m_size.isEmpty(); | |
| 698 if (s_allowContextEvictionOnCreate && isNewContext) | |
| 699 adjustedSize = adjustSizeWithContextEviction(newSize, evictContext); | |
| 700 else | |
| 701 adjustedSize = adjustSize(newSize); | |
| 702 | |
| 663 if (adjustedSize.isEmpty()) | 703 if (adjustedSize.isEmpty()) |
| 664 return; | 704 return; |
| 665 | 705 |
| 706 if (evictContext) | |
| 707 m_contextEvictionManager->forciblyLoseOldestContext(); | |
| 708 | |
| 666 if (adjustedSize != m_size) { | 709 if (adjustedSize != m_size) { |
| 667 do { | 710 do { |
| 668 // resize multisample FBO | 711 // resize multisample FBO |
| 669 if (!resizeMultisampleFramebuffer(adjustedSize) || !resizeFramebuffe r(adjustedSize)) { | 712 if (!resizeMultisampleFramebuffer(adjustedSize) || !resizeFramebuffe r(adjustedSize)) { |
| 670 adjustedSize.scale(s_resourceAdjustedRatio); | 713 adjustedSize.scale(s_resourceAdjustedRatio); |
| 671 continue; | 714 continue; |
| 672 } | 715 } |
| 673 | 716 |
| 674 #if OS(DARWIN) | 717 #if OS(DARWIN) |
| 675 // FIXME: This can be removed once renderbufferStorageMultisample st arts reporting GL_OUT_OF_MEMORY properly on OSX. | 718 // FIXME: This can be removed once renderbufferStorageMultisample st arts reporting GL_OUT_OF_MEMORY properly on OSX. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 752 | 795 |
| 753 void DrawingBuffer::bind() | 796 void DrawingBuffer::bind() |
| 754 { | 797 { |
| 755 if (!m_context) | 798 if (!m_context) |
| 756 return; | 799 return; |
| 757 | 800 |
| 758 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); | 801 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); |
| 759 } | 802 } |
| 760 | 803 |
| 761 } // namespace WebCore | 804 } // namespace WebCore |
| OLD | NEW |