summaryrefslogtreecommitdiffstats
path: root/cc/software_renderer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc/software_renderer.cc')
-rw-r--r--cc/software_renderer.cc279
1 files changed, 279 insertions, 0 deletions
diff --git a/cc/software_renderer.cc b/cc/software_renderer.cc
new file mode 100644
index 0000000..e833780
--- /dev/null
+++ b/cc/software_renderer.cc
@@ -0,0 +1,279 @@
+// 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_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 = adoptPtr(new SkCanvas(m_outputDevice->lock(true)->getSkBitmap()));
+}
+
+void CCRendererSoftware::finishDrawingFrame(DrawingFrame& frame)
+{
+ m_currentFramebufferLock.clear();
+ m_skCurrentCanvas = 0;
+ m_skRootCanvas.clear();
+ m_outputDevice->unlock();
+}
+
+bool CCRendererSoftware::flippedFramebuffer() const
+{
+ return false;
+}
+
+void CCRendererSoftware::finish()
+{
+}
+
+void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame& frame)
+{
+ m_currentFramebufferLock.clear();
+ m_skCurrentCanvas = m_skRootCanvas.get();
+}
+
+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;
+}
+
+}