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