| 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 |