1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 33 #include "platform/graphics/gpu/DrawingBuffer.h" 34 35 #include "platform/graphics/GraphicsContext3D.h" 36 #include "platform/graphics/ImageBuffer.h" 37 #include "platform/graphics/UnacceleratedImageBufferSurface.h" 38 #include "public/platform/Platform.h" 39 #include "public/platform/WebExternalTextureMailbox.h" 40 #include "web/tests/MockWebGraphicsContext3D.h" 41 #include "wtf/RefPtr.h" 42 43 #include <gmock/gmock.h> 44 #include <gtest/gtest.h> 45 46 using namespace WebCore; 47 using namespace blink; 48 using testing::Test; 49 using testing::_; 50 51 namespace { 52 53 class FakeContextEvictionManager : public ContextEvictionManager { 54 public: 55 void forciblyLoseOldestContext(const String& reason) { } 56 IntSize oldestContextSize() { return IntSize(); } 57 }; 58 59 class WebGraphicsContext3DForTests : public MockWebGraphicsContext3D { 60 public: 61 WebGraphicsContext3DForTests() 62 : MockWebGraphicsContext3D() 63 , m_boundTexture(0) 64 , m_currentMailboxByte(0) { } 65 66 virtual void bindTexture(WGC3Denum target, WebGLId texture) 67 { 68 if (target == GL_TEXTURE_2D) { 69 m_boundTexture = texture; 70 } 71 } 72 73 virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format, WGC3Denum type, const void* pixels) 74 { 75 if (target == GL_TEXTURE_2D && !level) { 76 m_textureSizes.set(m_boundTexture, IntSize(width, height)); 77 } 78 } 79 80 virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox) 81 { 82 ++m_currentMailboxByte; 83 WebExternalTextureMailbox temp; 84 memset(mailbox, m_currentMailboxByte, sizeof(temp.name)); 85 } 86 87 virtual void produceTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox) 88 { 89 ASSERT_EQ(target, static_cast<WGC3Denum>(GL_TEXTURE_2D)); 90 m_mostRecentlyProducedSize = m_textureSizes.get(m_boundTexture); 91 } 92 93 IntSize mostRecentlyProducedSize() 94 { 95 return m_mostRecentlyProducedSize; 96 } 97 98 private: 99 WebGLId m_boundTexture; 100 HashMap<WebGLId, IntSize> m_textureSizes; 101 WGC3Dbyte m_currentMailboxByte; 102 IntSize m_mostRecentlyProducedSize; 103 }; 104 105 static const int initialWidth = 100; 106 static const int initialHeight = 100; 107 static const int alternateHeight = 50; 108 109 } // namespace 110 111 class DrawingBufferTest : public Test { 112 protected: 113 virtual void SetUp() 114 { 115 RefPtr<FakeContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager()); 116 RefPtr<GraphicsContext3D> context = GraphicsContext3D::createGraphicsContextFromWebContext(adoptPtr(new WebGraphicsContext3DForTests)); 117 m_drawingBuffer = DrawingBuffer::create(context.get(), IntSize(initialWidth, initialHeight), DrawingBuffer::Discard, contextEvictionManager.release()); 118 } 119 120 WebGraphicsContext3DForTests* webContext() 121 { 122 return static_cast<WebGraphicsContext3DForTests*>(m_drawingBuffer->context()); 123 } 124 125 RefPtr<DrawingBuffer> m_drawingBuffer; 126 }; 127 128 namespace { 129 130 TEST_F(DrawingBufferTest, verifyNoNewBuffersAfterContextLostWithMailboxes) 131 { 132 // Tell the buffer its contents changed and context was lost. 133 m_drawingBuffer->markContentsChanged(); 134 m_drawingBuffer->releaseResources(); 135 136 blink::WebExternalTextureMailbox mailbox; 137 EXPECT_FALSE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); 138 } 139 140 TEST_F(DrawingBufferTest, verifyResizingProperlyAffectsMailboxes) 141 { 142 blink::WebExternalTextureMailbox mailbox; 143 144 IntSize initialSize(initialWidth, initialHeight); 145 IntSize alternateSize(initialWidth, alternateHeight); 146 147 // Produce one mailbox at size 100x100. 148 m_drawingBuffer->markContentsChanged(); 149 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); 150 EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); 151 152 // Resize to 100x50. 153 m_drawingBuffer->reset(IntSize(initialWidth, alternateHeight)); 154 m_drawingBuffer->mailboxReleased(mailbox); 155 156 // Produce a mailbox at this size. 157 m_drawingBuffer->markContentsChanged(); 158 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); 159 EXPECT_EQ(alternateSize, webContext()->mostRecentlyProducedSize()); 160 161 // Reset to initial size. 162 m_drawingBuffer->reset(IntSize(initialWidth, initialHeight)); 163 m_drawingBuffer->mailboxReleased(mailbox); 164 165 // Prepare another mailbox and verify that it's the correct size. 166 m_drawingBuffer->markContentsChanged(); 167 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); 168 EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); 169 170 // Prepare one final mailbox and verify that it's the correct size. 171 m_drawingBuffer->mailboxReleased(mailbox); 172 m_drawingBuffer->markContentsChanged(); 173 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); 174 EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); 175 } 176 177 } // namespace 178