Reenable NullOpenerRedirectForksProcess, as the offending patch has been reverted
[chromium-blink-merge.git] / cc / software_renderer.cc
blobd7aa06d21534613e42ab4a2c4e9fbfd49fcf4972
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.
5 #include "cc/software_renderer.h"
7 #include "base/debug/trace_event.h"
8 #include "cc/debug_border_draw_quad.h"
9 #include "cc/render_pass_draw_quad.h"
10 #include "cc/solid_color_draw_quad.h"
11 #include "cc/texture_draw_quad.h"
12 #include "cc/tile_draw_quad.h"
13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "third_party/skia/include/core/SkColor.h"
15 #include "third_party/skia/include/core/SkMatrix.h"
16 #include "third_party/skia/include/core/SkShader.h"
17 #include "third_party/skia/include/effects/SkLayerRasterizer.h"
18 #include "ui/gfx/rect_conversions.h"
19 #include "ui/gfx/skia_util.h"
20 #include <public/WebCompositorSoftwareOutputDevice.h>
21 #include <public/WebImage.h>
22 #include <public/WebSize.h>
23 #include <public/WebTransformationMatrix.h>
25 using WebKit::WebCompositorSoftwareOutputDevice;
26 using WebKit::WebSize;
27 using WebKit::WebTransformationMatrix;
29 namespace cc {
31 namespace {
33 void toSkMatrix(SkMatrix* flattened, const WebTransformationMatrix& m)
35 // Convert from 4x4 to 3x3 by dropping the third row and column.
36 flattened->set(0, SkDoubleToScalar(m.m11()));
37 flattened->set(1, SkDoubleToScalar(m.m21()));
38 flattened->set(2, SkDoubleToScalar(m.m41()));
39 flattened->set(3, SkDoubleToScalar(m.m12()));
40 flattened->set(4, SkDoubleToScalar(m.m22()));
41 flattened->set(5, SkDoubleToScalar(m.m42()));
42 flattened->set(6, SkDoubleToScalar(m.m14()));
43 flattened->set(7, SkDoubleToScalar(m.m24()));
44 flattened->set(8, SkDoubleToScalar(m.m44()));
47 bool isScaleAndTranslate(const SkMatrix& matrix)
49 return SkScalarNearlyZero(matrix[SkMatrix::kMSkewX]) &&
50 SkScalarNearlyZero(matrix[SkMatrix::kMSkewY]) &&
51 SkScalarNearlyZero(matrix[SkMatrix::kMPersp0]) &&
52 SkScalarNearlyZero(matrix[SkMatrix::kMPersp1]) &&
53 SkScalarNearlyZero(matrix[SkMatrix::kMPersp2] - 1.0f);
56 } // anonymous namespace
58 scoped_ptr<SoftwareRenderer> SoftwareRenderer::create(RendererClient* client, ResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice)
60 return make_scoped_ptr(new SoftwareRenderer(client, resourceProvider, outputDevice));
63 SoftwareRenderer::SoftwareRenderer(RendererClient* client, ResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice)
64 : DirectRenderer(client, resourceProvider)
65 , m_visible(true)
66 , m_outputDevice(outputDevice)
67 , m_skCurrentCanvas(0)
69 m_resourceProvider->setDefaultResourceType(ResourceProvider::Bitmap);
71 m_capabilities.maxTextureSize = INT_MAX;
72 m_capabilities.bestTextureFormat = GL_RGBA;
73 m_capabilities.contextHasCachedFrontBuffer = true;
74 m_capabilities.usingSetVisibility = true;
76 viewportChanged();
79 SoftwareRenderer::~SoftwareRenderer()
83 const RendererCapabilities& SoftwareRenderer::capabilities() const
85 return m_capabilities;
88 void SoftwareRenderer::viewportChanged()
90 m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewportSize().height()));
93 void SoftwareRenderer::beginDrawingFrame(DrawingFrame& frame)
95 TRACE_EVENT0("cc", "SoftwareRenderer::beginDrawingFrame");
96 m_skRootCanvas = make_scoped_ptr(new SkCanvas(m_outputDevice->lock(true)->getSkBitmap()));
99 void SoftwareRenderer::finishDrawingFrame(DrawingFrame& frame)
101 TRACE_EVENT0("cc", "SoftwareRenderer::finishDrawingFrame");
102 m_currentFramebufferLock.reset();
103 m_skCurrentCanvas = 0;
104 m_skRootCanvas.reset();
105 m_outputDevice->unlock();
108 bool SoftwareRenderer::flippedFramebuffer() const
110 return false;
113 void SoftwareRenderer::finish()
117 void SoftwareRenderer::bindFramebufferToOutputSurface(DrawingFrame& frame)
119 m_currentFramebufferLock.reset();
120 m_skCurrentCanvas = m_skRootCanvas.get();
123 bool SoftwareRenderer::bindFramebufferToTexture(DrawingFrame& frame, const ScopedResource* texture, const gfx::Rect& framebufferRect)
125 m_currentFramebufferLock = make_scoped_ptr(new ResourceProvider::ScopedWriteLockSoftware(m_resourceProvider, texture->id()));
126 m_skCurrentCanvas = m_currentFramebufferLock->skCanvas();
127 initializeMatrices(frame, framebufferRect, false);
128 setDrawViewportSize(framebufferRect.size());
130 return true;
133 void SoftwareRenderer::setScissorTestRect(const gfx::Rect& scissorRect)
135 m_skCurrentCanvas->clipRect(gfx::RectToSkRect(scissorRect), SkRegion::kReplace_Op);
138 void SoftwareRenderer::clearFramebuffer(DrawingFrame& frame)
140 if (frame.currentRenderPass->hasTransparentBackground()) {
141 m_skCurrentCanvas->clear(SkColorSetARGB(0, 0, 0, 0));
142 } else {
143 #ifndef NDEBUG
144 // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen.
145 m_skCurrentCanvas->clear(SkColorSetARGB(255, 0, 0, 255));
146 #endif
150 void SoftwareRenderer::setDrawViewportSize(const gfx::Size& viewportSize)
154 bool SoftwareRenderer::isSoftwareResource(ResourceProvider::ResourceId id) const
156 switch (m_resourceProvider->resourceType(id)) {
157 case ResourceProvider::GLTexture:
158 return false;
159 case ResourceProvider::Bitmap:
160 return true;
163 LOG(FATAL) << "Invalid resource type.";
164 return false;
167 void SoftwareRenderer::drawQuad(DrawingFrame& frame, const DrawQuad* quad)
169 TRACE_EVENT0("cc", "SoftwareRenderer::drawQuad");
170 WebTransformationMatrix quadRectMatrix;
171 quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect());
172 WebTransformationMatrix contentsDeviceTransform = (frame.windowMatrix * frame.projectionMatrix * quadRectMatrix).to2dTransform();
173 SkMatrix skDeviceMatrix;
174 toSkMatrix(&skDeviceMatrix, contentsDeviceTransform);
175 m_skCurrentCanvas->setMatrix(skDeviceMatrix);
177 m_skCurrentPaint.reset();
178 if (!isScaleAndTranslate(skDeviceMatrix)) {
179 m_skCurrentPaint.setAntiAlias(true);
180 m_skCurrentPaint.setFilterBitmap(true);
182 if (quad->needsBlending()) {
183 m_skCurrentPaint.setAlpha(quad->opacity() * 255);
184 m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
185 } else {
186 m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
189 switch (quad->material()) {
190 case DrawQuad::DebugBorder:
191 drawDebugBorderQuad(frame, DebugBorderDrawQuad::materialCast(quad));
192 break;
193 case DrawQuad::SolidColor:
194 drawSolidColorQuad(frame, SolidColorDrawQuad::materialCast(quad));
195 break;
196 case DrawQuad::TextureContent:
197 drawTextureQuad(frame, TextureDrawQuad::materialCast(quad));
198 break;
199 case DrawQuad::TiledContent:
200 drawTileQuad(frame, TileDrawQuad::materialCast(quad));
201 break;
202 case DrawQuad::RenderPass:
203 drawRenderPassQuad(frame, RenderPassDrawQuad::materialCast(quad));
204 break;
205 default:
206 drawUnsupportedQuad(frame, quad);
207 break;
210 m_skCurrentCanvas->resetMatrix();
213 void SoftwareRenderer::drawDebugBorderQuad(const DrawingFrame& frame, const DebugBorderDrawQuad* quad)
215 // We need to apply the matrix manually to have pixel-sized stroke width.
216 SkPoint vertices[4];
217 gfx::RectFToSkRect(quadVertexRect()).toQuad(vertices);
218 SkPoint transformedVertices[4];
219 m_skCurrentCanvas->getTotalMatrix().mapPoints(transformedVertices, vertices, 4);
220 m_skCurrentCanvas->resetMatrix();
222 m_skCurrentPaint.setColor(quad->color());
223 m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color()));
224 m_skCurrentPaint.setStyle(SkPaint::kStroke_Style);
225 m_skCurrentPaint.setStrokeWidth(quad->width());
226 m_skCurrentCanvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, transformedVertices, m_skCurrentPaint);
229 void SoftwareRenderer::drawSolidColorQuad(const DrawingFrame& frame, const SolidColorDrawQuad* quad)
231 m_skCurrentPaint.setColor(quad->color());
232 m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color()));
233 m_skCurrentCanvas->drawRect(gfx::RectFToSkRect(quadVertexRect()), m_skCurrentPaint);
236 void SoftwareRenderer::drawTextureQuad(const DrawingFrame& frame, const TextureDrawQuad* quad)
238 if (!isSoftwareResource(quad->resourceId())) {
239 drawUnsupportedQuad(frame, quad);
240 return;
243 // FIXME: Add support for non-premultiplied alpha.
244 ResourceProvider::ScopedReadLockSoftware lock(m_resourceProvider, quad->resourceId());
245 const SkBitmap* bitmap = lock.skBitmap();
246 gfx::RectF uvRect = gfx::ScaleRect(quad->uvRect(), bitmap->width(), bitmap->height());
247 SkRect skUvRect = gfx::RectFToSkRect(uvRect);
248 if (quad->flipped())
249 m_skCurrentCanvas->scale(1, -1);
250 m_skCurrentCanvas->drawBitmapRectToRect(*bitmap, &skUvRect,
251 gfx::RectFToSkRect(quadVertexRect()),
252 &m_skCurrentPaint);
255 void SoftwareRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* quad)
257 DCHECK(isSoftwareResource(quad->resourceId()));
258 ResourceProvider::ScopedReadLockSoftware lock(m_resourceProvider, quad->resourceId());
260 SkRect uvRect = SkRect::MakeXYWH(
261 quad->textureOffset().x(), quad->textureOffset().y(),
262 quad->quadRect().width(), quad->quadRect().height());
263 m_skCurrentPaint.setFilterBitmap(true);
264 m_skCurrentCanvas->drawBitmapRectToRect(*lock.skBitmap(), &uvRect,
265 gfx::RectFToSkRect(quadVertexRect()),
266 &m_skCurrentPaint);
269 void SoftwareRenderer::drawRenderPassQuad(const DrawingFrame& frame, const RenderPassDrawQuad* quad)
271 CachedResource* contentTexture = m_renderPassTextures.get(quad->renderPassId());
272 if (!contentTexture || !contentTexture->id())
273 return;
275 const RenderPass* renderPass = frame.renderPassesById->get(quad->renderPassId());
276 DCHECK(renderPass);
277 if (!renderPass)
278 return;
280 DCHECK(isSoftwareResource(contentTexture->id()));
281 ResourceProvider::ScopedReadLockSoftware lock(m_resourceProvider, contentTexture->id());
283 SkRect destRect = gfx::RectFToSkRect(quadVertexRect());
285 const SkBitmap* content = lock.skBitmap();
287 SkRect contentRect;
288 content->getBounds(&contentRect);
290 SkMatrix contentMat;
291 contentMat.setRectToRect(contentRect, destRect, SkMatrix::kFill_ScaleToFit);
293 SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(*content,
294 SkShader::kClamp_TileMode,
295 SkShader::kClamp_TileMode));
296 shader->setLocalMatrix(contentMat);
297 m_skCurrentPaint.setShader(shader);
299 SkImageFilter* filter = renderPass->filter();
300 if (filter)
301 m_skCurrentPaint.setImageFilter(filter);
303 if (quad->maskResourceId()) {
304 ResourceProvider::ScopedReadLockSoftware maskLock(m_resourceProvider, quad->maskResourceId());
306 const SkBitmap* mask = maskLock.skBitmap();
308 SkRect maskRect = SkRect::MakeXYWH(
309 quad->maskTexCoordOffsetX() * mask->width(),
310 quad->maskTexCoordOffsetY() * mask->height(),
311 quad->maskTexCoordScaleX() * mask->width(),
312 quad->maskTexCoordScaleY() * mask->height());
314 SkMatrix maskMat;
315 maskMat.setRectToRect(maskRect, destRect, SkMatrix::kFill_ScaleToFit);
317 SkAutoTUnref<SkShader> maskShader(SkShader::CreateBitmapShader(*mask,
318 SkShader::kClamp_TileMode,
319 SkShader::kClamp_TileMode));
320 maskShader->setLocalMatrix(maskMat);
322 SkPaint maskPaint;
323 maskPaint.setShader(maskShader);
325 SkAutoTUnref<SkLayerRasterizer> maskRasterizer(new SkLayerRasterizer);
326 maskRasterizer->addLayer(maskPaint);
328 m_skCurrentPaint.setRasterizer(maskRasterizer);
329 m_skCurrentCanvas->drawRect(destRect, m_skCurrentPaint);
330 } else {
331 // FIXME: Apply background filters and blend with content
332 m_skCurrentCanvas->drawRect(destRect, m_skCurrentPaint);
336 void SoftwareRenderer::drawUnsupportedQuad(const DrawingFrame& frame, const DrawQuad* quad)
338 m_skCurrentPaint.setColor(SK_ColorMAGENTA);
339 m_skCurrentPaint.setAlpha(quad->opacity() * 255);
340 m_skCurrentCanvas->drawRect(gfx::RectFToSkRect(quadVertexRect()), m_skCurrentPaint);
343 bool SoftwareRenderer::swapBuffers()
345 if (m_client->hasImplThread())
346 m_client->onSwapBuffersComplete();
347 return true;
350 void SoftwareRenderer::getFramebufferPixels(void *pixels, const gfx::Rect& rect)
352 TRACE_EVENT0("cc", "SoftwareRenderer::getFramebufferPixels");
353 SkBitmap fullBitmap = m_outputDevice->lock(false)->getSkBitmap();
354 SkBitmap subsetBitmap;
355 SkIRect invertRect = SkIRect::MakeXYWH(rect.x(), viewportSize().height() - rect.bottom(), rect.width(), rect.height());
356 fullBitmap.extractSubset(&subsetBitmap, invertRect);
357 subsetBitmap.copyPixelsTo(pixels, rect.width() * rect.height() * 4, rect.width() * 4);
358 m_outputDevice->unlock();
361 void SoftwareRenderer::setVisible(bool visible)
363 if (m_visible == visible)
364 return;
365 m_visible = visible;
368 } // namespace cc