diff options
author | aelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-24 21:32:57 +0000 |
---|---|---|
committer | aelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-24 21:32:57 +0000 |
commit | d61675de46031d9db57d198e482abaccc79c63e7 (patch) | |
tree | 8ecc4801ccce660ecb55ae7038fcf5e9a60ba51b /cc | |
parent | a02f64e4b986222548e9cd5bfdcbc940e22e69be (diff) | |
download | chromium_src-d61675de46031d9db57d198e482abaccc79c63e7.zip chromium_src-d61675de46031d9db57d198e482abaccc79c63e7.tar.gz chromium_src-d61675de46031d9db57d198e482abaccc79c63e7.tar.bz2 |
Add CC software renderer.
This new renderer adds support for the compositor to output to a
software-bitmap surface instead of a GL context. It uses Skia to
interpret the CCDrawQuads and configures the resource provider to only
use bitmap-backed resources. During initialization, the host checks
whether a GL or software output surface is available and initializes the
appropriate renderer.
The basic texture and solid-color based quad types are supported, along
with alpha, clipping and 3d transformations. Render surfaces and video
are not yet supported.
BUG=124671
Review URL: https://chromiumcodereview.appspot.com/10918258
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@158396 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/CCDirectRenderer.cpp | 2 | ||||
-rw-r--r-- | cc/CCDirectRenderer.h | 1 | ||||
-rw-r--r-- | cc/CCLayerTreeHostImpl.cpp | 19 | ||||
-rw-r--r-- | cc/CCRendererGL.cpp | 5 | ||||
-rw-r--r-- | cc/CCRendererGL.h | 1 | ||||
-rw-r--r-- | cc/CCRendererSoftware.cpp | 280 | ||||
-rw-r--r-- | cc/CCRendererSoftware.h | 74 | ||||
-rw-r--r-- | cc/CCRendererSoftwareTest.cpp | 162 | ||||
-rw-r--r-- | cc/CCResourceProvider.cpp | 6 | ||||
-rw-r--r-- | cc/cc.gyp | 2 | ||||
-rw-r--r-- | cc/cc_tests.gyp | 2 | ||||
-rw-r--r-- | cc/test/FakeWebCompositorOutputSurface.h | 17 | ||||
-rw-r--r-- | cc/test/FakeWebCompositorSoftwareOutputDevice.h | 45 |
13 files changed, 601 insertions, 15 deletions
diff --git a/cc/CCDirectRenderer.cpp b/cc/CCDirectRenderer.cpp index d2faf9f..1e9df5d 100644 --- a/cc/CCDirectRenderer.cpp +++ b/cc/CCDirectRenderer.cpp @@ -213,7 +213,7 @@ bool CCDirectRenderer::useRenderPass(DrawingFrame& frame, const CCRenderPass* re if (renderPass == frame.rootRenderPass) { bindFramebufferToOutputSurface(frame); - initializeMatrices(frame, renderPass->outputRect(), true); + initializeMatrices(frame, renderPass->outputRect(), flippedFramebuffer()); setDrawViewportSize(renderPass->outputRect().size()); return true; } diff --git a/cc/CCDirectRenderer.h b/cc/CCDirectRenderer.h index c3407c0..e11d1d74 100644 --- a/cc/CCDirectRenderer.h +++ b/cc/CCDirectRenderer.h @@ -88,6 +88,7 @@ protected: virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) = 0; virtual void beginDrawingFrame(DrawingFrame&) = 0; virtual void finishDrawingFrame(DrawingFrame&) = 0; + virtual bool flippedFramebuffer() const = 0; HashMap<CCRenderPass::Id, OwnPtr<CachedTexture> > m_renderPassTextures; CCResourceProvider* m_resourceProvider; diff --git a/cc/CCLayerTreeHostImpl.cpp b/cc/CCLayerTreeHostImpl.cpp index 4cb3db0..326117d 100644 --- a/cc/CCLayerTreeHostImpl.cpp +++ b/cc/CCLayerTreeHostImpl.cpp @@ -22,6 +22,7 @@ #include "CCPrioritizedTextureManager.h" #include "CCRenderPassDrawQuad.h" #include "CCRendererGL.h" +#include "CCRendererSoftware.h" #include "CCRenderingStats.h" #include "CCScrollbarAnimationController.h" #include "CCScrollbarLayerImpl.h" @@ -714,18 +715,16 @@ bool CCLayerTreeHostImpl::initializeRenderer(PassOwnPtr<CCGraphicsContext> conte if (!context->bindToClient(this)) return false; - WebKit::WebGraphicsContext3D* context3d = context->context3D(); - - if (!context3d) { - // FIXME: Implement this path for software compositing. - return false; - } - OwnPtr<CCGraphicsContext> contextRef(context); OwnPtr<CCResourceProvider> resourceProvider = CCResourceProvider::create(contextRef.get()); - OwnPtr<CCRendererGL> renderer; - if (resourceProvider.get()) - renderer = CCRendererGL::create(this, resourceProvider.get()); + + OwnPtr<CCRenderer> renderer; + if (resourceProvider.get()) { + if (contextRef->context3D()) + renderer = CCRendererGL::create(this, resourceProvider.get()); + else if (contextRef->softwareDevice()) + renderer = CCRendererSoftware::create(this, resourceProvider.get(), contextRef->softwareDevice()); + } // Since we now have a new context/renderer, we cannot continue to use the old // resources (i.e. renderSurfaces and texture IDs). diff --git a/cc/CCRendererGL.cpp b/cc/CCRendererGL.cpp index f86e96c..50fed7a 100644 --- a/cc/CCRendererGL.cpp +++ b/cc/CCRendererGL.cpp @@ -943,6 +943,11 @@ void CCRendererGL::finishDrawingFrame(DrawingFrame& frame) GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); } +bool CCRendererGL::flippedFramebuffer() const +{ + return true; +} + void CCRendererGL::toGLMatrix(float* flattened, const WebTransformationMatrix& m) { flattened[0] = m.m11(); diff --git a/cc/CCRendererGL.h b/cc/CCRendererGL.h index 400a8d3..e7c14ea 100644 --- a/cc/CCRendererGL.h +++ b/cc/CCRendererGL.h @@ -86,6 +86,7 @@ protected: virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) OVERRIDE; virtual void beginDrawingFrame(DrawingFrame&) OVERRIDE; virtual void finishDrawingFrame(DrawingFrame&) OVERRIDE; + virtual bool flippedFramebuffer() const OVERRIDE; private: static void toGLMatrix(float*, const WebKit::WebTransformationMatrix&); diff --git a/cc/CCRendererSoftware.cpp b/cc/CCRendererSoftware.cpp new file mode 100644 index 0000000..c6994fa8 --- /dev/null +++ b/cc/CCRendererSoftware.cpp @@ -0,0 +1,280 @@ +// 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 "CCRendererSoftware.h" + +#include "CCDebugBorderDrawQuad.h" +#include "CCSolidColorDrawQuad.h" +#include "CCTextureDrawQuad.h" +#include "CCTileDrawQuad.h" +#include "SkCanvas.h" +#include "SkColor.h" +#include "SkMatrix.h" +#include "SkPixelRef.h" +#include <GLES2/gl2.h> +#include <public/WebImage.h> +#include <public/WebSize.h> +#include <public/WebTransformationMatrix.h> + +using WebKit::WebCompositorSoftwareOutputDevice; +using WebKit::WebImage; +using WebKit::WebSize; +using WebKit::WebTransformationMatrix; + +namespace cc { + +namespace { + +SkRect toSkRect(const FloatRect& rect) +{ + return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); +} + +SkIRect toSkIRect(const IntRect& rect) +{ + return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); +} + +void toSkMatrix(SkMatrix* flattened, const WebTransformationMatrix& m) +{ + // Convert from 4x4 to 3x3 by dropping the third row and column. + flattened->set(0, m.m11()); + flattened->set(1, m.m21()); + flattened->set(2, m.m41()); + flattened->set(3, m.m12()); + flattened->set(4, m.m22()); + flattened->set(5, m.m42()); + flattened->set(6, m.m14()); + flattened->set(7, m.m24()); + flattened->set(8, m.m44()); +} + +} // anonymous namespace + +PassOwnPtr<CCRendererSoftware> CCRendererSoftware::create(CCRendererClient* client, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) +{ + return adoptPtr(new CCRendererSoftware(client, resourceProvider, outputDevice)); +} + +CCRendererSoftware::CCRendererSoftware(CCRendererClient* client, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) + : CCDirectRenderer(client, resourceProvider) + , m_visible(true) + , m_outputDevice(outputDevice) + , m_skRootCanvas(0) + , m_skCurrentCanvas(0) +{ + m_resourceProvider->setDefaultResourceType(CCResourceProvider::Bitmap); + + m_capabilities.maxTextureSize = INT_MAX; + m_capabilities.bestTextureFormat = GraphicsContext3D::RGBA; + m_capabilities.contextHasCachedFrontBuffer = true; + m_capabilities.usingSetVisibility = true; + + viewportChanged(); +} + +CCRendererSoftware::~CCRendererSoftware() +{ +} + +const RendererCapabilities& CCRendererSoftware::capabilities() const +{ + return m_capabilities; +} + +void CCRendererSoftware::viewportChanged() +{ + m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewportSize().height())); +} + +void CCRendererSoftware::beginDrawingFrame(DrawingFrame& frame) +{ + m_skRootCanvas.setBitmapDevice(m_outputDevice->lock(true)->getSkBitmap()); +} + +void CCRendererSoftware::finishDrawingFrame(DrawingFrame& frame) +{ + m_currentFramebufferLock.clear(); + m_skCurrentCanvas = 0; + m_skRootCanvas.setDevice(0); + m_outputDevice->unlock(); +} + +bool CCRendererSoftware::flippedFramebuffer() const +{ + return false; +} + +void CCRendererSoftware::finish() +{ +} + +void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame& frame) +{ + m_currentFramebufferLock.clear(); + m_skCurrentCanvas = &m_skRootCanvas; +} + +bool CCRendererSoftware::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& framebufferRect) +{ + m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockSoftware(m_resourceProvider, texture->id())); + m_skCurrentCanvas = m_currentFramebufferLock->skCanvas(); + initializeMatrices(frame, framebufferRect, false); + setDrawViewportSize(framebufferRect.size()); + + return true; +} + +void CCRendererSoftware::enableScissorTestRect(const IntRect& scissorRect) +{ + m_skCurrentCanvas->clipRect(toSkRect(scissorRect), SkRegion::kReplace_Op); +} + +void CCRendererSoftware::disableScissorTest() +{ + IntRect canvasRect(IntPoint(), viewportSize()); + m_skCurrentCanvas->clipRect(toSkRect(canvasRect), SkRegion::kReplace_Op); +} + +void CCRendererSoftware::clearFramebuffer(DrawingFrame& frame) +{ + m_skCurrentCanvas->clear(SK_ColorGREEN); +} + +void CCRendererSoftware::setDrawViewportSize(const IntSize& viewportSize) +{ +} + +bool CCRendererSoftware::isSoftwareResource(CCResourceProvider::ResourceId id) const +{ + switch (m_resourceProvider->resourceType(id)) { + case CCResourceProvider::GLTexture: + return false; + case CCResourceProvider::Bitmap: + return true; + } + + CRASH(); + return false; +} + +void CCRendererSoftware::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) +{ + WebTransformationMatrix quadRectMatrix; + quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect()); + WebTransformationMatrix windowMatrix = frame.windowMatrix * frame.projectionMatrix * quadRectMatrix; + SkMatrix skWindowMatrix; + toSkMatrix(&skWindowMatrix, windowMatrix); + m_skCurrentCanvas->setMatrix(skWindowMatrix); + + m_skCurrentPaint.reset(); + if (quad->needsBlending()) + m_skCurrentPaint.setAlpha(quad->opacity() * 255); + else + m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrc_Mode); + + switch (quad->material()) { + case CCDrawQuad::DebugBorder: + drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::SolidColor: + drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::TextureContent: + drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::TiledContent: + drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); + break; + default: + drawUnsupportedQuad(frame, quad); + break; + } + + m_skCurrentCanvas->resetMatrix(); +} + +void CCRendererSoftware::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugBorderDrawQuad* quad) +{ + // We need to apply the matrix manually to have pixel-sized stroke width. + SkPoint vertices[4]; + toSkRect(quadVertexRect()).toQuad(vertices); + SkPoint transformedVertices[4]; + m_skCurrentCanvas->getTotalMatrix().mapPoints(transformedVertices, vertices, 4); + m_skCurrentCanvas->resetMatrix(); + + m_skCurrentPaint.setColor(quad->color()); + m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); + m_skCurrentPaint.setStyle(SkPaint::kStroke_Style); + m_skCurrentPaint.setStrokeWidth(quad->width()); + m_skCurrentCanvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, transformedVertices, m_skCurrentPaint); +} + +void CCRendererSoftware::drawSolidColorQuad(const DrawingFrame& frame, const CCSolidColorDrawQuad* quad) +{ + m_skCurrentPaint.setColor(quad->color()); + m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); + m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); +} + +void CCRendererSoftware::drawTextureQuad(const DrawingFrame& frame, const CCTextureDrawQuad* quad) +{ + if (!isSoftwareResource(quad->resourceId())) { + drawUnsupportedQuad(frame, quad); + return; + } + + // FIXME: Add support for non-premultiplied alpha. + CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvider, quad->resourceId()); + FloatRect uvRect = quad->uvRect(); + uvRect.scale(quad->quadRect().width(), quad->quadRect().height()); + SkIRect skUvRect = toSkIRect(enclosingIntRect(uvRect)); + if (quad->flipped()) + m_skCurrentCanvas->scale(1, -1); + m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &skUvRect, toSkRect(quadVertexRect()), &m_skCurrentPaint); +} + +void CCRendererSoftware::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad) +{ + ASSERT(isSoftwareResource(quad->resourceId())); + CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvider, quad->resourceId()); + + SkIRect uvRect = toSkIRect(IntRect(quad->textureOffset(), quad->quadRect().size())); + m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &uvRect, toSkRect(quadVertexRect()), &m_skCurrentPaint); +} + +void CCRendererSoftware::drawUnsupportedQuad(const DrawingFrame& frame, const CCDrawQuad* quad) +{ + m_skCurrentPaint.setColor(SK_ColorMAGENTA); + m_skCurrentPaint.setAlpha(quad->opacity() * 255); + m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); +} + +bool CCRendererSoftware::swapBuffers() +{ + if (CCProxy::hasImplThread()) + m_client->onSwapBuffersComplete(); + return true; +} + +void CCRendererSoftware::getFramebufferPixels(void *pixels, const IntRect& rect) +{ + SkBitmap fullBitmap = m_outputDevice->lock(false)->getSkBitmap(); + SkBitmap subsetBitmap; + SkIRect invertRect = SkIRect::MakeXYWH(rect.x(), viewportSize().height() - rect.maxY(), rect.width(), rect.height()); + fullBitmap.extractSubset(&subsetBitmap, invertRect); + subsetBitmap.copyPixelsTo(pixels, rect.width() * rect.height() * 4, rect.width() * 4); + m_outputDevice->unlock(); +} + +void CCRendererSoftware::setVisible(bool visible) +{ + if (m_visible == visible) + return; + m_visible = visible; +} + +} diff --git a/cc/CCRendererSoftware.h b/cc/CCRendererSoftware.h new file mode 100644 index 0000000..cf9476b --- /dev/null +++ b/cc/CCRendererSoftware.h @@ -0,0 +1,74 @@ +// 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 CCRendererSoftware_h +#define CCRendererSoftware_h + +#include "CCDirectRenderer.h" +#include "CCLayerTreeHost.h" +#include <public/WebCompositorSoftwareOutputDevice.h> + +namespace cc { + +class CCDebugBorderDrawQuad; +class CCRendererClient; +class CCResourceProvider; +class CCSolidColorDrawQuad; +class CCTextureDrawQuad; +class CCTileDrawQuad; + +class CCRendererSoftware : public CCDirectRenderer { + WTF_MAKE_NONCOPYABLE(CCRendererSoftware); +public: + static PassOwnPtr<CCRendererSoftware> create(CCRendererClient*, CCResourceProvider*, WebKit::WebCompositorSoftwareOutputDevice*); + virtual ~CCRendererSoftware(); + + virtual const RendererCapabilities& capabilities() const OVERRIDE; + + virtual void viewportChanged() OVERRIDE; + + virtual void finish() OVERRIDE; + + virtual bool swapBuffers() OVERRIDE; + + virtual void getFramebufferPixels(void *pixels, const IntRect&) OVERRIDE; + + virtual void setVisible(bool) OVERRIDE; + +protected: + virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; + virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) OVERRIDE; + virtual void setDrawViewportSize(const IntSize&) OVERRIDE; + virtual void enableScissorTestRect(const IntRect& scissorRect) OVERRIDE; + virtual void disableScissorTest() OVERRIDE; + virtual void clearFramebuffer(DrawingFrame&) OVERRIDE; + virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) OVERRIDE; + virtual void beginDrawingFrame(DrawingFrame&) OVERRIDE; + virtual void finishDrawingFrame(DrawingFrame&) OVERRIDE; + virtual bool flippedFramebuffer() const OVERRIDE; + +private: + CCRendererSoftware(CCRendererClient*, CCResourceProvider*, WebKit::WebCompositorSoftwareOutputDevice*); + + bool isSoftwareResource(CCResourceProvider::ResourceId) const; + + void drawDebugBorderQuad(const DrawingFrame&, const CCDebugBorderDrawQuad*); + void drawSolidColorQuad(const DrawingFrame&, const CCSolidColorDrawQuad*); + void drawTextureQuad(const DrawingFrame&, const CCTextureDrawQuad*); + void drawTileQuad(const DrawingFrame&, const CCTileDrawQuad*); + void drawUnsupportedQuad(const DrawingFrame&, const CCDrawQuad*); + + RendererCapabilities m_capabilities; + bool m_visible; + + WebKit::WebCompositorSoftwareOutputDevice* m_outputDevice; + SkCanvas m_skRootCanvas; + SkCanvas* m_skCurrentCanvas; + SkPaint m_skCurrentPaint; + OwnPtr<CCResourceProvider::ScopedWriteLockSoftware> m_currentFramebufferLock; +}; + +} + +#endif diff --git a/cc/CCRendererSoftwareTest.cpp b/cc/CCRendererSoftwareTest.cpp new file mode 100644 index 0000000..fee24cd --- /dev/null +++ b/cc/CCRendererSoftwareTest.cpp @@ -0,0 +1,162 @@ +// 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 "CCRendererSoftware.h" + +#include "CCAnimationTestCommon.h" +#include "CCGeometryTestUtils.h" +#include "CCQuadSink.h" +#include "CCRenderPass.h" +#include "CCRenderPassDrawQuad.h" +#include "CCSettings.h" +#include "CCSingleThreadProxy.h" // For DebugScopedSetImplThread +#include "CCSolidColorDrawQuad.h" +#include "CCTestCommon.h" +#include "CCTileDrawQuad.h" +#include "FakeWebCompositorSoftwareOutputDevice.h" +#include "FakeWebCompositorOutputSurface.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <wtf/OwnArrayPtr.h> + +using namespace cc; +using namespace WebKit; +using namespace WebKitTests; + +namespace { + +class CCRendererSoftwareTest : public testing::Test, public CCRendererClient { +public: + void initializeRenderer() { + m_outputSurface = FakeWebCompositorOutputSurface::createSoftware(adoptPtr(new FakeWebCompositorSoftwareOutputDevice)); + m_resourceProvider = CCResourceProvider::create(m_outputSurface.get()); + m_renderer = CCRendererSoftware::create(this, resourceProvider(), softwareDevice()); + } + + WebCompositorSoftwareOutputDevice* softwareDevice() const { return m_outputSurface->softwareDevice(); } + FakeWebCompositorOutputSurface* outputSurface() const { return m_outputSurface.get(); } + CCResourceProvider* resourceProvider() const { return m_resourceProvider.get(); } + CCRendererSoftware* renderer() const { return m_renderer.get(); } + void setViewportSize(IntSize viewportSize) { m_viewportSize = viewportSize; } + + // CCRendererClient implementation. + virtual const IntSize& deviceViewportSize() const OVERRIDE { return m_viewportSize; } + virtual const CCLayerTreeSettings& settings() const OVERRIDE { return m_settings; } + virtual void didLoseContext() OVERRIDE { } + virtual void onSwapBuffersComplete() OVERRIDE { } + virtual void setFullRootLayerDamage() OVERRIDE { } + virtual void releaseContentsTextures() OVERRIDE { } + virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE { } + +protected: + DebugScopedSetImplThread m_alwaysImplThread; + + OwnPtr<FakeWebCompositorOutputSurface> m_outputSurface; + OwnPtr<CCResourceProvider> m_resourceProvider; + OwnPtr<CCRendererSoftware> m_renderer; + IntSize m_viewportSize; + CCLayerTreeSettings m_settings; +}; + +class CCTestRenderPass : public CCRenderPass { +public: + static PassOwnPtr<CCTestRenderPass> create(CCRenderPass::Id id, IntRect outputRect, const WebTransformationMatrix& rootTransform) { return adoptPtr(new CCTestRenderPass(id, outputRect, rootTransform)); } + + void appendQuad(PassOwnPtr<CCDrawQuad> quad) { m_quadList.append(quad); } + +protected: + CCTestRenderPass(CCRenderPass::Id id, IntRect outputRect, const WebTransformationMatrix& rootTransform) : CCRenderPass(id, outputRect, rootTransform) { } +}; + + +TEST_F(CCRendererSoftwareTest, solidColorQuad) +{ + IntSize outerSize(100, 100); + int outerPixels = outerSize.width() * outerSize.height(); + IntSize innerSize(98, 98); + IntRect outerRect(IntPoint(), outerSize); + IntRect innerRect(IntPoint(1, 1), innerSize); + setViewportSize(outerSize); + + initializeRenderer(); + + OwnPtr<CCSharedQuadState> sharedQuadState = CCSharedQuadState::create(WebTransformationMatrix(), outerRect, outerRect, 1.0, true); + CCRenderPass::Id rootRenderPassId = CCRenderPass::Id(1, 1); + OwnPtr<CCRenderPass> rootRenderPass = CCTestRenderPass::create(rootRenderPassId, outerRect, WebTransformationMatrix()); + CCTestRenderPass* testRenderPass = static_cast<CCTestRenderPass*>(rootRenderPass.get()); + OwnPtr<CCDrawQuad> outerQuad = CCSolidColorDrawQuad::create(sharedQuadState.get(), outerRect, SK_ColorYELLOW); + OwnPtr<CCDrawQuad> innerQuad = CCSolidColorDrawQuad::create(sharedQuadState.get(), innerRect, SK_ColorCYAN); + testRenderPass->appendQuad(innerQuad.release()); + testRenderPass->appendQuad(outerQuad.release()); + + CCRenderPassList list; + CCRenderPassIdHashMap hashmap; + list.append(rootRenderPass.get()); + hashmap.add(rootRenderPassId, rootRenderPass.release()); + renderer()->drawFrame(list, hashmap); + + OwnArrayPtr<SkColor> pixels = adoptArrayPtr(new SkColor[deviceViewportSize().width() * deviceViewportSize().height()]); + renderer()->getFramebufferPixels(pixels.get(), outerRect); + + EXPECT_EQ(SK_ColorYELLOW, pixels[0]); + EXPECT_EQ(SK_ColorYELLOW, pixels[outerPixels - 1]); + EXPECT_EQ(SK_ColorCYAN, pixels[outerSize.width() + 1]); + EXPECT_EQ(SK_ColorCYAN, pixels[outerPixels - outerSize.width() - 2]); +} + +TEST_F(CCRendererSoftwareTest, tileQuad) +{ + IntSize outerSize(100, 100); + int outerPixels = outerSize.width() * outerSize.height(); + IntSize innerSize(98, 98); + int innerPixels = innerSize.width() * innerSize.height(); + IntRect outerRect(IntPoint(), outerSize); + IntRect innerRect(IntPoint(1, 1), innerSize); + setViewportSize(outerSize); + initializeRenderer(); + + CCResourceProvider::ResourceId resourceYellow = resourceProvider()->createResource(1, outerSize, GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny); + CCResourceProvider::ResourceId resourceCyan = resourceProvider()->createResource(1, innerSize, GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny); + + SkColor yellow = SK_ColorYELLOW; + SkColor cyan = SK_ColorCYAN; + OwnArrayPtr<SkColor> yellowPixels = adoptArrayPtr(new SkColor[outerPixels]); + OwnArrayPtr<SkColor> cyanPixels = adoptArrayPtr(new SkColor[innerPixels]); + for (int i = 0; i < outerPixels; i++) + yellowPixels[i] = yellow; + for (int i = 0; i < innerPixels; i++) + cyanPixels[i] = cyan; + + resourceProvider()->upload(resourceYellow, reinterpret_cast<uint8_t*>(yellowPixels.get()), IntRect(IntPoint(), outerSize), IntRect(IntPoint(), outerSize), IntSize()); + resourceProvider()->upload(resourceCyan, reinterpret_cast<uint8_t*>(cyanPixels.get()), IntRect(IntPoint(), innerSize), IntRect(IntPoint(), innerSize), IntSize()); + + IntRect rect = IntRect(IntPoint(), deviceViewportSize()); + + OwnPtr<CCSharedQuadState> sharedQuadState = CCSharedQuadState::create(WebTransformationMatrix(), outerRect, outerRect, 1.0, true); + CCRenderPass::Id rootRenderPassId = CCRenderPass::Id(1, 1); + OwnPtr<CCRenderPass> rootRenderPass = CCTestRenderPass::create(rootRenderPassId, IntRect(IntPoint(), deviceViewportSize()), WebTransformationMatrix()); + CCTestRenderPass* testRenderPass = static_cast<CCTestRenderPass*>(rootRenderPass.get()); + OwnPtr<CCDrawQuad> outerQuad = CCTileDrawQuad::create(sharedQuadState.get(), outerRect, outerRect, resourceYellow, IntPoint(), outerSize, 0, false, false, false, false, false); + OwnPtr<CCDrawQuad> innerQuad = CCTileDrawQuad::create(sharedQuadState.get(), innerRect, innerRect, resourceCyan, IntPoint(), innerSize, 0, false, false, false, false, false); + testRenderPass->appendQuad(innerQuad.release()); + testRenderPass->appendQuad(outerQuad.release()); + + CCRenderPassList list; + CCRenderPassIdHashMap hashmap; + list.append(rootRenderPass.get()); + hashmap.add(rootRenderPassId, rootRenderPass.release()); + renderer()->drawFrame(list, hashmap); + + OwnArrayPtr<SkColor> pixels = adoptArrayPtr(new SkColor[deviceViewportSize().width() * deviceViewportSize().height()]); + renderer()->getFramebufferPixels(pixels.get(), outerRect); + + EXPECT_EQ(SK_ColorYELLOW, pixels[0]); + EXPECT_EQ(SK_ColorYELLOW, pixels[outerPixels - 1]); + EXPECT_EQ(SK_ColorCYAN, pixels[outerSize.width() + 1]); + EXPECT_EQ(SK_ColorCYAN, pixels[outerPixels - outerSize.width() - 2]); +} + +} // namespace diff --git a/cc/CCResourceProvider.cpp b/cc/CCResourceProvider.cpp index 1cc5a29..97e692f 100644 --- a/cc/CCResourceProvider.cpp +++ b/cc/CCResourceProvider.cpp @@ -452,11 +452,9 @@ bool CCResourceProvider::initialize() ASSERT(CCProxy::isImplThread()); WebGraphicsContext3D* context3d = m_context->context3D(); if (!context3d) { - m_maxTextureSize = INT_MAX; + m_maxTextureSize = INT_MAX / 2; m_textureUploader = UnthrottledTextureUploader::create(); - - // FIXME: Implement this path for software compositing. - return false; + return true; } if (!context3d->makeContextCurrent()) return false; @@ -101,6 +101,8 @@ 'CCRenderer.h', 'CCRendererGL.cpp', 'CCRendererGL.h', + 'CCRendererSoftware.cpp', + 'CCRendererSoftware.h', 'CCRenderingStats.h', 'CCResourceProvider.cpp', 'CCResourceProvider.h', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 9df85b9..8d9800c 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -27,6 +27,7 @@ 'CCOcclusionTrackerTest.cpp', 'CCPrioritizedTextureTest.cpp', 'CCQuadCullerTest.cpp', + 'CCRendererSoftwareTest.cpp', 'CCRenderPassTest.cpp', 'CCRenderSurfaceFiltersTest.cpp', 'CCRenderSurfaceTest.cpp', @@ -72,6 +73,7 @@ 'test/FakeCCLayerTreeHostClient.cpp', 'test/FakeCCLayerTreeHostClient.h', 'test/FakeGraphicsContext3DTest.cpp', + 'test/FakeWebCompositorSoftwareOutputDevice.h', 'test/FakeWebCompositorOutputSurface.h', 'test/FakeWebGraphicsContext3D.h', 'test/FakeWebScrollbarThemeGeometry.h', diff --git a/cc/test/FakeWebCompositorOutputSurface.h b/cc/test/FakeWebCompositorOutputSurface.h index 97ebbac..01b6638 100644 --- a/cc/test/FakeWebCompositorOutputSurface.h +++ b/cc/test/FakeWebCompositorOutputSurface.h @@ -5,6 +5,7 @@ #ifndef FakeWebCompositorOutputSurface_h #define FakeWebCompositorOutputSurface_h +#include "FakeWebCompositorSoftwareOutputDevice.h" #include <public/WebCompositorOutputSurface.h> #include <public/WebGraphicsContext3D.h> #include <wtf/OwnPtr.h> @@ -19,9 +20,15 @@ public: return adoptPtr(new FakeWebCompositorOutputSurface(context3D)); } + static inline PassOwnPtr<FakeWebCompositorOutputSurface> createSoftware(PassOwnPtr<WebCompositorSoftwareOutputDevice> softwareDevice) + { + return adoptPtr(new FakeWebCompositorOutputSurface(softwareDevice)); + } virtual bool bindToClient(WebCompositorOutputSurfaceClient* client) OVERRIDE { + if (!m_context3D) + return true; ASSERT(client); if (!m_context3D->makeContextCurrent()) return false; @@ -38,6 +45,10 @@ public: { return m_context3D.get(); } + virtual WebCompositorSoftwareOutputDevice* softwareDevice() const OVERRIDE + { + return m_softwareDevice.get(); + } virtual void sendFrameToParentCompositor(const WebCompositorFrame&) OVERRIDE { @@ -49,7 +60,13 @@ private: m_context3D = context3D; } + explicit FakeWebCompositorOutputSurface(PassOwnPtr<WebCompositorSoftwareOutputDevice> softwareDevice) + { + m_softwareDevice = softwareDevice; + } + OwnPtr<WebGraphicsContext3D> m_context3D; + OwnPtr<WebCompositorSoftwareOutputDevice> m_softwareDevice; Capabilities m_capabilities; WebCompositorOutputSurfaceClient* m_client; }; diff --git a/cc/test/FakeWebCompositorSoftwareOutputDevice.h b/cc/test/FakeWebCompositorSoftwareOutputDevice.h new file mode 100644 index 0000000..f362719 --- /dev/null +++ b/cc/test/FakeWebCompositorSoftwareOutputDevice.h @@ -0,0 +1,45 @@ +// 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 FakeWebCompositorSoftwareOutputDevice_h +#define FakeWebCompositorSoftwareOutputDevice_h + +#include "SkDevice.h" +#include <public/WebCompositorSoftwareOutputDevice.h> +#include <public/WebImage.h> +#include <public/WebSize.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> + +namespace WebKit { + +class FakeWebCompositorSoftwareOutputDevice : public WebCompositorSoftwareOutputDevice { +public: + virtual WebImage* lock(bool forWrite) OVERRIDE + { + ASSERT(m_device); + m_image = m_device->accessBitmap(forWrite); + return &m_image; + } + virtual void unlock() OVERRIDE + { + m_image.reset(); + } + + virtual void didChangeViewportSize(WebSize size) OVERRIDE + { + if (m_device.get() && size.width == m_device->width() && size.height == m_device->height()) + return; + + m_device = adoptPtr(new SkDevice(SkBitmap::kARGB_8888_Config, size.width, size.height, true)); + } + +private: + OwnPtr<SkDevice> m_device; + WebImage m_image; +}; + +} // namespace WebKit + +#endif // FakeWebCompositorSoftwareOutputDevice_h |