summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authoraelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-24 21:32:57 +0000
committeraelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-24 21:32:57 +0000
commitd61675de46031d9db57d198e482abaccc79c63e7 (patch)
tree8ecc4801ccce660ecb55ae7038fcf5e9a60ba51b /cc
parenta02f64e4b986222548e9cd5bfdcbc940e22e69be (diff)
downloadchromium_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.cpp2
-rw-r--r--cc/CCDirectRenderer.h1
-rw-r--r--cc/CCLayerTreeHostImpl.cpp19
-rw-r--r--cc/CCRendererGL.cpp5
-rw-r--r--cc/CCRendererGL.h1
-rw-r--r--cc/CCRendererSoftware.cpp280
-rw-r--r--cc/CCRendererSoftware.h74
-rw-r--r--cc/CCRendererSoftwareTest.cpp162
-rw-r--r--cc/CCResourceProvider.cpp6
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/cc_tests.gyp2
-rw-r--r--cc/test/FakeWebCompositorOutputSurface.h17
-rw-r--r--cc/test/FakeWebCompositorSoftwareOutputDevice.h45
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;
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 62cd798..3fa30a7 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -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