summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests/CCResourceProviderTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/chromium/tests/CCResourceProviderTest.cpp')
-rw-r--r--Source/WebKit/chromium/tests/CCResourceProviderTest.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/Source/WebKit/chromium/tests/CCResourceProviderTest.cpp b/Source/WebKit/chromium/tests/CCResourceProviderTest.cpp
new file mode 100644
index 000000000..57165e6ca
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCResourceProviderTest.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "cc/CCResourceProvider.h"
+
+#include "CompositorFakeWebGraphicsContext3D.h"
+#include "Extensions3DChromium.h"
+#include "cc/CCGraphicsContext.h"
+#include "cc/CCSingleThreadProxy.h" // For DebugScopedSetImplThread
+#include <gtest/gtest.h>
+#include <public/WebGraphicsContext3D.h>
+#include <wtf/HashMap.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/OwnPtr.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+namespace {
+
+class ResourceProviderContext : public CompositorFakeWebGraphicsContext3D {
+public:
+ static PassOwnPtr<ResourceProviderContext> create() { return adoptPtr(new ResourceProviderContext(Attributes())); }
+
+ virtual void bindTexture(WGC3Denum target, WebGLId texture)
+ {
+ ASSERT(target == GraphicsContext3D::TEXTURE_2D);
+ ASSERT(!texture || m_textures.find(texture) != m_textures.end());
+ m_currentTexture = texture;
+ }
+
+ virtual WebGLId createTexture()
+ {
+ WebGLId id = CompositorFakeWebGraphicsContext3D::createTexture();
+ m_textures.add(id, nullptr);
+ return id;
+ }
+
+ virtual void deleteTexture(WebGLId id)
+ {
+ TextureMap::iterator it = m_textures.find(id);
+ ASSERT(it != m_textures.end());
+ m_textures.remove(it);
+ if (m_currentTexture == id)
+ m_currentTexture = 0;
+ }
+
+ virtual void texStorage2DEXT(WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat,
+ WGC3Dint width, WGC3Dint height)
+ {
+ ASSERT(m_currentTexture);
+ ASSERT(target == GraphicsContext3D::TEXTURE_2D);
+ ASSERT(levels == 1);
+ WGC3Denum format = GraphicsContext3D::RGBA;
+ switch (internalformat) {
+ case Extensions3D::RGBA8_OES:
+ break;
+ case Extensions3DChromium::BGRA8_EXT:
+ format = Extensions3D::BGRA_EXT;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ allocateTexture(IntSize(width, height), format);
+ }
+
+ virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format, WGC3Denum type, const void* pixels)
+ {
+ ASSERT(m_currentTexture);
+ ASSERT(target == GraphicsContext3D::TEXTURE_2D);
+ ASSERT(!level);
+ ASSERT(internalformat == format);
+ ASSERT(!border);
+ ASSERT(type == GraphicsContext3D::UNSIGNED_BYTE);
+ allocateTexture(IntSize(width, height), format);
+ if (pixels)
+ setPixels(0, 0, width, height, pixels);
+ }
+
+ virtual void texSubImage2D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3Denum type, const void* pixels)
+ {
+ ASSERT(m_currentTexture);
+ ASSERT(target == GraphicsContext3D::TEXTURE_2D);
+ ASSERT(!level);
+ ASSERT(m_textures.get(m_currentTexture));
+ ASSERT(m_textures.get(m_currentTexture)->format == format);
+ ASSERT(type == GraphicsContext3D::UNSIGNED_BYTE);
+ ASSERT(pixels);
+ setPixels(xoffset, yoffset, width, height, pixels);
+ }
+
+ void getPixels(const IntSize& size, WGC3Denum format, uint8_t* pixels)
+ {
+ ASSERT(m_currentTexture);
+ Texture* texture = m_textures.get(m_currentTexture);
+ ASSERT(texture);
+ ASSERT(texture->size == size);
+ ASSERT(texture->format == format);
+ memcpy(pixels, texture->data.get(), textureSize(size, format));
+ }
+
+ int textureCount()
+ {
+ return m_textures.size();
+ }
+
+ static size_t textureSize(const IntSize& size, WGC3Denum format)
+ {
+ unsigned int componentsPerPixel = 4;
+ unsigned int bytesPerComponent = 1;
+ GraphicsContext3D::computeFormatAndTypeParameters(format, GraphicsContext3D::UNSIGNED_BYTE, &componentsPerPixel, &bytesPerComponent);
+ return size.width() * size.height() * componentsPerPixel * bytesPerComponent;
+ }
+
+protected:
+ explicit ResourceProviderContext(const Attributes& attrs)
+ : CompositorFakeWebGraphicsContext3D(attrs)
+ , m_currentTexture(0)
+ { }
+
+private:
+ struct Texture {
+ Texture(const IntSize& size_, WGC3Denum format_)
+ : size(size_)
+ , format(format_)
+ , data(adoptArrayPtr(new uint8_t[textureSize(size, format)]))
+ {
+ }
+
+ IntSize size;
+ WGC3Denum format;
+ OwnArrayPtr<uint8_t> data;
+ };
+
+ void allocateTexture(const IntSize& size, WGC3Denum format)
+ {
+ ASSERT(m_currentTexture);
+ m_textures.set(m_currentTexture, adoptPtr(new Texture(size, format)));
+ }
+
+ void setPixels(int xoffset, int yoffset, int width, int height, const void* pixels)
+ {
+ ASSERT(m_currentTexture);
+ Texture* texture = m_textures.get(m_currentTexture);
+ ASSERT(texture);
+ ASSERT(xoffset >= 0 && xoffset+width <= texture->size.width());
+ ASSERT(yoffset >= 0 && yoffset+height <= texture->size.height());
+ ASSERT(pixels);
+ size_t inPitch = textureSize(IntSize(width, 1), texture->format);
+ size_t outPitch = textureSize(IntSize(texture->size.width(), 1), texture->format);
+ uint8_t* dest = texture->data.get() + yoffset * outPitch + textureSize(IntSize(xoffset, 1), texture->format);
+ const uint8_t* src = static_cast<const uint8_t*>(pixels);
+ for (int i = 0; i < height; ++i) {
+ memcpy(dest, src, inPitch);
+ dest += outPitch;
+ src += inPitch;
+ }
+ }
+
+ typedef HashMap<WebGLId, OwnPtr<Texture> > TextureMap;
+ WebGLId m_currentTexture;
+ TextureMap m_textures;
+};
+
+class CCResourceProviderTest : public testing::Test {
+public:
+ CCResourceProviderTest()
+ : m_context(CCGraphicsContext::create3D(ResourceProviderContext::create()))
+ , m_resourceProvider(CCResourceProvider::create(m_context.get()))
+ {
+ }
+
+ ResourceProviderContext* context() { return static_cast<ResourceProviderContext*>(m_context->context3D()); }
+
+ void getResourcePixels(CCResourceProvider::ResourceId id, const IntSize& size, WGC3Denum format, uint8_t* pixels)
+ {
+ CCScopedLockResourceForRead lock(m_resourceProvider.get(), id);
+ ASSERT_NE(0U, lock.textureId());
+ context()->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
+ context()->getPixels(size, format, pixels);
+ }
+
+protected:
+ DebugScopedSetImplThread implThread;
+ OwnPtr<CCGraphicsContext> m_context;
+ OwnPtr<CCResourceProvider> m_resourceProvider;
+};
+
+TEST_F(CCResourceProviderTest, Basic)
+{
+ IntSize size(1, 1);
+ WGC3Denum format = GraphicsContext3D::RGBA;
+ int pool = 1;
+ size_t pixelSize = ResourceProviderContext::textureSize(size, format);
+ ASSERT_EQ(4U, pixelSize);
+
+ CCResourceProvider::ResourceId id = m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
+ EXPECT_EQ(1, context()->textureCount());
+
+ uint8_t data[4] = {1, 2, 3, 4};
+ IntRect rect(IntPoint(), size);
+ m_resourceProvider->upload(id, data, rect, rect, rect);
+
+ uint8_t result[4] = {0};
+ getResourcePixels(id, size, format, result);
+ EXPECT_EQ(0, memcmp(data, result, pixelSize));
+
+ m_resourceProvider->deleteResource(id);
+ EXPECT_EQ(0, context()->textureCount());
+}
+
+TEST_F(CCResourceProviderTest, DeleteOwnedResources)
+{
+ IntSize size(1, 1);
+ WGC3Denum format = GraphicsContext3D::RGBA;
+ int pool = 1;
+
+ const int count = 3;
+ CCResourceProvider::ResourceId ids[count] = {0};
+ for (int i = 0; i < count; ++i)
+ ids[i] = m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
+ EXPECT_EQ(3, context()->textureCount());
+
+ m_resourceProvider->deleteOwnedResources(pool+1);
+ EXPECT_EQ(3, context()->textureCount());
+
+ m_resourceProvider->deleteOwnedResources(pool);
+ EXPECT_EQ(0, context()->textureCount());
+}
+
+TEST_F(CCResourceProviderTest, Upload)
+{
+ IntSize size(2, 2);
+ WGC3Denum format = GraphicsContext3D::RGBA;
+ int pool = 1;
+ size_t pixelSize = ResourceProviderContext::textureSize(size, format);
+ ASSERT_EQ(16U, pixelSize);
+
+ CCResourceProvider::ResourceId id = m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
+
+ uint8_t image[16] = {0};
+ IntRect imageRect(IntPoint(), size);
+ m_resourceProvider->upload(id, image, imageRect, imageRect, imageRect);
+
+ for (uint8_t i = 0 ; i < pixelSize; ++i)
+ image[i] = i;
+
+ uint8_t result[16] = {0};
+ {
+ IntRect sourceRect(0, 0, 1, 1);
+ IntRect destRect(0, 0, 1, 1);
+ m_resourceProvider->upload(id, image, imageRect, sourceRect, destRect);
+
+ uint8_t expected[16] = {0, 1, 2, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ getResourcePixels(id, size, format, result);
+ EXPECT_EQ(0, memcmp(expected, result, pixelSize));
+ }
+ {
+ IntRect sourceRect(0, 0, 1, 1);
+ IntRect destRect(1, 1, 1, 1);
+ m_resourceProvider->upload(id, image, imageRect, sourceRect, destRect);
+
+ uint8_t expected[16] = {0, 1, 2, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 2, 3};
+ getResourcePixels(id, size, format, result);
+ EXPECT_EQ(0, memcmp(expected, result, pixelSize));
+ }
+ {
+ IntRect sourceRect(1, 0, 1, 1);
+ IntRect destRect(0, 1, 1, 1);
+ m_resourceProvider->upload(id, image, imageRect, sourceRect, destRect);
+
+ uint8_t expected[16] = {0, 1, 2, 3, 0, 0, 0, 0,
+ 4, 5, 6, 7, 0, 1, 2, 3};
+ getResourcePixels(id, size, format, result);
+ EXPECT_EQ(0, memcmp(expected, result, pixelSize));
+ }
+
+ m_resourceProvider->deleteResource(id);
+}
+
+} // namespace