2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
33 #include "platform/graphics/gpu/DrawingBuffer.h"
35 #include "platform/graphics/ImageBuffer.h"
36 #include "platform/graphics/UnacceleratedImageBufferSurface.h"
37 #include "public/platform/Platform.h"
38 #include "public/platform/WebExternalTextureMailbox.h"
39 #include "web/tests/MockWebGraphicsContext3D.h"
40 #include "wtf/RefPtr.h"
42 #include <gmock/gmock.h>
43 #include <gtest/gtest.h>
45 using namespace WebCore;
46 using namespace blink;
52 class FakeContextEvictionManager : public ContextEvictionManager {
54 void forciblyLoseOldestContext(const String& reason) { }
55 IntSize oldestContextSize() { return IntSize(); }
58 class WebGraphicsContext3DForTests : public MockWebGraphicsContext3D {
60 WebGraphicsContext3DForTests()
61 : MockWebGraphicsContext3D()
63 , m_currentMailboxByte(0) { }
65 virtual void bindTexture(WGC3Denum target, WebGLId texture)
67 if (target == GL_TEXTURE_2D) {
68 m_boundTexture = texture;
72 virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format, WGC3Denum type, const void* pixels)
74 if (target == GL_TEXTURE_2D && !level) {
75 m_textureSizes.set(m_boundTexture, IntSize(width, height));
79 virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox)
81 ++m_currentMailboxByte;
82 WebExternalTextureMailbox temp;
83 memset(mailbox, m_currentMailboxByte, sizeof(temp.name));
86 virtual void produceTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox)
88 ASSERT_EQ(target, static_cast<WGC3Denum>(GL_TEXTURE_2D));
89 m_mostRecentlyProducedSize = m_textureSizes.get(m_boundTexture);
92 IntSize mostRecentlyProducedSize()
94 return m_mostRecentlyProducedSize;
98 WebGLId m_boundTexture;
99 HashMap<WebGLId, IntSize> m_textureSizes;
100 WGC3Dbyte m_currentMailboxByte;
101 IntSize m_mostRecentlyProducedSize;
104 static const int initialWidth = 100;
105 static const int initialHeight = 100;
106 static const int alternateHeight = 50;
110 class DrawingBufferTest : public Test {
114 RefPtr<FakeContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager());
115 m_context = adoptPtr(new WebGraphicsContext3DForTests);
116 m_drawingBuffer = DrawingBuffer::create(m_context.get(), IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve, contextEvictionManager.release());
119 WebGraphicsContext3DForTests* webContext()
121 return m_context.get();
124 OwnPtr<WebGraphicsContext3DForTests> m_context;
125 RefPtr<DrawingBuffer> m_drawingBuffer;
130 TEST_F(DrawingBufferTest, testPaintRenderingResultsToCanvas)
132 OwnPtr<ImageBufferSurface> imageBufferSurface = adoptPtr(new UnacceleratedImageBufferSurface(IntSize(initialWidth, initialHeight)));
133 EXPECT_FALSE(!imageBufferSurface);
134 EXPECT_TRUE(imageBufferSurface->isValid());
135 OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageBufferSurface.release());
136 EXPECT_FALSE(!imageBuffer);
137 EXPECT_FALSE(imageBuffer->isAccelerated());
138 EXPECT_FALSE(imageBuffer->bitmap().isNull());
139 m_drawingBuffer->paintRenderingResultsToCanvas(imageBuffer.get());
140 EXPECT_FALSE(imageBuffer->isAccelerated());
141 EXPECT_FALSE(imageBuffer->bitmap().isNull());
144 TEST_F(DrawingBufferTest, verifyNoNewBuffersAfterContextLostWithMailboxes)
146 // Tell the buffer its contents changed and context was lost.
147 m_drawingBuffer->markContentsChanged();
148 m_drawingBuffer->releaseResources();
150 blink::WebExternalTextureMailbox mailbox;
151 EXPECT_FALSE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
154 TEST_F(DrawingBufferTest, verifyResizingProperlyAffectsMailboxes)
156 blink::WebExternalTextureMailbox mailbox;
158 IntSize initialSize(initialWidth, initialHeight);
159 IntSize alternateSize(initialWidth, alternateHeight);
161 // Produce one mailbox at size 100x100.
162 m_drawingBuffer->markContentsChanged();
163 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
164 EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
167 m_drawingBuffer->reset(IntSize(initialWidth, alternateHeight));
168 m_drawingBuffer->mailboxReleased(mailbox);
170 // Produce a mailbox at this size.
171 m_drawingBuffer->markContentsChanged();
172 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
173 EXPECT_EQ(alternateSize, webContext()->mostRecentlyProducedSize());
175 // Reset to initial size.
176 m_drawingBuffer->reset(IntSize(initialWidth, initialHeight));
177 m_drawingBuffer->mailboxReleased(mailbox);
179 // Prepare another mailbox and verify that it's the correct size.
180 m_drawingBuffer->markContentsChanged();
181 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
182 EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
184 // Prepare one final mailbox and verify that it's the correct size.
185 m_drawingBuffer->mailboxReleased(mailbox);
186 m_drawingBuffer->markContentsChanged();
187 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
188 EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
191 class TextureMailboxWrapper {
193 explicit TextureMailboxWrapper(const blink::WebExternalTextureMailbox& mailbox)
197 bool operator==(const TextureMailboxWrapper& other) const
199 return !memcmp(m_mailbox.name, other.m_mailbox.name, sizeof(m_mailbox.name));
203 blink::WebExternalTextureMailbox m_mailbox;
206 TEST_F(DrawingBufferTest, verifyRecyclingMailboxesByFIFO)
208 blink::WebExternalTextureMailbox mailbox1;
209 blink::WebExternalTextureMailbox mailbox2;
210 blink::WebExternalTextureMailbox mailbox3;
212 IntSize initialSize(initialWidth, initialHeight);
214 // Produce mailboxes.
215 m_drawingBuffer->markContentsChanged();
216 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox1, 0));
217 m_drawingBuffer->markContentsChanged();
218 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox2, 0));
219 m_drawingBuffer->markContentsChanged();
220 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox3, 0));
222 // Release mailboxes by specific order; 2, 3, 1.
223 m_drawingBuffer->markContentsChanged();
224 m_drawingBuffer->mailboxReleased(mailbox2);
225 m_drawingBuffer->markContentsChanged();
226 m_drawingBuffer->mailboxReleased(mailbox3);
227 m_drawingBuffer->markContentsChanged();
228 m_drawingBuffer->mailboxReleased(mailbox1);
230 // The first recycled mailbox must be 2.
231 blink::WebExternalTextureMailbox recycledMailbox;
232 m_drawingBuffer->markContentsChanged();
233 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox, 0));
234 EXPECT_EQ(TextureMailboxWrapper(mailbox2), TextureMailboxWrapper(recycledMailbox));
236 // The second recycled mailbox must be 3.
237 m_drawingBuffer->markContentsChanged();
238 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox, 0));
239 EXPECT_EQ(TextureMailboxWrapper(mailbox3), TextureMailboxWrapper(recycledMailbox));
241 // The third recycled mailbox must be 1.
242 m_drawingBuffer->markContentsChanged();
243 EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox, 0));
244 EXPECT_EQ(TextureMailboxWrapper(mailbox1), TextureMailboxWrapper(recycledMailbox));