Index: cc/CCRendererSoftware.cpp |
diff --git a/cc/CCRendererSoftware.cpp b/cc/CCRendererSoftware.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f28a9e1245955c7f78713fca170fa18ee8354119 |
--- /dev/null |
+++ b/cc/CCRendererSoftware.cpp |
@@ -0,0 +1,308 @@ |
+/* |
+ * Copyright (C) 2012 Google Inc. All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * |
+ * 1. Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * 2. Redistributions in binary form must reproduce the above copyright |
+ * notice, this list of conditions and the following disclaimer in the |
+ * documentation and/or other materials provided with the distribution. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ */ |
+ |
+#include "config.h" |
+ |
+#include "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 "UnthrottledTextureUploader.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()); |
+} |
+ |
+class SoftwareTextureCopier : public TextureCopier { |
+ WTF_MAKE_NONCOPYABLE(SoftwareTextureCopier); |
+public: |
+ static PassOwnPtr<SoftwareTextureCopier> create() |
+ { |
+ return adoptPtr(new SoftwareTextureCopier()); |
+ } |
+ virtual void copyTexture(TextureCopier::Parameters) OVERRIDE { /* FIXME */ } |
+ virtual void flush() OVERRIDE { } |
+ |
+private: |
+ SoftwareTextureCopier() { } |
+}; |
+ |
+} // 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_textureCopier(SoftwareTextureCopier::create()) |
+ , m_textureUploader(UnthrottledTextureUploader::create()) |
+ , 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() |
+{ |
+} |
+ |
+void CCRendererSoftware::viewportChanged() |
+{ |
+ m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewportSize().height())); |
danakj
2012/09/19 18:35:14
How come the software renderer needs a call like t
aelias_OOO_until_Jul13
2012/09/19 19:58:27
For the test harness and GL adapter, they need to
danakj
2012/09/19 20:06:18
I see, thanks.
|
+} |
+ |
+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(); |
+} |
+ |
+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. |
danakj
2012/09/19 18:35:14
Do you want an assert quad->premultipliedAlpha() o
|
+ 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; |
+} |
+ |
+} |