[chromium] Replace destRect with destOffset in texture upload
[WebKit-https.git] / Source / WebKit / chromium / tests / CCResourceProviderTest.cpp
1 /*
2  * Copyright (C) 2012 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
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCResourceProvider.h"
28
29 #include "CompositorFakeWebGraphicsContext3D.h"
30 #include "Extensions3DChromium.h"
31 #include "FakeWebCompositorOutputSurface.h"
32 #include "cc/CCGraphicsContext.h"
33 #include "cc/CCSingleThreadProxy.h" // For DebugScopedSetImplThread
34 #include <gtest/gtest.h>
35 #include <public/WebGraphicsContext3D.h>
36 #include <wtf/HashMap.h>
37 #include <wtf/OwnArrayPtr.h>
38 #include <wtf/OwnPtr.h>
39
40 using namespace WebCore;
41 using namespace WebKit;
42
43 namespace {
44
45 class ResourceProviderContext : public CompositorFakeWebGraphicsContext3D {
46 public:
47     static PassOwnPtr<ResourceProviderContext> create() { return adoptPtr(new ResourceProviderContext(Attributes())); }
48
49     virtual void bindTexture(WGC3Denum target, WebGLId texture)
50     {
51       ASSERT(target == GraphicsContext3D::TEXTURE_2D);
52       ASSERT(!texture || m_textures.find(texture) != m_textures.end());
53       m_currentTexture = texture;
54     }
55
56     virtual WebGLId createTexture()
57     {
58         WebGLId id = CompositorFakeWebGraphicsContext3D::createTexture();
59         m_textures.add(id, nullptr);
60         return id;
61     }
62
63     virtual void deleteTexture(WebGLId id)
64     {
65         TextureMap::iterator it = m_textures.find(id);
66         ASSERT(it != m_textures.end());
67         m_textures.remove(it);
68         if (m_currentTexture == id)
69             m_currentTexture = 0;
70     }
71
72     virtual void texStorage2DEXT(WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat,
73                                  WGC3Dint width, WGC3Dint height)
74     {
75         ASSERT(m_currentTexture);
76         ASSERT(target == GraphicsContext3D::TEXTURE_2D);
77         ASSERT(levels == 1);
78         WGC3Denum format = GraphicsContext3D::RGBA;
79         switch (internalformat) {
80         case Extensions3D::RGBA8_OES:
81             break;
82         case Extensions3DChromium::BGRA8_EXT:
83             format = Extensions3D::BGRA_EXT;
84             break;
85         default:
86             ASSERT_NOT_REACHED();
87         }
88         allocateTexture(IntSize(width, height), format);
89     }
90
91     virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format, WGC3Denum type, const void* pixels)
92     {
93         ASSERT(m_currentTexture);
94         ASSERT(target == GraphicsContext3D::TEXTURE_2D);
95         ASSERT(!level);
96         ASSERT(internalformat == format);
97         ASSERT(!border);
98         ASSERT(type == GraphicsContext3D::UNSIGNED_BYTE);
99         allocateTexture(IntSize(width, height), format);
100         if (pixels)
101             setPixels(0, 0, width, height, pixels);
102     }
103
104     virtual void texSubImage2D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3Denum type, const void* pixels)
105     {
106         ASSERT(m_currentTexture);
107         ASSERT(target == GraphicsContext3D::TEXTURE_2D);
108         ASSERT(!level);
109         ASSERT(m_textures.get(m_currentTexture));
110         ASSERT(m_textures.get(m_currentTexture)->format == format);
111         ASSERT(type == GraphicsContext3D::UNSIGNED_BYTE);
112         ASSERT(pixels);
113         setPixels(xoffset, yoffset, width, height, pixels);
114     }
115
116     void getPixels(const IntSize& size, WGC3Denum format, uint8_t* pixels)
117     {
118         ASSERT(m_currentTexture);
119         Texture* texture = m_textures.get(m_currentTexture);
120         ASSERT(texture);
121         ASSERT(texture->size == size);
122         ASSERT(texture->format == format);
123         memcpy(pixels, texture->data.get(), textureSize(size, format));
124     }
125
126     int textureCount()
127     {
128         return m_textures.size();
129     }
130
131     static size_t textureSize(const IntSize& size, WGC3Denum format)
132     {
133         unsigned int componentsPerPixel = 4;
134         unsigned int bytesPerComponent = 1;
135         GraphicsContext3D::computeFormatAndTypeParameters(format, GraphicsContext3D::UNSIGNED_BYTE, &componentsPerPixel, &bytesPerComponent);
136         return size.width() * size.height() * componentsPerPixel * bytesPerComponent;
137     }
138
139 protected:
140     explicit ResourceProviderContext(const Attributes& attrs)
141         : CompositorFakeWebGraphicsContext3D(attrs)
142         , m_currentTexture(0)
143     { }
144
145 private:
146     struct Texture {
147         Texture(const IntSize& size_, WGC3Denum format_)
148             : size(size_)
149             , format(format_)
150             , data(adoptArrayPtr(new uint8_t[textureSize(size, format)]))
151         {
152         }
153
154         IntSize size;
155         WGC3Denum format;
156         OwnArrayPtr<uint8_t> data;
157     };
158
159     void allocateTexture(const IntSize& size, WGC3Denum format)
160     {
161         ASSERT(m_currentTexture);
162         m_textures.set(m_currentTexture, adoptPtr(new Texture(size, format)));
163     }
164
165     void setPixels(int xoffset, int yoffset, int width, int height, const void* pixels)
166     {
167         ASSERT(m_currentTexture);
168         Texture* texture = m_textures.get(m_currentTexture);
169         ASSERT(texture);
170         ASSERT(xoffset >= 0 && xoffset+width <= texture->size.width());
171         ASSERT(yoffset >= 0 && yoffset+height <= texture->size.height());
172         ASSERT(pixels);
173         size_t inPitch = textureSize(IntSize(width, 1), texture->format);
174         size_t outPitch = textureSize(IntSize(texture->size.width(), 1), texture->format);
175         uint8_t* dest = texture->data.get() + yoffset * outPitch + textureSize(IntSize(xoffset, 1), texture->format);
176         const uint8_t* src = static_cast<const uint8_t*>(pixels);
177         for (int i = 0; i < height; ++i) {
178             memcpy(dest, src, inPitch);
179             dest += outPitch;
180             src += inPitch;
181         }
182     }
183
184     typedef HashMap<WebGLId, OwnPtr<Texture> > TextureMap;
185     WebGLId m_currentTexture;
186     TextureMap m_textures;
187 };
188
189 class CCResourceProviderTest : public testing::Test {
190 public:
191     CCResourceProviderTest()
192         : m_context(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create()))
193         , m_resourceProvider(CCResourceProvider::create(m_context.get()))
194     {
195     }
196
197     ResourceProviderContext* context() { return static_cast<ResourceProviderContext*>(m_context->context3D()); }
198
199     void getResourcePixels(CCResourceProvider::ResourceId id, const IntSize& size, WGC3Denum format, uint8_t* pixels)
200     {
201         CCScopedLockResourceForRead lock(m_resourceProvider.get(), id);
202         ASSERT_NE(0U, lock.textureId());
203         context()->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
204         context()->getPixels(size, format, pixels);
205     }
206
207 protected:
208     DebugScopedSetImplThread implThread;
209     OwnPtr<CCGraphicsContext> m_context;
210     OwnPtr<CCResourceProvider> m_resourceProvider;
211 };
212
213 TEST_F(CCResourceProviderTest, Basic)
214 {
215     IntSize size(1, 1);
216     WGC3Denum format = GraphicsContext3D::RGBA;
217     int pool = 1;
218     size_t pixelSize = ResourceProviderContext::textureSize(size, format);
219     ASSERT_EQ(4U, pixelSize);
220
221     CCResourceProvider::ResourceId id = m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
222     EXPECT_EQ(1, context()->textureCount());
223
224     uint8_t data[4] = {1, 2, 3, 4};
225     IntRect rect(IntPoint(), size);
226     m_resourceProvider->upload(id, data, rect, rect, IntSize());
227
228     uint8_t result[4] = {0};
229     getResourcePixels(id, size, format, result);
230     EXPECT_EQ(0, memcmp(data, result, pixelSize));
231
232     m_resourceProvider->deleteResource(id);
233     EXPECT_EQ(0, context()->textureCount());
234 }
235
236 TEST_F(CCResourceProviderTest, DeleteOwnedResources)
237 {
238     IntSize size(1, 1);
239     WGC3Denum format = GraphicsContext3D::RGBA;
240     int pool = 1;
241
242     const int count = 3;
243     for (int i = 0; i < count; ++i)
244         m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
245     EXPECT_EQ(3, context()->textureCount());
246
247     m_resourceProvider->deleteOwnedResources(pool+1);
248     EXPECT_EQ(3, context()->textureCount());
249
250     m_resourceProvider->deleteOwnedResources(pool);
251     EXPECT_EQ(0, context()->textureCount());
252 }
253
254 TEST_F(CCResourceProviderTest, Upload)
255 {
256     IntSize size(2, 2);
257     WGC3Denum format = GraphicsContext3D::RGBA;
258     int pool = 1;
259     size_t pixelSize = ResourceProviderContext::textureSize(size, format);
260     ASSERT_EQ(16U, pixelSize);
261
262     CCResourceProvider::ResourceId id = m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
263
264     uint8_t image[16] = {0};
265     IntRect imageRect(IntPoint(), size);
266     m_resourceProvider->upload(id, image, imageRect, imageRect, IntSize());
267
268     for (uint8_t i = 0 ; i < pixelSize; ++i)
269         image[i] = i;
270
271     uint8_t result[16] = {0};
272     {
273         IntRect sourceRect(0, 0, 1, 1);
274         IntSize destOffset(0, 0);
275         m_resourceProvider->upload(id, image, imageRect, sourceRect, destOffset);
276
277         uint8_t expected[16] = {0, 1, 2, 3,   0, 0, 0, 0,
278                                 0, 0, 0, 0,   0, 0, 0, 0};
279         getResourcePixels(id, size, format, result);
280         EXPECT_EQ(0, memcmp(expected, result, pixelSize));
281     }
282     {
283         IntRect sourceRect(0, 0, 1, 1);
284         IntSize destOffset(1, 1);
285         m_resourceProvider->upload(id, image, imageRect, sourceRect, destOffset);
286
287         uint8_t expected[16] = {0, 1, 2, 3,   0, 0, 0, 0,
288                                 0, 0, 0, 0,   0, 1, 2, 3};
289         getResourcePixels(id, size, format, result);
290         EXPECT_EQ(0, memcmp(expected, result, pixelSize));
291     }
292     {
293         IntRect sourceRect(1, 0, 1, 1);
294         IntSize destOffset(0, 1);
295         m_resourceProvider->upload(id, image, imageRect, sourceRect, destOffset);
296
297         uint8_t expected[16] = {0, 1, 2, 3,   0, 0, 0, 0,
298                                 4, 5, 6, 7,   0, 1, 2, 3};
299         getResourcePixels(id, size, format, result);
300         EXPECT_EQ(0, memcmp(expected, result, pixelSize));
301     }
302
303     m_resourceProvider->deleteResource(id);
304 }
305
306 } // namespace