diff options
author | aelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-06 05:53:00 +0000 |
---|---|---|
committer | aelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-06 05:53:00 +0000 |
commit | 35680c0ca726980e1a380e668bf7565b39eb7ce9 (patch) | |
tree | f6c147c60ca4beae0d663efc9d211f55325a6854 | |
parent | ae8be5cadd06887ae263a9e906afe297e8cffb8b (diff) | |
download | chromium_src-35680c0ca726980e1a380e668bf7565b39eb7ce9.zip chromium_src-35680c0ca726980e1a380e668bf7565b39eb7ce9.tar.gz chromium_src-35680c0ca726980e1a380e668bf7565b39eb7ce9.tar.bz2 |
cc: Nine patch layer.
Review URL: https://chromiumcodereview.appspot.com/11304020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166154 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/cc.gyp | 6 | ||||
-rw-r--r-- | cc/cc_tests.gyp | 2 | ||||
-rw-r--r-- | cc/image_layer.cc | 66 | ||||
-rw-r--r-- | cc/image_layer_updater.cc | 55 | ||||
-rw-r--r-- | cc/image_layer_updater.h | 50 | ||||
-rw-r--r-- | cc/nine_patch_layer.cc | 99 | ||||
-rw-r--r-- | cc/nine_patch_layer.h | 55 | ||||
-rw-r--r-- | cc/nine_patch_layer_impl.cc | 117 | ||||
-rw-r--r-- | cc/nine_patch_layer_impl.h | 51 | ||||
-rw-r--r-- | cc/nine_patch_layer_impl_unittest.cc | 94 | ||||
-rw-r--r-- | cc/nine_patch_layer_unittest.cc | 142 | ||||
-rw-r--r-- | webkit/compositor_bindings/compositor_bindings.gyp | 2 | ||||
-rw-r--r-- | webkit/compositor_bindings/web_nine_patch_layer_impl.cc | 36 | ||||
-rw-r--r-- | webkit/compositor_bindings/web_nine_patch_layer_impl.h | 31 |
14 files changed, 741 insertions, 65 deletions
@@ -60,6 +60,8 @@ 'heads_up_display_layer.h', 'heads_up_display_layer_impl.cc', 'heads_up_display_layer_impl.h', + 'image_layer_updater.cc', + 'image_layer_updater.h', 'image_layer.cc', 'image_layer.h', 'input_handler.h', @@ -99,6 +101,10 @@ 'managed_memory_policy.h', 'math_util.cc', 'math_util.h', + 'nine_patch_layer.cc', + 'nine_patch_layer.h', + 'nine_patch_layer_impl.cc', + 'nine_patch_layer_impl.h', 'occlusion_tracker.cc', 'occlusion_tracker.h', 'overdraw_metrics.cc', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index c51556d..df98423 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -25,6 +25,8 @@ 'layer_tree_host_impl_unittest.cc', 'layer_tree_host_unittest.cc', 'math_util_unittest.cc', + 'nine_patch_layer_unittest.cc', + 'nine_patch_layer_impl_unittest.cc', 'occlusion_tracker_unittest.cc', 'prioritized_texture_unittest.cc', 'quad_culler_unittest.cc', diff --git a/cc/image_layer.cc b/cc/image_layer.cc index 5171799..c150c6d 100644 --- a/cc/image_layer.cc +++ b/cc/image_layer.cc @@ -7,77 +7,13 @@ #include "cc/image_layer.h" #include "base/compiler_specific.h" +#include "cc/image_layer_updater.h" #include "cc/layer_updater.h" #include "cc/layer_tree_host.h" #include "cc/resource_update_queue.h" namespace cc { -class ImageLayerUpdater : public LayerUpdater { -public: - class Resource : public LayerUpdater::Resource { - public: - Resource(ImageLayerUpdater* updater, scoped_ptr<PrioritizedTexture> texture) - : LayerUpdater::Resource(texture.Pass()) - , m_updater(updater) - { - } - - virtual void update(ResourceUpdateQueue& queue, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset, bool partialUpdate, RenderingStats&) OVERRIDE - { - updater()->updateTexture(queue, texture(), sourceRect, destOffset, partialUpdate); - } - - private: - ImageLayerUpdater* updater() { return m_updater; } - - ImageLayerUpdater* m_updater; - }; - - static scoped_refptr<ImageLayerUpdater> create() - { - return make_scoped_refptr(new ImageLayerUpdater()); - } - - virtual scoped_ptr<LayerUpdater::Resource> createResource( - PrioritizedTextureManager* manager) OVERRIDE - { - return scoped_ptr<LayerUpdater::Resource>(new Resource(this, PrioritizedTexture::create(manager))); - } - - void updateTexture(ResourceUpdateQueue& queue, PrioritizedTexture* texture, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset, bool partialUpdate) - { - // Source rect should never go outside the image pixels, even if this - // is requested because the texture extends outside the image. - gfx::Rect clippedSourceRect = sourceRect; - gfx::Rect imageRect = gfx::Rect(0, 0, m_bitmap.width(), m_bitmap.height()); - clippedSourceRect.Intersect(imageRect); - - gfx::Vector2d clippedDestOffset = destOffset + (clippedSourceRect.origin() - sourceRect.origin()); - - ResourceUpdate upload = ResourceUpdate::Create(texture, - &m_bitmap, - imageRect, - clippedSourceRect, - clippedDestOffset); - if (partialUpdate) - queue.appendPartialUpload(upload); - else - queue.appendFullUpload(upload); - } - - void setBitmap(const SkBitmap& bitmap) - { - m_bitmap = bitmap; - } - -private: - ImageLayerUpdater() { } - virtual ~ImageLayerUpdater() { } - - SkBitmap m_bitmap; -}; - scoped_refptr<ImageLayer> ImageLayer::create() { return make_scoped_refptr(new ImageLayer()); diff --git a/cc/image_layer_updater.cc b/cc/image_layer_updater.cc new file mode 100644 index 0000000..9f73b80 --- /dev/null +++ b/cc/image_layer_updater.cc @@ -0,0 +1,55 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "cc/image_layer_updater.h" +#include "cc/resource_update_queue.h" + +namespace cc { + +void ImageLayerUpdater::Resource::update(ResourceUpdateQueue& queue, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset, bool partialUpdate, RenderingStats&) +{ + m_updater->updateTexture(queue, texture(), sourceRect, destOffset, partialUpdate); +} + +// static +scoped_refptr<ImageLayerUpdater> ImageLayerUpdater::create() +{ + return make_scoped_refptr(new ImageLayerUpdater()); +} + +scoped_ptr<LayerUpdater::Resource> ImageLayerUpdater::createResource( + PrioritizedTextureManager* manager) +{ + return scoped_ptr<LayerUpdater::Resource>(new Resource(this, PrioritizedTexture::create(manager))); +} + +void ImageLayerUpdater::updateTexture(ResourceUpdateQueue& queue, PrioritizedTexture* texture, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset, bool partialUpdate) +{ + // Source rect should never go outside the image pixels, even if this + // is requested because the texture extends outside the image. + gfx::Rect clippedSourceRect = sourceRect; + gfx::Rect imageRect = gfx::Rect(0, 0, m_bitmap.width(), m_bitmap.height()); + clippedSourceRect.Intersect(imageRect); + + gfx::Vector2d clippedDestOffset = destOffset + gfx::Vector2d(clippedSourceRect.origin() - sourceRect.origin()); + + ResourceUpdate upload = ResourceUpdate::Create(texture, + &m_bitmap, + imageRect, + clippedSourceRect, + clippedDestOffset); + if (partialUpdate) + queue.appendPartialUpload(upload); + else + queue.appendFullUpload(upload); +} + +void ImageLayerUpdater::setBitmap(const SkBitmap& bitmap) +{ + m_bitmap = bitmap; +} + +} diff --git a/cc/image_layer_updater.h b/cc/image_layer_updater.h new file mode 100644 index 0000000..89c26b2 --- /dev/null +++ b/cc/image_layer_updater.h @@ -0,0 +1,50 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ImageLayerUpdater_h +#define ImageLayerUpdater_h + +#include "config.h" + +#include "cc/layer_updater.h" + +namespace cc { + +class ResourceUpdateQueue; + +class ImageLayerUpdater : public LayerUpdater { +public: + class Resource : public LayerUpdater::Resource { + public: + Resource(ImageLayerUpdater* updater, scoped_ptr<PrioritizedTexture> texture) + : LayerUpdater::Resource(texture.Pass()) + , m_updater(updater) + { + } + + virtual void update(ResourceUpdateQueue&, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset, bool partialUpdate, RenderingStats&) OVERRIDE; + + private: + ImageLayerUpdater* m_updater; + }; + + static scoped_refptr<ImageLayerUpdater> create(); + + virtual scoped_ptr<LayerUpdater::Resource> createResource( + PrioritizedTextureManager*) OVERRIDE; + + void updateTexture(ResourceUpdateQueue&, PrioritizedTexture*, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset, bool partialUpdate); + + void setBitmap(const SkBitmap&); + +private: + ImageLayerUpdater() { } + virtual ~ImageLayerUpdater() { } + + SkBitmap m_bitmap; +}; + +} + +#endif diff --git a/cc/nine_patch_layer.cc b/cc/nine_patch_layer.cc new file mode 100644 index 0000000..8ad3174 --- /dev/null +++ b/cc/nine_patch_layer.cc @@ -0,0 +1,99 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "cc/nine_patch_layer.h" + +#include "cc/layer_tree_host.h" +#include "cc/nine_patch_layer_impl.h" +#include "cc/resource_update.h" +#include "cc/resource_update_queue.h" + +namespace cc { + +scoped_refptr<NinePatchLayer> NinePatchLayer::create() +{ + return make_scoped_refptr(new NinePatchLayer()); +} + +NinePatchLayer::NinePatchLayer() + : m_bitmapDirty(false) +{ +} + +NinePatchLayer::~NinePatchLayer() +{ +} + +scoped_ptr<LayerImpl> NinePatchLayer::createLayerImpl() +{ + return NinePatchLayerImpl::create(id()).PassAs<LayerImpl>(); +} + +void NinePatchLayer::setTexturePriorities(const PriorityCalculator& priorityCalc) +{ + if (m_needsDisplay && m_bitmapDirty && drawsContent()) { + DCHECK(!m_bitmap.isNull()); + createUpdaterIfNeeded(); + m_updater->setBitmap(m_bitmap); + m_needsDisplay = false; + + if (!m_resource) + m_resource = m_updater->createResource(layerTreeHost()->contentsTextureManager()); + } + + if (m_resource) { + m_resource->texture()->setRequestPriority(PriorityCalculator::uiPriority(true)); + // FIXME: Need to support swizzle in the shader for !PlatformColor::sameComponentOrder(textureFormat) + GLenum textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; + m_resource->texture()->setDimensions(gfx::Size(m_bitmap.width(), m_bitmap.height()), textureFormat); + } +} + +void NinePatchLayer::setBitmap(const SkBitmap& bitmap, const gfx::Rect& aperture) { + m_bitmap = bitmap; + m_imageAperture = aperture; + m_bitmapDirty = true; + setNeedsDisplay(); +} + +void NinePatchLayer::update(ResourceUpdateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats) +{ + createUpdaterIfNeeded(); + + if (m_resource && (m_bitmapDirty || m_resource->texture()->backingResourceWasEvicted())) { + gfx::Rect contentRect(gfx::Point(), gfx::Size(m_bitmap.width(), m_bitmap.height())); + ResourceUpdate upload = ResourceUpdate::Create(m_resource->texture(), &m_bitmap, contentRect, contentRect, gfx::Vector2d()); + queue.appendFullUpload(upload); + m_bitmapDirty = false; + } +} + +void NinePatchLayer::createUpdaterIfNeeded() +{ + if (m_updater) + return; + + m_updater = ImageLayerUpdater::create(); +} + +bool NinePatchLayer::drawsContent() const +{ + bool draws = !m_bitmap.isNull() && Layer::drawsContent() && m_bitmap.width() && m_bitmap.height(); + return draws; +} + +void NinePatchLayer::pushPropertiesTo(LayerImpl* layer) +{ + Layer::pushPropertiesTo(layer); + NinePatchLayerImpl* layerImpl = static_cast<NinePatchLayerImpl*>(layer); + + DCHECK(!m_bitmap.isNull()); + DCHECK(m_resource); + layerImpl->setResourceId(m_resource->texture()->resourceId()); + layerImpl->setLayout(gfx::Size(m_bitmap.width(), m_bitmap.height()), m_imageAperture); +} + +} diff --git a/cc/nine_patch_layer.h b/cc/nine_patch_layer.h new file mode 100644 index 0000000..6e20b1f --- /dev/null +++ b/cc/nine_patch_layer.h @@ -0,0 +1,55 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NinePatchLayer_h +#define NinePatchLayer_h + +#include "base/memory/scoped_ptr.h" +#include "cc/cc_export.h" +#include "cc/layer.h" +#include "cc/image_layer_updater.h" +#include "ui/gfx/rect.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace cc { + +class ResourceUpdateQueue; + +class CC_EXPORT NinePatchLayer : public Layer { +public: + static scoped_refptr<NinePatchLayer> create(); + + virtual bool drawsContent() const OVERRIDE; + virtual void setTexturePriorities(const PriorityCalculator&) OVERRIDE; + virtual void update(ResourceUpdateQueue&, const OcclusionTracker*, RenderingStats&) OVERRIDE; + virtual void pushPropertiesTo(LayerImpl*) OVERRIDE; + + // aperture is in the pixel space of the bitmap resource and refers to + // the center patch of the ninepatch (which is unused in this + // implementation). We split off eight rects surrounding it and stick them + // on the edges of the layer. The corners are unscaled, the top and bottom + // rects are x-stretched to fit, and the left and right rects are + // y-stretched to fit. + void setBitmap(const SkBitmap& bitmap, const gfx::Rect& aperture); + +private: + NinePatchLayer(); + virtual ~NinePatchLayer(); + virtual scoped_ptr<LayerImpl> createLayerImpl() OVERRIDE; + + void createUpdaterIfNeeded(); + + scoped_refptr<ImageLayerUpdater> m_updater; + scoped_ptr<LayerUpdater::Resource> m_resource; + + SkBitmap m_bitmap; + bool m_bitmapDirty; + + // The transparent center region that shows the parent layer's contents in image space. + gfx::Rect m_imageAperture; +}; + +} + +#endif diff --git a/cc/nine_patch_layer_impl.cc b/cc/nine_patch_layer_impl.cc new file mode 100644 index 0000000..d271eb0 --- /dev/null +++ b/cc/nine_patch_layer_impl.cc @@ -0,0 +1,117 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "nine_patch_layer_impl.h" + +#include "cc/quad_sink.h" +#include "cc/texture_draw_quad.h" +#include "ui/gfx/rect_f.h" + +namespace cc { + +NinePatchLayerImpl::NinePatchLayerImpl(int id) + : LayerImpl(id) + , m_resourceId(0) +{ +} + +NinePatchLayerImpl::~NinePatchLayerImpl() +{ +} + +ResourceProvider::ResourceId NinePatchLayerImpl::contentsResourceId() const +{ + return 0; +} + +void NinePatchLayerImpl::dumpLayerProperties(std::string* str, int indent) const +{ + LayerImpl::dumpLayerProperties(str, indent); +} + + +void NinePatchLayerImpl::willDraw(ResourceProvider* resourceProvider) +{ +} + +static gfx::RectF normalizedRect(float x, float y, float width, float height, float totalWidth, float totalHeight) +{ + return gfx::RectF(x / totalWidth, y / totalHeight, width / totalWidth, height / totalHeight); +} + +void NinePatchLayerImpl::setLayout(const gfx::Size& imageBounds, const gfx::Rect& aperture) +{ + m_imageBounds = imageBounds; + m_imageAperture = aperture; +} + +void NinePatchLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuadsData) +{ + if (!m_resourceId) + return; + + SharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + static const bool flipped = false; + static const bool premultipliedAlpha = true; + + DCHECK(!bounds().IsEmpty()); + + // NinePatch border widths in bitmap pixel space + int leftWidth = m_imageAperture.x(); + int topHeight = m_imageAperture.y(); + int rightWidth = m_imageBounds.width() - m_imageAperture.right(); + int bottomHeight = m_imageBounds.height() - m_imageAperture.bottom(); + + // Patch positions in layer space + gfx::Rect topLeft(0, 0, leftWidth, topHeight); + gfx::Rect topRight(bounds().width() - rightWidth, 0, rightWidth, topHeight); + gfx::Rect bottomLeft(0, bounds().height() - bottomHeight, leftWidth, bottomHeight); + gfx::Rect bottomRight(topRight.x(), bottomLeft.y(), rightWidth, bottomHeight); + gfx::Rect top(topLeft.right(), 0, bounds().width() - leftWidth - rightWidth, topHeight); + gfx::Rect left(0, topLeft.bottom(), leftWidth, bounds().height() - topHeight - bottomHeight); + gfx::Rect right(topRight.x(), topRight.bottom(), rightWidth, left.height()); + gfx::Rect bottom(top.x(), bottomLeft.y(), top.width(), bottomHeight); + + float imgWidth = m_imageBounds.width(); + float imgHeight = m_imageBounds.height(); + + // Patch positions in bitmap UV space (from zero to one) + gfx::RectF uvTopLeft = normalizedRect(0, 0, leftWidth, topHeight, imgWidth, imgHeight); + gfx::RectF uvTopRight = normalizedRect(imgWidth - rightWidth, 0, rightWidth, topHeight, imgWidth, imgHeight); + gfx::RectF uvBottomLeft = normalizedRect(0, imgHeight - bottomHeight, leftWidth, bottomHeight, imgWidth, imgHeight); + gfx::RectF uvBottomRight = normalizedRect(imgWidth - rightWidth, imgHeight - bottomHeight, rightWidth, bottomHeight, imgWidth, imgHeight); + gfx::RectF uvTop(uvTopLeft.right(), 0, (imgWidth - leftWidth - rightWidth) / imgWidth, (topHeight) / imgHeight); + gfx::RectF uvLeft(0, uvTopLeft.bottom(), leftWidth / imgWidth, (imgHeight - topHeight - bottomHeight) / imgHeight); + gfx::RectF uvRight(uvTopRight.x(), uvTopRight.bottom(), rightWidth / imgWidth, uvLeft.height()); + gfx::RectF uvBottom(uvTop.x(), uvBottomLeft.y(), uvTop.width(), bottomHeight / imgHeight); + + quadSink.append(TextureDrawQuad::create(sharedQuadState, topLeft, m_resourceId, premultipliedAlpha, uvTopLeft, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, topRight, m_resourceId, premultipliedAlpha, uvTopRight, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, bottomLeft, m_resourceId, premultipliedAlpha, uvBottomLeft, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, bottomRight, m_resourceId, premultipliedAlpha, uvBottomRight, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, top, m_resourceId, premultipliedAlpha, uvTop, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, left, m_resourceId, premultipliedAlpha, uvLeft, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, right, m_resourceId, premultipliedAlpha, uvRight, flipped).PassAs<DrawQuad>(), appendQuadsData); + quadSink.append(TextureDrawQuad::create(sharedQuadState, bottom, m_resourceId, premultipliedAlpha, uvBottom, flipped).PassAs<DrawQuad>(), appendQuadsData); +} + +void NinePatchLayerImpl::didDraw(ResourceProvider* resourceProvider) +{ +} + +void NinePatchLayerImpl::didLoseContext() +{ + m_resourceId = 0; +} + +const char* NinePatchLayerImpl::layerTypeAsString() const +{ + return "NinePatchLayer"; +} + +} diff --git a/cc/nine_patch_layer_impl.h b/cc/nine_patch_layer_impl.h new file mode 100644 index 0000000..476f5bb --- /dev/null +++ b/cc/nine_patch_layer_impl.h @@ -0,0 +1,51 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NinePatchLayerImpl_h +#define NinePatchLayerImpl_h + +#include "cc/cc_export.h" +#include "cc/layer_impl.h" +#include "cc/resource_provider.h" +#include "ui/gfx/size.h" +#include "ui/gfx/rect.h" + +namespace cc { + +class CC_EXPORT NinePatchLayerImpl : public LayerImpl { +public: + static scoped_ptr<NinePatchLayerImpl> create(int id) + { + return make_scoped_ptr(new NinePatchLayerImpl(id)); + } + virtual ~NinePatchLayerImpl(); + + void setResourceId(unsigned id) { m_resourceId = id; } + void setLayout(const gfx::Size& imageBounds, const gfx::Rect& aperture); + + virtual void willDraw(ResourceProvider*) OVERRIDE; + virtual void appendQuads(QuadSink&, AppendQuadsData&) OVERRIDE; + virtual void didDraw(ResourceProvider*) OVERRIDE; + virtual ResourceProvider::ResourceId contentsResourceId() const OVERRIDE; + virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; + virtual void didLoseContext() OVERRIDE; + +protected: + explicit NinePatchLayerImpl(int id); + +private: + virtual const char* layerTypeAsString() const OVERRIDE; + + // The size of the NinePatch bitmap in pixels. + gfx::Size m_imageBounds; + + // The transparent center region that shows the parent layer's contents in image space. + gfx::Rect m_imageAperture; + + ResourceProvider::ResourceId m_resourceId; +}; + +} + +#endif diff --git a/cc/nine_patch_layer_impl_unittest.cc b/cc/nine_patch_layer_impl_unittest.cc new file mode 100644 index 0000000..55f0c10 --- /dev/null +++ b/cc/nine_patch_layer_impl_unittest.cc @@ -0,0 +1,94 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "cc/nine_patch_layer_impl.h" + +#include "cc/append_quads_data.h" +#include "cc/single_thread_proxy.h" +#include "cc/test/geometry_test_utils.h" +#include "cc/test/layer_test_common.h" +#include "cc/test/mock_quad_culler.h" +#include "cc/texture_draw_quad.h" +#include "ui/gfx/rect_conversions.h" +#include "ui/gfx/safe_integer_conversions.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include <public/WebTransformationMatrix.h> + +using namespace cc; + +namespace { + +gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) { + return gfx::Rect(gfx::ToRoundedInt(rect_f.x()), gfx::ToRoundedInt(rect_f.y()), gfx::ToRoundedInt(rect_f.width()), gfx::ToRoundedInt(rect_f.height())); +} + +TEST(NinePatchLayerImplTest, verifyDrawQuads) +{ + DebugScopedSetImplThread implThread; + + // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30. + // The bounds of the layer are set to 400x400, so the draw quads + // generated should leave the border width (40) intact. + MockQuadCuller quadCuller; + gfx::Size bitmapSize(100, 100); + gfx::Size layerSize(400, 400); + gfx::Rect visibleContentRect(gfx::Point(), layerSize); + gfx::Rect apertureRect(20, 30, 40, 50); + gfx::Rect scaledApertureNonUniform(20, 30, 340, 350); + + scoped_ptr<NinePatchLayerImpl> layer = NinePatchLayerImpl::create(1); + layer->setVisibleContentRect(visibleContentRect); + layer->setBounds(layerSize); + layer->setContentBounds(layerSize); + layer->createRenderSurface(); + layer->setRenderTarget(layer.get()); + layer->setLayout(bitmapSize, apertureRect); + layer->setResourceId(1); + + // This scale should not affect the generated quad geometry, but only + // the shared draw transform. + WebKit::WebTransformationMatrix transform; + transform.scale(10); + layer->setDrawTransform(transform); + + AppendQuadsData data; + layer->appendQuads(quadCuller, data); + + // Verify quad rects + const QuadList& quads = quadCuller.quadList(); + EXPECT_EQ(quads.size(), 8); + Region remaining(visibleContentRect); + for (size_t i = 0; i < quads.size(); ++i) { + DrawQuad* quad = quads[i]; + gfx::Rect quadRect = quad->quadRect(); + + EXPECT_TRUE(visibleContentRect.Contains(quadRect)) << i; + EXPECT_TRUE(remaining.Contains(quadRect)) << i; + EXPECT_EQ(quad->sharedQuadState()->quadTransform, transform) << i; + remaining.Subtract(Region(quadRect)); + } + EXPECT_RECT_EQ(remaining.bounds(), scaledApertureNonUniform); + Region scaledApertureRegion(scaledApertureNonUniform); + EXPECT_EQ(remaining, scaledApertureRegion); + + // Verify UV rects + gfx::Rect bitmapRect(gfx::Point(), bitmapSize); + Region texRemaining(bitmapRect); + for (size_t i = 0; i < quads.size(); ++i) { + DrawQuad* quad = quads[i]; + ASSERT_EQ(quad->material(), DrawQuad::TextureContent); + TextureDrawQuad* texQuad = static_cast<TextureDrawQuad*>(quad); + gfx::RectF texRect = texQuad->uvRect(); + texRect.Scale(bitmapSize.width(), bitmapSize.height()); + texRemaining.Subtract(Region(ToRoundedIntRect(texRect))); + } + EXPECT_RECT_EQ(texRemaining.bounds(), apertureRect); + Region apertureRegion(apertureRect); + EXPECT_EQ(texRemaining, apertureRegion); +} + +} diff --git a/cc/nine_patch_layer_unittest.cc b/cc/nine_patch_layer_unittest.cc new file mode 100644 index 0000000..49757fe --- /dev/null +++ b/cc/nine_patch_layer_unittest.cc @@ -0,0 +1,142 @@ +// Copyright 2012 The Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "cc/nine_patch_layer.h" + +#include "cc/layer_tree_host.h" +#include "cc/occlusion_tracker.h" +#include "cc/overdraw_metrics.h" +#include "cc/rendering_stats.h" +#include "cc/resource_provider.h" +#include "cc/single_thread_proxy.h" +#include "cc/resource_update_queue.h" +#include "cc/texture_uploader.h" +#include "cc/test/fake_graphics_context.h" +#include "cc/test/fake_layer_tree_host_client.h" +#include "cc/test/geometry_test_utils.h" +#include "cc/test/layer_tree_test_common.h" +#include "SkBitmap.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using namespace cc; +using ::testing::Mock; +using ::testing::_; +using ::testing::AtLeast; +using ::testing::AnyNumber; + +namespace { + +class MockLayerTreeHost : public LayerTreeHost { +public: + MockLayerTreeHost() + : LayerTreeHost(&m_fakeClient, LayerTreeSettings()) + { + initialize(); + } + +private: + FakeLayerImplTreeHostClient m_fakeClient; +}; + + +class NinePatchLayerTest : public testing::Test { +public: + NinePatchLayerTest() + { + } + +protected: + virtual void SetUp() + { + m_layerTreeHost.reset(new MockLayerTreeHost); + } + + virtual void TearDown() + { + Mock::VerifyAndClearExpectations(m_layerTreeHost.get()); + } + + scoped_ptr<MockLayerTreeHost> m_layerTreeHost; +}; + +TEST_F(NinePatchLayerTest, triggerFullUploadOnceWhenChangingBitmap) +{ + scoped_refptr<NinePatchLayer> testLayer = NinePatchLayer::create(); + ASSERT_TRUE(testLayer); + testLayer->setIsDrawable(true); + testLayer->setBounds(gfx::Size(100, 100)); + + m_layerTreeHost->setRootLayer(testLayer); + Mock::VerifyAndClearExpectations(m_layerTreeHost.get()); + EXPECT_EQ(testLayer->layerTreeHost(), m_layerTreeHost.get()); + + m_layerTreeHost->initializeRendererIfNeeded(); + + PriorityCalculator calculator; + ResourceUpdateQueue queue; + OcclusionTracker occlusionTracker(gfx::Rect(), false); + RenderingStats stats; + + // No bitmap set should not trigger any uploads. + testLayer->setTexturePriorities(calculator); + testLayer->update(queue, &occlusionTracker, stats); + EXPECT_EQ(queue.fullUploadSize(), 0); + EXPECT_EQ(queue.partialUploadSize(), 0); + + // Setting a bitmap set should trigger a single full upload. + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10); + bitmap.allocPixels(); + testLayer->setBitmap(bitmap, gfx::Rect(5, 5, 1, 1)); + testLayer->setTexturePriorities(calculator); + testLayer->update(queue, &occlusionTracker, stats); + EXPECT_EQ(queue.fullUploadSize(), 1); + EXPECT_EQ(queue.partialUploadSize(), 0); + ResourceUpdate params = queue.takeFirstFullUpload(); + EXPECT_TRUE(params.texture != NULL); + + // Upload the texture. + m_layerTreeHost->contentsTextureManager()->setMaxMemoryLimitBytes(1024 * 1024); + m_layerTreeHost->contentsTextureManager()->prioritizeTextures(); + + scoped_ptr<GraphicsContext> context; + scoped_ptr<ResourceProvider> resourceProvider; + { + DebugScopedSetImplThread implThread; + DebugScopedSetMainThreadBlocked mainThreadBlocked; + context = WebKit::createFakeGraphicsContext(); + resourceProvider = ResourceProvider::create(context.get()); + params.texture->acquireBackingTexture(resourceProvider.get()); + ASSERT_TRUE(params.texture->haveBackingTexture()); + } + + // Nothing changed, so no repeated upload. + testLayer->setTexturePriorities(calculator); + { + DebugScopedSetImplThread implThread; + testLayer->update(queue, &occlusionTracker, stats); + } + EXPECT_EQ(queue.fullUploadSize(), 0); + EXPECT_EQ(queue.partialUploadSize(), 0); + + { + DebugScopedSetImplThread implThread; + DebugScopedSetMainThreadBlocked mainThreadBlocked; + m_layerTreeHost->contentsTextureManager()->clearAllMemory(resourceProvider.get()); + } + + // Reupload after eviction + testLayer->setTexturePriorities(calculator); + { + DebugScopedSetImplThread implThread; + testLayer->update(queue, &occlusionTracker, stats); + } + EXPECT_EQ(queue.fullUploadSize(), 1); + EXPECT_EQ(queue.partialUploadSize(), 0); +} + +} // anonymous namespace diff --git a/webkit/compositor_bindings/compositor_bindings.gyp b/webkit/compositor_bindings/compositor_bindings.gyp index 9f6417c..abcbaee 100644 --- a/webkit/compositor_bindings/compositor_bindings.gyp +++ b/webkit/compositor_bindings/compositor_bindings.gyp @@ -25,6 +25,8 @@ 'web_image_layer_impl.h', 'web_layer_impl.cc', 'web_layer_impl.h', + 'web_nine_patch_layer_impl.cc', + 'web_nine_patch_layer_impl.h', 'web_to_ccinput_handler_adapter.cc', 'web_to_ccinput_handler_adapter.h', 'web_layer_tree_view_impl.cc', diff --git a/webkit/compositor_bindings/web_nine_patch_layer_impl.cc b/webkit/compositor_bindings/web_nine_patch_layer_impl.cc new file mode 100644 index 0000000..2d30b35 --- /dev/null +++ b/webkit/compositor_bindings/web_nine_patch_layer_impl.cc @@ -0,0 +1,36 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "web_nine_patch_layer_impl.h" + +#include "cc/nine_patch_layer.h" +#include "ui/gfx/rect.h" +#include "web_layer_impl.h" +#include "SkBitmap.h" + +using cc::NinePatchLayer; + +namespace WebKit { + +WebNinePatchLayerImpl::WebNinePatchLayerImpl() + : m_layer(new WebLayerImpl(NinePatchLayer::create())) +{ + m_layer->layer()->setIsDrawable(true); +} + +WebNinePatchLayerImpl::~WebNinePatchLayerImpl() +{ +} + +WebLayer* WebNinePatchLayerImpl::layer() +{ + return m_layer.get(); +} + +void WebNinePatchLayerImpl::setBitmap(const SkBitmap& bitmap, const WebRect& aperture) { + static_cast<NinePatchLayer*>(m_layer->layer())->setBitmap(bitmap, gfx::Rect(aperture)); +} + +} // namespace WebKit diff --git a/webkit/compositor_bindings/web_nine_patch_layer_impl.h b/webkit/compositor_bindings/web_nine_patch_layer_impl.h new file mode 100644 index 0000000..02605d8 --- /dev/null +++ b/webkit/compositor_bindings/web_nine_patch_layer_impl.h @@ -0,0 +1,31 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebNinePatchLayerImpl_h +#define WebNinePatchLayerImpl_h + +#include "web_layer_impl.h" +#include "base/memory/scoped_ptr.h" +#include "SkBitmap.h" + +namespace WebKit { + +class WebLayerImpl; + +class WebNinePatchLayerImpl { +public: + WebNinePatchLayerImpl(); + virtual ~WebNinePatchLayerImpl(); + + WebLayer* layer(); + + void setBitmap(const SkBitmap& bitmap, const WebRect& aperture); + +private: + scoped_ptr<WebLayerImpl> m_layer; +}; + +} // namespace WebKit + +#endif |