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

Side by Side Diff: Source/core/platform/graphics/gpu/DrawingBuffer.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
« no previous file with comments | « Source/core/platform/graphics/gpu/DrawingBuffer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, PassRefPtr<ContextEvictionManag er> contextEvictionManager)
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 PassRefPtr<ContextEvictionManager> contextEvictionM anager)
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
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();
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 {
464 unsigned offscreenColorTexture = m_context->createTexture(); 470 unsigned offscreenColorTexture = m_context->createTexture();
465 if (!offscreenColorTexture) 471 if (!offscreenColorTexture)
466 return 0; 472 return 0;
467 473
468 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture) ; 474 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture) ;
469 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); 475 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
470 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); 476 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
471 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); 477 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
472 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); 478 m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T EXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
473 if(!size.isEmpty()) 479 if (!size.isEmpty())
474 m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_in ternalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContex t3D::UNSIGNED_BYTE); 480 m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_in ternalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContex t3D::UNSIGNED_BYTE);
475 481
476 return offscreenColorTexture; 482 return offscreenColorTexture;
477 } 483 }
478 484
479 void DrawingBuffer::createSecondaryBuffers() 485 void DrawingBuffer::createSecondaryBuffers()
480 { 486 {
481 // create a multisample FBO 487 // create a multisample FBO
482 if (multisample()) { 488 if (multisample()) {
483 m_multisampleFBO = m_context->createFramebuffer(); 489 m_multisampleFBO = m_context->createFramebuffer();
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 (scaleAttempts > s_maxScaleAttempts)
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.
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("WARNING: WebGL cont exts have exceeded the maximum allowed backbuffer area. Oldest context will be l ost.");
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
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
OLDNEW
« no previous file with comments | « Source/core/platform/graphics/gpu/DrawingBuffer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698