OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "config.h" |
| 6 |
| 7 #include "CCRendererSoftware.h" |
| 8 |
| 9 #include "CCDebugBorderDrawQuad.h" |
| 10 #include "CCSolidColorDrawQuad.h" |
| 11 #include "CCTextureDrawQuad.h" |
| 12 #include "CCTileDrawQuad.h" |
| 13 #include "SkCanvas.h" |
| 14 #include "SkColor.h" |
| 15 #include "SkMatrix.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> |
| 21 |
| 22 using WebKit::WebCompositorSoftwareOutputDevice; |
| 23 using WebKit::WebImage; |
| 24 using WebKit::WebSize; |
| 25 using WebKit::WebTransformationMatrix; |
| 26 |
| 27 namespace cc { |
| 28 |
| 29 namespace { |
| 30 |
| 31 SkRect toSkRect(const FloatRect& rect) |
| 32 { |
| 33 return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); |
| 34 } |
| 35 |
| 36 SkIRect toSkIRect(const IntRect& rect) |
| 37 { |
| 38 return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); |
| 39 } |
| 40 |
| 41 void toSkMatrix(SkMatrix* flattened, const WebTransformationMatrix& m) |
| 42 { |
| 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()); |
| 53 } |
| 54 |
| 55 } // anonymous namespace |
| 56 |
| 57 PassOwnPtr<CCRendererSoftware> CCRendererSoftware::create(CCRendererClient* clie
nt, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* out
putDevice) |
| 58 { |
| 59 return adoptPtr(new CCRendererSoftware(client, resourceProvider, outputDevic
e)); |
| 60 } |
| 61 |
| 62 CCRendererSoftware::CCRendererSoftware(CCRendererClient* client, CCResourceProvi
der* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) |
| 63 : CCDirectRenderer(client, resourceProvider) |
| 64 , m_visible(true) |
| 65 , m_outputDevice(outputDevice) |
| 66 , m_skRootCanvas(0) |
| 67 , m_skCurrentCanvas(0) |
| 68 { |
| 69 m_resourceProvider->setDefaultResourceType(CCResourceProvider::Bitmap); |
| 70 |
| 71 m_capabilities.maxTextureSize = INT_MAX; |
| 72 m_capabilities.bestTextureFormat = GraphicsContext3D::RGBA; |
| 73 m_capabilities.contextHasCachedFrontBuffer = true; |
| 74 m_capabilities.usingSetVisibility = true; |
| 75 |
| 76 viewportChanged(); |
| 77 } |
| 78 |
| 79 CCRendererSoftware::~CCRendererSoftware() |
| 80 { |
| 81 } |
| 82 |
| 83 const RendererCapabilities& CCRendererSoftware::capabilities() const |
| 84 { |
| 85 return m_capabilities; |
| 86 } |
| 87 |
| 88 void CCRendererSoftware::viewportChanged() |
| 89 { |
| 90 m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewpo
rtSize().height())); |
| 91 } |
| 92 |
| 93 void CCRendererSoftware::beginDrawingFrame(DrawingFrame& frame) |
| 94 { |
| 95 m_skRootCanvas.setBitmapDevice(m_outputDevice->lock(true)->getSkBitmap()); |
| 96 } |
| 97 |
| 98 void CCRendererSoftware::finishDrawingFrame(DrawingFrame& frame) |
| 99 { |
| 100 m_currentFramebufferLock.clear(); |
| 101 m_skCurrentCanvas = 0; |
| 102 m_skRootCanvas.setDevice(0); |
| 103 m_outputDevice->unlock(); |
| 104 } |
| 105 |
| 106 bool CCRendererSoftware::flippedFramebuffer() const |
| 107 { |
| 108 return false; |
| 109 } |
| 110 |
| 111 void CCRendererSoftware::finish() |
| 112 { |
| 113 } |
| 114 |
| 115 void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame& frame) |
| 116 { |
| 117 m_currentFramebufferLock.clear(); |
| 118 m_skCurrentCanvas = &m_skRootCanvas; |
| 119 } |
| 120 |
| 121 bool CCRendererSoftware::bindFramebufferToTexture(DrawingFrame& frame, const CCS
copedTexture* texture, const IntRect& framebufferRect) |
| 122 { |
| 123 m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockS
oftware(m_resourceProvider, texture->id())); |
| 124 m_skCurrentCanvas = m_currentFramebufferLock->skCanvas(); |
| 125 initializeMatrices(frame, framebufferRect, false); |
| 126 setDrawViewportSize(framebufferRect.size()); |
| 127 |
| 128 return true; |
| 129 } |
| 130 |
| 131 void CCRendererSoftware::enableScissorTestRect(const IntRect& scissorRect) |
| 132 { |
| 133 m_skCurrentCanvas->clipRect(toSkRect(scissorRect), SkRegion::kReplace_Op); |
| 134 } |
| 135 |
| 136 void CCRendererSoftware::disableScissorTest() |
| 137 { |
| 138 IntRect canvasRect(IntPoint(), viewportSize()); |
| 139 m_skCurrentCanvas->clipRect(toSkRect(canvasRect), SkRegion::kReplace_Op); |
| 140 } |
| 141 |
| 142 void CCRendererSoftware::clearFramebuffer(DrawingFrame& frame) |
| 143 { |
| 144 m_skCurrentCanvas->clear(SK_ColorGREEN); |
| 145 } |
| 146 |
| 147 void CCRendererSoftware::setDrawViewportSize(const IntSize& viewportSize) |
| 148 { |
| 149 } |
| 150 |
| 151 bool CCRendererSoftware::isSoftwareResource(CCResourceProvider::ResourceId id) c
onst |
| 152 { |
| 153 switch (m_resourceProvider->resourceType(id)) { |
| 154 case CCResourceProvider::GLTexture: |
| 155 return false; |
| 156 case CCResourceProvider::Bitmap: |
| 157 return true; |
| 158 } |
| 159 |
| 160 CRASH(); |
| 161 return false; |
| 162 } |
| 163 |
| 164 void CCRendererSoftware::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) |
| 165 { |
| 166 WebTransformationMatrix quadRectMatrix; |
| 167 quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect()); |
| 168 WebTransformationMatrix windowMatrix = frame.windowMatrix * frame.projection
Matrix * quadRectMatrix; |
| 169 SkMatrix skWindowMatrix; |
| 170 toSkMatrix(&skWindowMatrix, windowMatrix); |
| 171 m_skCurrentCanvas->setMatrix(skWindowMatrix); |
| 172 |
| 173 m_skCurrentPaint.reset(); |
| 174 if (quad->needsBlending()) |
| 175 m_skCurrentPaint.setAlpha(quad->opacity() * 255); |
| 176 else |
| 177 m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
| 178 |
| 179 switch (quad->material()) { |
| 180 case CCDrawQuad::DebugBorder: |
| 181 drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); |
| 182 break; |
| 183 case CCDrawQuad::SolidColor: |
| 184 drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); |
| 185 break; |
| 186 case CCDrawQuad::TextureContent: |
| 187 drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); |
| 188 break; |
| 189 case CCDrawQuad::TiledContent: |
| 190 drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); |
| 191 break; |
| 192 default: |
| 193 drawUnsupportedQuad(frame, quad); |
| 194 break; |
| 195 } |
| 196 |
| 197 m_skCurrentCanvas->resetMatrix(); |
| 198 } |
| 199 |
| 200 void CCRendererSoftware::drawDebugBorderQuad(const DrawingFrame& frame, const CC
DebugBorderDrawQuad* quad) |
| 201 { |
| 202 // We need to apply the matrix manually to have pixel-sized stroke width. |
| 203 SkPoint vertices[4]; |
| 204 toSkRect(quadVertexRect()).toQuad(vertices); |
| 205 SkPoint transformedVertices[4]; |
| 206 m_skCurrentCanvas->getTotalMatrix().mapPoints(transformedVertices, vertices,
4); |
| 207 m_skCurrentCanvas->resetMatrix(); |
| 208 |
| 209 m_skCurrentPaint.setColor(quad->color()); |
| 210 m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); |
| 211 m_skCurrentPaint.setStyle(SkPaint::kStroke_Style); |
| 212 m_skCurrentPaint.setStrokeWidth(quad->width()); |
| 213 m_skCurrentCanvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, transformedVe
rtices, m_skCurrentPaint); |
| 214 } |
| 215 |
| 216 void CCRendererSoftware::drawSolidColorQuad(const DrawingFrame& frame, const CCS
olidColorDrawQuad* quad) |
| 217 { |
| 218 m_skCurrentPaint.setColor(quad->color()); |
| 219 m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); |
| 220 m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); |
| 221 } |
| 222 |
| 223 void CCRendererSoftware::drawTextureQuad(const DrawingFrame& frame, const CCText
ureDrawQuad* quad) |
| 224 { |
| 225 if (!isSoftwareResource(quad->resourceId())) { |
| 226 drawUnsupportedQuad(frame, quad); |
| 227 return; |
| 228 } |
| 229 |
| 230 // FIXME: Add support for non-premultiplied alpha. |
| 231 CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvid
er, quad->resourceId()); |
| 232 FloatRect uvRect = quad->uvRect(); |
| 233 uvRect.scale(quad->quadRect().width(), quad->quadRect().height()); |
| 234 SkIRect skUvRect = toSkIRect(enclosingIntRect(uvRect)); |
| 235 if (quad->flipped()) |
| 236 m_skCurrentCanvas->scale(1, -1); |
| 237 m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &skUvRect, t
oSkRect(quadVertexRect()), &m_skCurrentPaint); |
| 238 } |
| 239 |
| 240 void CCRendererSoftware::drawTileQuad(const DrawingFrame& frame, const CCTileDra
wQuad* quad) |
| 241 { |
| 242 ASSERT(isSoftwareResource(quad->resourceId())); |
| 243 CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvid
er, quad->resourceId()); |
| 244 |
| 245 SkIRect uvRect = toSkIRect(IntRect(quad->textureOffset(), quad->quadRect().s
ize())); |
| 246 m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &uvRect, toS
kRect(quadVertexRect()), &m_skCurrentPaint); |
| 247 } |
| 248 |
| 249 void CCRendererSoftware::drawUnsupportedQuad(const DrawingFrame& frame, const CC
DrawQuad* quad) |
| 250 { |
| 251 m_skCurrentPaint.setColor(SK_ColorMAGENTA); |
| 252 m_skCurrentPaint.setAlpha(quad->opacity() * 255); |
| 253 m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); |
| 254 } |
| 255 |
| 256 bool CCRendererSoftware::swapBuffers() |
| 257 { |
| 258 if (CCProxy::hasImplThread()) |
| 259 m_client->onSwapBuffersComplete(); |
| 260 return true; |
| 261 } |
| 262 |
| 263 void CCRendererSoftware::getFramebufferPixels(void *pixels, const IntRect& rect) |
| 264 { |
| 265 SkBitmap fullBitmap = m_outputDevice->lock(false)->getSkBitmap(); |
| 266 SkBitmap subsetBitmap; |
| 267 SkIRect invertRect = SkIRect::MakeXYWH(rect.x(), viewportSize().height() - r
ect.maxY(), rect.width(), rect.height()); |
| 268 fullBitmap.extractSubset(&subsetBitmap, invertRect); |
| 269 subsetBitmap.copyPixelsTo(pixels, rect.width() * rect.height() * 4, rect.wid
th() * 4); |
| 270 m_outputDevice->unlock(); |
| 271 } |
| 272 |
| 273 void CCRendererSoftware::setVisible(bool visible) |
| 274 { |
| 275 if (m_visible == visible) |
| 276 return; |
| 277 m_visible = visible; |
| 278 } |
| 279 |
| 280 } |
OLD | NEW |