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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #ifndef NDEBUG | 47 #ifndef NDEBUG |
48 #include "wtf/RefCountedLeakCounter.h" | 48 #include "wtf/RefCountedLeakCounter.h" |
49 #endif | 49 #endif |
50 | 50 |
51 namespace blink { | 51 namespace blink { |
52 | 52 |
53 namespace { | 53 namespace { |
54 | 54 |
55 const float s_resourceAdjustedRatio = 0.5; | 55 const float s_resourceAdjustedRatio = 0.5; |
56 | 56 |
57 // Drawing buffers with more pixels than this will be explicitly checked for out
of memory errors upon creation | |
58 const int s_largeBufferSize = 4096 * 4096; | |
59 | |
60 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, drawingBufferCounter, ("Dra
wingBuffer")); | 57 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, drawingBufferCounter, ("Dra
wingBuffer")); |
61 | 58 |
62 class ScopedTextureUnit0BindingRestorer { | 59 class ScopedTextureUnit0BindingRestorer { |
63 public: | 60 public: |
64 ScopedTextureUnit0BindingRestorer(WebGraphicsContext3D* context, GLenum acti
veTextureUnit, Platform3DObject textureUnitZeroId) | 61 ScopedTextureUnit0BindingRestorer(WebGraphicsContext3D* context, GLenum acti
veTextureUnit, Platform3DObject textureUnitZeroId) |
65 : m_context(context) | 62 : m_context(context) |
66 , m_oldActiveTextureUnit(activeTextureUnit) | 63 , m_oldActiveTextureUnit(activeTextureUnit) |
67 , m_oldTextureUnitZeroId(textureUnitZeroId) | 64 , m_oldTextureUnitZeroId(textureUnitZeroId) |
68 { | 65 { |
69 m_context->activeTexture(GL_TEXTURE0); | 66 m_context->activeTexture(GL_TEXTURE0); |
70 } | 67 } |
71 ~ScopedTextureUnit0BindingRestorer() | 68 ~ScopedTextureUnit0BindingRestorer() |
72 { | 69 { |
73 m_context->bindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId); | 70 m_context->bindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId); |
74 m_context->activeTexture(m_oldActiveTextureUnit); | 71 m_context->activeTexture(m_oldActiveTextureUnit); |
75 } | 72 } |
76 | 73 |
77 private: | 74 private: |
78 WebGraphicsContext3D* m_context; | 75 WebGraphicsContext3D* m_context; |
79 GLenum m_oldActiveTextureUnit; | 76 GLenum m_oldActiveTextureUnit; |
80 Platform3DObject m_oldTextureUnitZeroId; | 77 Platform3DObject m_oldTextureUnitZeroId; |
81 }; | 78 }; |
82 | 79 |
83 class ScopedConditionalErrorCache { | |
84 public: | |
85 ScopedConditionalErrorCache(WebGraphicsContext3D* context, bool active) | |
86 : m_context(context) | |
87 , m_active(active) | |
88 { | |
89 if (m_active) { | |
90 GLenum error = m_context->getError(); | |
91 int i = 0; | |
92 for (; i < 100 && error != GL_NO_ERROR; ++i) { | |
93 m_cachedErrors.append(error); | |
94 error = m_context->getError(); | |
95 } | |
96 ASSERT(i < 100); | |
97 } | |
98 } | |
99 | |
100 ~ScopedConditionalErrorCache() | |
101 { | |
102 while (m_cachedErrors.size()) { | |
103 m_context->synthesizeGLError(m_cachedErrors.first()); | |
104 m_cachedErrors.remove(0); | |
105 } | |
106 } | |
107 | |
108 bool consumeErrorIf(GLenum error) | |
109 { | |
110 if (m_active) { | |
111 GLenum nextError = m_context->getError(); | |
112 if (error == GL_NO_ERROR) | |
113 return false; | |
114 | |
115 if (nextError == error) | |
116 return true; | |
117 | |
118 m_cachedErrors.append(nextError); | |
119 } | |
120 return false; | |
121 } | |
122 | |
123 private: | |
124 WebGraphicsContext3D* m_context; | |
125 bool m_active; | |
126 Vector<GLenum> m_cachedErrors; | |
127 }; | |
128 | |
129 bool isLargeBuffer(const IntSize& size) | |
130 { | |
131 return s_largeBufferSize <= size.width() * size.height(); | |
132 } | |
133 | |
134 } // namespace | 80 } // namespace |
135 | 81 |
136 PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<WebGraphicsContext3D>
context, const IntSize& size, PreserveDrawingBuffer preserve, WebGraphicsContex
t3D::Attributes requestedAttributes) | 82 PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<WebGraphicsContext3D>
context, const IntSize& size, PreserveDrawingBuffer preserve, WebGraphicsContex
t3D::Attributes requestedAttributes) |
137 { | 83 { |
138 ASSERT(context); | 84 ASSERT(context); |
139 OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.g
et()); | 85 OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.g
et()); |
140 if (!extensionsUtil) { | 86 if (!extensionsUtil) { |
141 // This might be the first time we notice that the WebGraphicsContext3D
is lost. | 87 // This might be the first time we notice that the WebGraphicsContext3D
is lost. |
142 return nullptr; | 88 return nullptr; |
143 } | 89 } |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 } | 613 } |
668 } | 614 } |
669 | 615 |
670 bool DrawingBuffer::resizeFramebuffer(const IntSize& size) | 616 bool DrawingBuffer::resizeFramebuffer(const IntSize& size) |
671 { | 617 { |
672 // resize regular FBO | 618 // resize regular FBO |
673 m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); | 619 m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); |
674 | 620 |
675 m_context->bindTexture(GL_TEXTURE_2D, m_colorBuffer.textureId); | 621 m_context->bindTexture(GL_TEXTURE_2D, m_colorBuffer.textureId); |
676 | 622 |
677 if (!allocateTextureMemory(&m_colorBuffer, size)) | 623 allocateTextureMemory(&m_colorBuffer, size); |
678 return false; | |
679 | 624 |
680 if (m_multisampleMode == ImplicitResolve) | 625 if (m_multisampleMode == ImplicitResolve) |
681 m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_A
TTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount); | 626 m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_A
TTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount); |
682 else | 627 else |
683 m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL
_TEXTURE_2D, m_colorBuffer.textureId, 0); | 628 m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL
_TEXTURE_2D, m_colorBuffer.textureId, 0); |
684 | 629 |
685 m_context->bindTexture(GL_TEXTURE_2D, 0); | 630 m_context->bindTexture(GL_TEXTURE_2D, 0); |
686 | 631 |
687 if (m_multisampleMode != ExplicitResolve) { | 632 if (m_multisampleMode != ExplicitResolve) |
688 if (!resizeDepthStencil(size)) | 633 resizeDepthStencil(size); |
689 return false; | |
690 } | |
691 if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMP
LETE) | 634 if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMP
LETE) |
692 return false; | 635 return false; |
693 | 636 |
694 return true; | 637 return true; |
695 } | 638 } |
696 | 639 |
697 bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size) | 640 bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size) |
698 { | 641 { |
699 if (m_multisampleMode == ExplicitResolve) { | 642 if (m_multisampleMode == ExplicitResolve) { |
700 ScopedConditionalErrorCache errorCache(m_context.get(), isLargeBuffer(si
ze)); | |
701 | |
702 m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); | 643 m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); |
703 | 644 |
704 m_context->bindRenderbuffer(GL_RENDERBUFFER, m_multisampleColorBuffer); | 645 m_context->bindRenderbuffer(GL_RENDERBUFFER, m_multisampleColorBuffer); |
705 m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sam
pleCount, m_internalRenderbufferFormat, size.width(), size.height()); | 646 m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sam
pleCount, m_internalRenderbufferFormat, size.width(), size.height()); |
706 | 647 |
707 if (errorCache.consumeErrorIf(GL_OUT_OF_MEMORY)) | 648 if (m_context->getError() == GL_OUT_OF_MEMORY) |
708 return false; | 649 return false; |
709 | 650 |
710 m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, m_multisampleColorBuffer); | 651 m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, m_multisampleColorBuffer); |
711 if (!resizeDepthStencil(size)) | 652 resizeDepthStencil(size); |
712 return false; | |
713 if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_
COMPLETE) | 653 if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_
COMPLETE) |
714 return false; | 654 return false; |
715 } | 655 } |
716 | 656 |
717 return true; | 657 return true; |
718 } | 658 } |
719 | 659 |
720 bool DrawingBuffer::resizeDepthStencil(const IntSize& size) | 660 void DrawingBuffer::resizeDepthStencil(const IntSize& size) |
721 { | 661 { |
722 if (!m_requestedAttributes.depth && !m_requestedAttributes.stencil) | 662 if (!m_requestedAttributes.depth && !m_requestedAttributes.stencil) |
723 return true; | 663 return; |
724 | |
725 ScopedConditionalErrorCache errorCache(m_context.get(), isLargeBuffer(size))
; | |
726 | 664 |
727 if (m_packedDepthStencilExtensionSupported) { | 665 if (m_packedDepthStencilExtensionSupported) { |
728 if (!m_depthStencilBuffer) | 666 if (!m_depthStencilBuffer) |
729 m_depthStencilBuffer = m_context->createRenderbuffer(); | 667 m_depthStencilBuffer = m_context->createRenderbuffer(); |
730 m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); | 668 m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); |
731 if (m_multisampleMode == ImplicitResolve) | 669 if (m_multisampleMode == ImplicitResolve) |
732 m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_samp
leCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); | 670 m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_samp
leCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); |
733 else if (m_multisampleMode == ExplicitResolve) | 671 else if (m_multisampleMode == ExplicitResolve) |
734 m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m
_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); | 672 m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m
_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); |
735 else | 673 else |
(...skipping 20 matching lines...) Expand all Loading... |
756 if (m_multisampleMode == ImplicitResolve) | 694 if (m_multisampleMode == ImplicitResolve) |
757 m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_
sampleCount, GL_STENCIL_INDEX8, size.width(), size.height()); | 695 m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_
sampleCount, GL_STENCIL_INDEX8, size.width(), size.height()); |
758 else if (m_multisampleMode == ExplicitResolve) | 696 else if (m_multisampleMode == ExplicitResolve) |
759 m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFE
R, m_sampleCount, GL_STENCIL_INDEX8, size.width(), size.height()); | 697 m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFE
R, m_sampleCount, GL_STENCIL_INDEX8, size.width(), size.height()); |
760 else | 698 else |
761 m_context->renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX
8, size.width(), size.height()); | 699 m_context->renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX
8, size.width(), size.height()); |
762 m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACH
MENT, GL_RENDERBUFFER, m_stencilBuffer); | 700 m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACH
MENT, GL_RENDERBUFFER, m_stencilBuffer); |
763 } | 701 } |
764 } | 702 } |
765 m_context->bindRenderbuffer(GL_RENDERBUFFER, 0); | 703 m_context->bindRenderbuffer(GL_RENDERBUFFER, 0); |
766 | |
767 if (errorCache.consumeErrorIf(GL_OUT_OF_MEMORY)) | |
768 return false; | |
769 | |
770 return true; | |
771 } | 704 } |
772 | 705 |
773 | 706 |
774 | 707 |
775 void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) | 708 void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) |
776 { | 709 { |
777 // We will clear the multisample FBO, but we also need to clear the non-mult
isampled buffer. | 710 // We will clear the multisample FBO, but we also need to clear the non-mult
isampled buffer. |
778 if (m_multisampleFBO) { | 711 if (m_multisampleFBO) { |
779 m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); | 712 m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); |
780 m_context->clear(GL_COLOR_BUFFER_BIT); | 713 m_context->clear(GL_COLOR_BUFFER_BIT); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 memcpy(rowA, scanline, rowBytes); | 956 memcpy(rowA, scanline, rowBytes); |
1024 } | 957 } |
1025 } | 958 } |
1026 | 959 |
1027 void DrawingBuffer::texImage2DResourceSafe(GLenum target, GLint level, GLenum in
ternalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum
type, GLint unpackAlignment) | 960 void DrawingBuffer::texImage2DResourceSafe(GLenum target, GLint level, GLenum in
ternalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum
type, GLint unpackAlignment) |
1028 { | 961 { |
1029 ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4
|| unpackAlignment == 8); | 962 ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4
|| unpackAlignment == 8); |
1030 m_context->texImage2D(target, level, internalformat, width, height, border,
format, type, 0); | 963 m_context->texImage2D(target, level, internalformat, width, height, border,
format, type, 0); |
1031 } | 964 } |
1032 | 965 |
1033 bool DrawingBuffer::allocateTextureMemory(TextureInfo* info, const IntSize& size
) | 966 void DrawingBuffer::allocateTextureMemory(TextureInfo* info, const IntSize& size
) |
1034 { | 967 { |
1035 ScopedConditionalErrorCache errorCache(m_context.get(), isLargeBuffer(size))
; | |
1036 | |
1037 if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) { | 968 if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) { |
1038 deleteChromiumImageForTexture(info); | 969 deleteChromiumImageForTexture(info); |
1039 | 970 |
1040 info->imageId = m_context->createGpuMemoryBufferImageCHROMIUM(size.width
(), size.height(), GL_RGBA, GC3D_SCANOUT_CHROMIUM); | 971 info->imageId = m_context->createGpuMemoryBufferImageCHROMIUM(size.width
(), size.height(), GL_RGBA, GC3D_SCANOUT_CHROMIUM); |
1041 | |
1042 if (errorCache.consumeErrorIf(GL_OUT_OF_MEMORY)) | |
1043 return false; | |
1044 | |
1045 if (info->imageId) { | 972 if (info->imageId) { |
1046 m_context->bindTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId); | 973 m_context->bindTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId); |
1047 return true; | 974 return; |
1048 } | 975 } |
1049 } | 976 } |
1050 | 977 |
1051 texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, size.width()
, size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE); | 978 texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, size.width()
, size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE); |
1052 | |
1053 if (errorCache.consumeErrorIf(GL_OUT_OF_MEMORY)) | |
1054 return false; | |
1055 | |
1056 return true; | |
1057 } | 979 } |
1058 | 980 |
1059 void DrawingBuffer::deleteChromiumImageForTexture(TextureInfo* info) | 981 void DrawingBuffer::deleteChromiumImageForTexture(TextureInfo* info) |
1060 { | 982 { |
1061 if (info->imageId) { | 983 if (info->imageId) { |
1062 m_context->releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId); | 984 m_context->releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId); |
1063 m_context->destroyImageCHROMIUM(info->imageId); | 985 m_context->destroyImageCHROMIUM(info->imageId); |
1064 info->imageId = 0; | 986 info->imageId = 0; |
1065 } | 987 } |
1066 } | 988 } |
1067 | 989 |
1068 } // namespace blink | 990 } // namespace blink |
OLD | NEW |