1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "CCRendererSoftware.h"
9 #include "CCDebugBorderDrawQuad.h"
10 #include "CCSolidColorDrawQuad.h"
11 #include "CCTextureDrawQuad.h"
12 #include "CCTileDrawQuad.h"
16 #include "SkPixelRef.h"
17 #include <GLES2/gl2.h>
18 #include <public/WebImage.h>
19 #include <public/WebSize.h>
20 #include <public/WebTransformationMatrix.h>
22 using WebKit::WebCompositorSoftwareOutputDevice
;
23 using WebKit::WebImage
;
24 using WebKit::WebSize
;
25 using WebKit::WebTransformationMatrix
;
31 SkRect
toSkRect(const FloatRect
& rect
)
33 return SkRect::MakeXYWH(rect
.x(), rect
.y(), rect
.width(), rect
.height());
36 SkIRect
toSkIRect(const IntRect
& rect
)
38 return SkIRect::MakeXYWH(rect
.x(), rect
.y(), rect
.width(), rect
.height());
41 void toSkMatrix(SkMatrix
* flattened
, const WebTransformationMatrix
& m
)
43 // Convert from 4x4 to 3x3 by dropping the third row and column.
44 flattened
->set(0, m
.m11());
45 flattened
->set(1, m
.m21());
46 flattened
->set(2, m
.m41());
47 flattened
->set(3, m
.m12());
48 flattened
->set(4, m
.m22());
49 flattened
->set(5, m
.m42());
50 flattened
->set(6, m
.m14());
51 flattened
->set(7, m
.m24());
52 flattened
->set(8, m
.m44());
55 } // anonymous namespace
57 PassOwnPtr
<CCRendererSoftware
> CCRendererSoftware::create(CCRendererClient
* client
, CCResourceProvider
* resourceProvider
, WebCompositorSoftwareOutputDevice
* outputDevice
)
59 return adoptPtr(new CCRendererSoftware(client
, resourceProvider
, outputDevice
));
62 CCRendererSoftware::CCRendererSoftware(CCRendererClient
* client
, CCResourceProvider
* resourceProvider
, WebCompositorSoftwareOutputDevice
* outputDevice
)
63 : CCDirectRenderer(client
, resourceProvider
)
65 , m_outputDevice(outputDevice
)
66 , m_skCurrentCanvas(0)
68 m_resourceProvider
->setDefaultResourceType(CCResourceProvider::Bitmap
);
70 m_capabilities
.maxTextureSize
= INT_MAX
;
71 m_capabilities
.bestTextureFormat
= GraphicsContext3D::RGBA
;
72 m_capabilities
.contextHasCachedFrontBuffer
= true;
73 m_capabilities
.usingSetVisibility
= true;
78 CCRendererSoftware::~CCRendererSoftware()
82 const RendererCapabilities
& CCRendererSoftware::capabilities() const
84 return m_capabilities
;
87 void CCRendererSoftware::viewportChanged()
89 m_outputDevice
->didChangeViewportSize(WebSize(viewportSize().width(), viewportSize().height()));
92 void CCRendererSoftware::beginDrawingFrame(DrawingFrame
& frame
)
94 m_skRootCanvas
= adoptPtr(new SkCanvas(m_outputDevice
->lock(true)->getSkBitmap()));
97 void CCRendererSoftware::finishDrawingFrame(DrawingFrame
& frame
)
99 m_currentFramebufferLock
.clear();
100 m_skCurrentCanvas
= 0;
101 m_skRootCanvas
.clear();
102 m_outputDevice
->unlock();
105 bool CCRendererSoftware::flippedFramebuffer() const
110 void CCRendererSoftware::finish()
114 void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame
& frame
)
116 m_currentFramebufferLock
.clear();
117 m_skCurrentCanvas
= m_skRootCanvas
.get();
120 bool CCRendererSoftware::bindFramebufferToTexture(DrawingFrame
& frame
, const CCScopedTexture
* texture
, const IntRect
& framebufferRect
)
122 m_currentFramebufferLock
= adoptPtr(new CCResourceProvider::ScopedWriteLockSoftware(m_resourceProvider
, texture
->id()));
123 m_skCurrentCanvas
= m_currentFramebufferLock
->skCanvas();
124 initializeMatrices(frame
, framebufferRect
, false);
125 setDrawViewportSize(framebufferRect
.size());
130 void CCRendererSoftware::enableScissorTestRect(const IntRect
& scissorRect
)
132 m_skCurrentCanvas
->clipRect(toSkRect(scissorRect
), SkRegion::kReplace_Op
);
135 void CCRendererSoftware::disableScissorTest()
137 IntRect
canvasRect(IntPoint(), viewportSize());
138 m_skCurrentCanvas
->clipRect(toSkRect(canvasRect
), SkRegion::kReplace_Op
);
141 void CCRendererSoftware::clearFramebuffer(DrawingFrame
& frame
)
143 m_skCurrentCanvas
->clear(SK_ColorGREEN
);
146 void CCRendererSoftware::setDrawViewportSize(const IntSize
& viewportSize
)
150 bool CCRendererSoftware::isSoftwareResource(CCResourceProvider::ResourceId id
) const
152 switch (m_resourceProvider
->resourceType(id
)) {
153 case CCResourceProvider::GLTexture
:
155 case CCResourceProvider::Bitmap
:
163 void CCRendererSoftware::drawQuad(DrawingFrame
& frame
, const CCDrawQuad
* quad
)
165 WebTransformationMatrix quadRectMatrix
;
166 quadRectTransform(&quadRectMatrix
, quad
->quadTransform(), quad
->quadRect());
167 WebTransformationMatrix windowMatrix
= frame
.windowMatrix
* frame
.projectionMatrix
* quadRectMatrix
;
168 SkMatrix skWindowMatrix
;
169 toSkMatrix(&skWindowMatrix
, windowMatrix
);
170 m_skCurrentCanvas
->setMatrix(skWindowMatrix
);
172 m_skCurrentPaint
.reset();
173 if (quad
->needsBlending())
174 m_skCurrentPaint
.setAlpha(quad
->opacity() * 255);
176 m_skCurrentPaint
.setXfermodeMode(SkXfermode::kSrc_Mode
);
178 switch (quad
->material()) {
179 case CCDrawQuad::DebugBorder
:
180 drawDebugBorderQuad(frame
, CCDebugBorderDrawQuad::materialCast(quad
));
182 case CCDrawQuad::SolidColor
:
183 drawSolidColorQuad(frame
, CCSolidColorDrawQuad::materialCast(quad
));
185 case CCDrawQuad::TextureContent
:
186 drawTextureQuad(frame
, CCTextureDrawQuad::materialCast(quad
));
188 case CCDrawQuad::TiledContent
:
189 drawTileQuad(frame
, CCTileDrawQuad::materialCast(quad
));
192 drawUnsupportedQuad(frame
, quad
);
196 m_skCurrentCanvas
->resetMatrix();
199 void CCRendererSoftware::drawDebugBorderQuad(const DrawingFrame
& frame
, const CCDebugBorderDrawQuad
* quad
)
201 // We need to apply the matrix manually to have pixel-sized stroke width.
203 toSkRect(quadVertexRect()).toQuad(vertices
);
204 SkPoint transformedVertices
[4];
205 m_skCurrentCanvas
->getTotalMatrix().mapPoints(transformedVertices
, vertices
, 4);
206 m_skCurrentCanvas
->resetMatrix();
208 m_skCurrentPaint
.setColor(quad
->color());
209 m_skCurrentPaint
.setAlpha(quad
->opacity() * SkColorGetA(quad
->color()));
210 m_skCurrentPaint
.setStyle(SkPaint::kStroke_Style
);
211 m_skCurrentPaint
.setStrokeWidth(quad
->width());
212 m_skCurrentCanvas
->drawPoints(SkCanvas::kPolygon_PointMode
, 4, transformedVertices
, m_skCurrentPaint
);
215 void CCRendererSoftware::drawSolidColorQuad(const DrawingFrame
& frame
, const CCSolidColorDrawQuad
* quad
)
217 m_skCurrentPaint
.setColor(quad
->color());
218 m_skCurrentPaint
.setAlpha(quad
->opacity() * SkColorGetA(quad
->color()));
219 m_skCurrentCanvas
->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint
);
222 void CCRendererSoftware::drawTextureQuad(const DrawingFrame
& frame
, const CCTextureDrawQuad
* quad
)
224 if (!isSoftwareResource(quad
->resourceId())) {
225 drawUnsupportedQuad(frame
, quad
);
229 // FIXME: Add support for non-premultiplied alpha.
230 CCResourceProvider::ScopedReadLockSoftware
quadResourceLock(m_resourceProvider
, quad
->resourceId());
231 FloatRect uvRect
= quad
->uvRect();
232 uvRect
.scale(quad
->quadRect().width(), quad
->quadRect().height());
233 SkIRect skUvRect
= toSkIRect(enclosingIntRect(uvRect
));
235 m_skCurrentCanvas
->scale(1, -1);
236 m_skCurrentCanvas
->drawBitmapRect(*quadResourceLock
.skBitmap(), &skUvRect
, toSkRect(quadVertexRect()), &m_skCurrentPaint
);
239 void CCRendererSoftware::drawTileQuad(const DrawingFrame
& frame
, const CCTileDrawQuad
* quad
)
241 ASSERT(isSoftwareResource(quad
->resourceId()));
242 CCResourceProvider::ScopedReadLockSoftware
quadResourceLock(m_resourceProvider
, quad
->resourceId());
244 SkIRect uvRect
= toSkIRect(IntRect(quad
->textureOffset(), quad
->quadRect().size()));
245 m_skCurrentCanvas
->drawBitmapRect(*quadResourceLock
.skBitmap(), &uvRect
, toSkRect(quadVertexRect()), &m_skCurrentPaint
);
248 void CCRendererSoftware::drawUnsupportedQuad(const DrawingFrame
& frame
, const CCDrawQuad
* quad
)
250 m_skCurrentPaint
.setColor(SK_ColorMAGENTA
);
251 m_skCurrentPaint
.setAlpha(quad
->opacity() * 255);
252 m_skCurrentCanvas
->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint
);
255 bool CCRendererSoftware::swapBuffers()
257 if (CCProxy::hasImplThread())
258 m_client
->onSwapBuffersComplete();
262 void CCRendererSoftware::getFramebufferPixels(void *pixels
, const IntRect
& rect
)
264 SkBitmap fullBitmap
= m_outputDevice
->lock(false)->getSkBitmap();
265 SkBitmap subsetBitmap
;
266 SkIRect invertRect
= SkIRect::MakeXYWH(rect
.x(), viewportSize().height() - rect
.maxY(), rect
.width(), rect
.height());
267 fullBitmap
.extractSubset(&subsetBitmap
, invertRect
);
268 subsetBitmap
.copyPixelsTo(pixels
, rect
.width() * rect
.height() * 4, rect
.width() * 4);
269 m_outputDevice
->unlock();
272 void CCRendererSoftware::setVisible(bool visible
)
274 if (m_visible
== visible
)