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 "cc/output/software_renderer.h" 6 7 #include "base/debug/trace_event.h" 8 #include "cc/base/math_util.h" 9 #include "cc/output/compositor_frame.h" 10 #include "cc/output/compositor_frame_ack.h" 11 #include "cc/output/compositor_frame_metadata.h" 12 #include "cc/output/copy_output_request.h" 13 #include "cc/output/output_surface.h" 14 #include "cc/output/render_surface_filters.h" 15 #include "cc/output/software_output_device.h" 16 #include "cc/quads/checkerboard_draw_quad.h" 17 #include "cc/quads/debug_border_draw_quad.h" 18 #include "cc/quads/picture_draw_quad.h" 19 #include "cc/quads/render_pass_draw_quad.h" 20 #include "cc/quads/solid_color_draw_quad.h" 21 #include "cc/quads/texture_draw_quad.h" 22 #include "cc/quads/tile_draw_quad.h" 23 #include "skia/ext/opacity_draw_filter.h" 24 #include "third_party/skia/include/core/SkCanvas.h" 25 #include "third_party/skia/include/core/SkColor.h" 26 #include "third_party/skia/include/core/SkImageFilter.h" 27 #include "third_party/skia/include/core/SkMatrix.h" 28 #include "third_party/skia/include/core/SkShader.h" 29 #include "third_party/skia/include/effects/SkLayerRasterizer.h" 30 #include "ui/gfx/rect_conversions.h" 31 #include "ui/gfx/skia_util.h" 32 #include "ui/gfx/transform.h" 33 34 namespace cc { 35 36 namespace { 37 38 static inline bool IsScalarNearlyInteger(SkScalar scalar) { 39 return SkScalarNearlyZero(scalar - SkScalarRound(scalar)); 40 } 41 42 bool IsScaleAndIntegerTranslate(const SkMatrix& matrix) { 43 return IsScalarNearlyInteger(matrix[SkMatrix::kMTransX]) && 44 IsScalarNearlyInteger(matrix[SkMatrix::kMTransY]) && 45 SkScalarNearlyZero(matrix[SkMatrix::kMSkewX]) && 46 SkScalarNearlyZero(matrix[SkMatrix::kMSkewY]) && 47 SkScalarNearlyZero(matrix[SkMatrix::kMPersp0]) && 48 SkScalarNearlyZero(matrix[SkMatrix::kMPersp1]) && 49 SkScalarNearlyZero(matrix[SkMatrix::kMPersp2] - 1.0f); 50 } 51 52 static SkShader::TileMode WrapModeToTileMode(GLint wrap_mode) { 53 switch (wrap_mode) { 54 case GL_REPEAT: 55 return SkShader::kRepeat_TileMode; 56 case GL_CLAMP_TO_EDGE: 57 return SkShader::kClamp_TileMode; 58 } 59 NOTREACHED(); 60 return SkShader::kClamp_TileMode; 61 } 62 63 } // anonymous namespace 64 65 scoped_ptr<SoftwareRenderer> SoftwareRenderer::Create( 66 RendererClient* client, 67 const LayerTreeSettings* settings, 68 OutputSurface* output_surface, 69 ResourceProvider* resource_provider) { 70 return make_scoped_ptr(new SoftwareRenderer( 71 client, settings, output_surface, resource_provider)); 72 } 73 74 SoftwareRenderer::SoftwareRenderer(RendererClient* client, 75 const LayerTreeSettings* settings, 76 OutputSurface* output_surface, 77 ResourceProvider* resource_provider) 78 : DirectRenderer(client, settings, output_surface, resource_provider), 79 visible_(true), 80 is_scissor_enabled_(false), 81 is_backbuffer_discarded_(false), 82 output_device_(output_surface->software_device()), 83 current_canvas_(NULL) { 84 if (resource_provider_) { 85 capabilities_.max_texture_size = resource_provider_->max_texture_size(); 86 capabilities_.best_texture_format = 87 resource_provider_->best_texture_format(); 88 } 89 // The updater can access bitmaps while the SoftwareRenderer is using them. 90 capabilities_.allow_partial_texture_updates = true; 91 capabilities_.using_partial_swap = true; 92 93 capabilities_.using_map_image = settings_->use_map_image; 94 capabilities_.using_shared_memory_resources = true; 95 } 96 97 SoftwareRenderer::~SoftwareRenderer() {} 98 99 const RendererCapabilitiesImpl& SoftwareRenderer::Capabilities() const { 100 return capabilities_; 101 } 102 103 void SoftwareRenderer::BeginDrawingFrame(DrawingFrame* frame) { 104 TRACE_EVENT0("cc", "SoftwareRenderer::BeginDrawingFrame"); 105 root_canvas_ = output_device_->BeginPaint( 106 gfx::ToEnclosingRect(frame->root_damage_rect)); 107 } 108 109 void SoftwareRenderer::FinishDrawingFrame(DrawingFrame* frame) { 110 TRACE_EVENT0("cc", "SoftwareRenderer::FinishDrawingFrame"); 111 current_framebuffer_lock_.reset(); 112 current_canvas_ = NULL; 113 root_canvas_ = NULL; 114 115 current_frame_data_.reset(new SoftwareFrameData); 116 output_device_->EndPaint(current_frame_data_.get()); 117 } 118 119 void SoftwareRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) { 120 CompositorFrame compositor_frame; 121 compositor_frame.metadata = metadata; 122 compositor_frame.software_frame_data = current_frame_data_.Pass(); 123 output_surface_->SwapBuffers(&compositor_frame); 124 } 125 126 void SoftwareRenderer::ReceiveSwapBuffersAck(const CompositorFrameAck& ack) { 127 output_device_->ReclaimSoftwareFrame(ack.last_software_frame_id); 128 } 129 130 bool SoftwareRenderer::FlippedFramebuffer() const { 131 return false; 132 } 133 134 void SoftwareRenderer::EnsureScissorTestEnabled() { 135 is_scissor_enabled_ = true; 136 SetClipRect(scissor_rect_); 137 } 138 139 void SoftwareRenderer::EnsureScissorTestDisabled() { 140 // There is no explicit notion of enabling/disabling scissoring in software 141 // rendering, but the underlying effect we want is to clear any existing 142 // clipRect on the current SkCanvas. This is done by setting clipRect to 143 // the viewport's dimensions. 144 is_scissor_enabled_ = false; 145 SkBaseDevice* device = current_canvas_->getDevice(); 146 SetClipRect(gfx::Rect(device->width(), device->height())); 147 } 148 149 void SoftwareRenderer::Finish() {} 150 151 void SoftwareRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) { 152 DCHECK(!output_surface_->HasExternalStencilTest()); 153 current_framebuffer_lock_.reset(); 154 current_canvas_ = root_canvas_; 155 } 156 157 bool SoftwareRenderer::BindFramebufferToTexture( 158 DrawingFrame* frame, 159 const ScopedResource* texture, 160 gfx::Rect target_rect) { 161 current_framebuffer_lock_.reset(); 162 current_framebuffer_lock_ = make_scoped_ptr( 163 new ResourceProvider::ScopedWriteLockSoftware( 164 resource_provider_, texture->id())); 165 current_canvas_ = current_framebuffer_lock_->sk_canvas(); 166 InitializeViewport(frame, 167 target_rect, 168 gfx::Rect(target_rect.size()), 169 target_rect.size()); 170 return true; 171 } 172 173 void SoftwareRenderer::SetScissorTestRect(gfx::Rect scissor_rect) { 174 is_scissor_enabled_ = true; 175 scissor_rect_ = scissor_rect; 176 SetClipRect(scissor_rect); 177 } 178 179 void SoftwareRenderer::SetClipRect(gfx::Rect rect) { 180 // Skia applies the current matrix to clip rects so we reset it temporary. 181 SkMatrix current_matrix = current_canvas_->getTotalMatrix(); 182 current_canvas_->resetMatrix(); 183 current_canvas_->clipRect(gfx::RectToSkRect(rect), SkRegion::kReplace_Op); 184 current_canvas_->setMatrix(current_matrix); 185 } 186 187 void SoftwareRenderer::ClearCanvas(SkColor color) { 188 // SkCanvas::clear doesn't respect the current clipping region 189 // so we SkCanvas::drawColor instead if scissoring is active. 190 if (is_scissor_enabled_) 191 current_canvas_->drawColor(color, SkXfermode::kSrc_Mode); 192 else 193 current_canvas_->clear(color); 194 } 195 196 void SoftwareRenderer::DiscardPixels(bool has_external_stencil_test, 197 bool draw_rect_covers_full_surface) {} 198 199 void SoftwareRenderer::ClearFramebuffer(DrawingFrame* frame, 200 bool has_external_stencil_test) { 201 if (frame->current_render_pass->has_transparent_background) { 202 ClearCanvas(SkColorSetARGB(0, 0, 0, 0)); 203 } else { 204 #ifndef NDEBUG 205 // On DEBUG builds, opaque render passes are cleared to blue 206 // to easily see regions that were not drawn on the screen. 207 ClearCanvas(SkColorSetARGB(255, 0, 0, 255)); 208 #endif 209 } 210 } 211 212 void SoftwareRenderer::SetDrawViewport(gfx::Rect window_space_viewport) {} 213 214 bool SoftwareRenderer::IsSoftwareResource( 215 ResourceProvider::ResourceId resource_id) const { 216 switch (resource_provider_->GetResourceType(resource_id)) { 217 case ResourceProvider::GLTexture: 218 return false; 219 case ResourceProvider::Bitmap: 220 return true; 221 case ResourceProvider::InvalidType: 222 break; 223 } 224 225 LOG(FATAL) << "Invalid resource type."; 226 return false; 227 } 228 229 void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { 230 TRACE_EVENT0("cc", "SoftwareRenderer::DoDrawQuad"); 231 gfx::Transform quad_rect_matrix; 232 QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); 233 gfx::Transform contents_device_transform = 234 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; 235 contents_device_transform.FlattenTo2d(); 236 SkMatrix sk_device_matrix; 237 gfx::TransformToFlattenedSkMatrix(contents_device_transform, 238 &sk_device_matrix); 239 current_canvas_->setMatrix(sk_device_matrix); 240 241 current_paint_.reset(); 242 if (!IsScaleAndIntegerTranslate(sk_device_matrix)) { 243 // TODO(danakj): Until we can enable AA only on exterior edges of the 244 // layer, disable AA if any interior edges are present. crbug.com/248175 245 bool all_four_edges_are_exterior = quad->IsTopEdge() && 246 quad->IsLeftEdge() && 247 quad->IsBottomEdge() && 248 quad->IsRightEdge(); 249 if (settings_->allow_antialiasing && all_four_edges_are_exterior) 250 current_paint_.setAntiAlias(true); 251 current_paint_.setFilterBitmap(true); 252 } 253 254 if (quad->ShouldDrawWithBlending()) { 255 current_paint_.setAlpha(quad->opacity() * 255); 256 current_paint_.setXfermodeMode(SkXfermode::kSrcOver_Mode); 257 } else { 258 current_paint_.setXfermodeMode(SkXfermode::kSrc_Mode); 259 } 260 261 switch (quad->material) { 262 case DrawQuad::CHECKERBOARD: 263 DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad)); 264 break; 265 case DrawQuad::DEBUG_BORDER: 266 DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad)); 267 break; 268 case DrawQuad::PICTURE_CONTENT: 269 DrawPictureQuad(frame, PictureDrawQuad::MaterialCast(quad)); 270 break; 271 case DrawQuad::RENDER_PASS: 272 DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad)); 273 break; 274 case DrawQuad::SOLID_COLOR: 275 DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad)); 276 break; 277 case DrawQuad::TEXTURE_CONTENT: 278 DrawTextureQuad(frame, TextureDrawQuad::MaterialCast(quad)); 279 break; 280 case DrawQuad::TILED_CONTENT: 281 DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad)); 282 break; 283 case DrawQuad::INVALID: 284 case DrawQuad::IO_SURFACE_CONTENT: 285 case DrawQuad::YUV_VIDEO_CONTENT: 286 case DrawQuad::STREAM_VIDEO_CONTENT: 287 DrawUnsupportedQuad(frame, quad); 288 NOTREACHED(); 289 break; 290 } 291 292 current_canvas_->resetMatrix(); 293 } 294 295 void SoftwareRenderer::DrawCheckerboardQuad(const DrawingFrame* frame, 296 const CheckerboardDrawQuad* quad) { 297 gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional( 298 QuadVertexRect(), quad->rect, quad->visible_rect); 299 current_paint_.setColor(quad->color); 300 current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color)); 301 current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect), 302 current_paint_); 303 } 304 305 void SoftwareRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, 306 const DebugBorderDrawQuad* quad) { 307 // We need to apply the matrix manually to have pixel-sized stroke width. 308 SkPoint vertices[4]; 309 gfx::RectFToSkRect(QuadVertexRect()).toQuad(vertices); 310 SkPoint transformed_vertices[4]; 311 current_canvas_->getTotalMatrix().mapPoints(transformed_vertices, 312 vertices, 313 4); 314 current_canvas_->resetMatrix(); 315 316 current_paint_.setColor(quad->color); 317 current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color)); 318 current_paint_.setStyle(SkPaint::kStroke_Style); 319 current_paint_.setStrokeWidth(quad->width); 320 current_canvas_->drawPoints(SkCanvas::kPolygon_PointMode, 321 4, transformed_vertices, current_paint_); 322 } 323 324 void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame, 325 const PictureDrawQuad* quad) { 326 SkMatrix content_matrix; 327 content_matrix.setRectToRect( 328 gfx::RectFToSkRect(quad->tex_coord_rect), 329 gfx::RectFToSkRect(QuadVertexRect()), 330 SkMatrix::kFill_ScaleToFit); 331 current_canvas_->concat(content_matrix); 332 333 // TODO(aelias): This isn't correct in all cases. We should detect these 334 // cases and fall back to a persistent bitmap backing 335 // (http://crbug.com/280374). 336 skia::RefPtr<SkDrawFilter> opacity_filter = 337 skia::AdoptRef(new skia::OpacityDrawFilter( 338 quad->opacity(), frame->disable_picture_quad_image_filtering)); 339 DCHECK(!current_canvas_->getDrawFilter()); 340 current_canvas_->setDrawFilter(opacity_filter.get()); 341 342 TRACE_EVENT0("cc", 343 "SoftwareRenderer::DrawPictureQuad"); 344 quad->picture_pile->RasterDirect( 345 current_canvas_, quad->content_rect, quad->contents_scale, NULL); 346 347 current_canvas_->setDrawFilter(NULL); 348 } 349 350 void SoftwareRenderer::DrawSolidColorQuad(const DrawingFrame* frame, 351 const SolidColorDrawQuad* quad) { 352 gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional( 353 QuadVertexRect(), quad->rect, quad->visible_rect); 354 current_paint_.setColor(quad->color); 355 current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color)); 356 current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect), 357 current_paint_); 358 } 359 360 void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame, 361 const TextureDrawQuad* quad) { 362 if (!IsSoftwareResource(quad->resource_id)) { 363 DrawUnsupportedQuad(frame, quad); 364 return; 365 } 366 367 // TODO(skaslev): Add support for non-premultiplied alpha. 368 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_, 369 quad->resource_id); 370 const SkBitmap* bitmap = lock.sk_bitmap(); 371 gfx::RectF uv_rect = gfx::ScaleRect(gfx::BoundingRect(quad->uv_top_left, 372 quad->uv_bottom_right), 373 bitmap->width(), 374 bitmap->height()); 375 gfx::RectF visible_uv_rect = 376 MathUtil::ScaleRectProportional(uv_rect, quad->rect, quad->visible_rect); 377 SkRect sk_uv_rect = gfx::RectFToSkRect(visible_uv_rect); 378 gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional( 379 QuadVertexRect(), quad->rect, quad->visible_rect); 380 SkRect quad_rect = gfx::RectFToSkRect(visible_quad_vertex_rect); 381 382 if (quad->flipped) 383 current_canvas_->scale(1, -1); 384 385 bool blend_background = quad->background_color != SK_ColorTRANSPARENT && 386 !bitmap->isOpaque(); 387 bool needs_layer = blend_background && (current_paint_.getAlpha() != 0xFF); 388 if (needs_layer) { 389 current_canvas_->saveLayerAlpha(&quad_rect, current_paint_.getAlpha()); 390 current_paint_.setAlpha(0xFF); 391 } 392 if (blend_background) { 393 SkPaint background_paint; 394 background_paint.setColor(quad->background_color); 395 current_canvas_->drawRect(quad_rect, background_paint); 396 } 397 SkShader::TileMode tile_mode = WrapModeToTileMode(lock.wrap_mode()); 398 if (tile_mode != SkShader::kClamp_TileMode) { 399 SkMatrix matrix; 400 matrix.setRectToRect(sk_uv_rect, quad_rect, SkMatrix::kFill_ScaleToFit); 401 skia::RefPtr<SkShader> shader = skia::AdoptRef( 402 SkShader::CreateBitmapShader(*bitmap, tile_mode, tile_mode)); 403 shader->setLocalMatrix(matrix); 404 SkPaint paint; 405 paint.setStyle(SkPaint::kFill_Style); 406 paint.setShader(shader.get()); 407 current_canvas_->drawRect(quad_rect, paint); 408 } else { 409 current_canvas_->drawBitmapRectToRect(*bitmap, 410 &sk_uv_rect, 411 quad_rect, 412 ¤t_paint_); 413 } 414 415 if (needs_layer) 416 current_canvas_->restore(); 417 } 418 419 void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame, 420 const TileDrawQuad* quad) { 421 DCHECK(!output_surface_->ForcedDrawToSoftwareDevice()); 422 DCHECK(IsSoftwareResource(quad->resource_id)); 423 424 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_, 425 quad->resource_id); 426 DCHECK_EQ(GL_CLAMP_TO_EDGE, lock.wrap_mode()); 427 428 gfx::RectF visible_tex_coord_rect = MathUtil::ScaleRectProportional( 429 quad->tex_coord_rect, quad->rect, quad->visible_rect); 430 gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional( 431 QuadVertexRect(), quad->rect, quad->visible_rect); 432 433 SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect); 434 current_paint_.setFilterBitmap(true); 435 current_canvas_->drawBitmapRectToRect( 436 *lock.sk_bitmap(), 437 &uv_rect, 438 gfx::RectFToSkRect(visible_quad_vertex_rect), 439 ¤t_paint_); 440 } 441 442 void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame, 443 const RenderPassDrawQuad* quad) { 444 ScopedResource* content_texture = 445 render_pass_textures_.get(quad->render_pass_id); 446 if (!content_texture || !content_texture->id()) 447 return; 448 449 DCHECK(IsSoftwareResource(content_texture->id())); 450 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_, 451 content_texture->id()); 452 SkShader::TileMode content_tile_mode = WrapModeToTileMode(lock.wrap_mode()); 453 454 SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect()); 455 SkRect dest_visible_rect = gfx::RectFToSkRect(MathUtil::ScaleRectProportional( 456 QuadVertexRect(), quad->rect, quad->visible_rect)); 457 SkRect content_rect = SkRect::MakeWH(quad->rect.width(), quad->rect.height()); 458 459 SkMatrix content_mat; 460 content_mat.setRectToRect(content_rect, dest_rect, 461 SkMatrix::kFill_ScaleToFit); 462 463 const SkBitmap* content = lock.sk_bitmap(); 464 465 SkBitmap filter_bitmap; 466 if (!quad->filters.IsEmpty()) { 467 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 468 quad->filters, content_texture->size()); 469 // TODO(ajuma): In addition origin translation, the canvas should also be 470 // scaled to accomodate device pixel ratio and pinch zoom. See 471 // crbug.com/281516 and crbug.com/281518. 472 // TODO(ajuma): Apply the filter in the same pass as the content where 473 // possible (e.g. when there's no origin offset). See crbug.com/308201. 474 if (filter) { 475 bool is_opaque = false; 476 skia::RefPtr<SkBaseDevice> device = 477 skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config, 478 content_texture->size().width(), 479 content_texture->size().height(), 480 is_opaque)); 481 SkCanvas canvas(device.get()); 482 SkPaint paint; 483 paint.setImageFilter(filter.get()); 484 canvas.clear(SK_ColorTRANSPARENT); 485 canvas.translate(SkIntToScalar(-quad->rect.origin().x()), 486 SkIntToScalar(-quad->rect.origin().y())); 487 canvas.drawSprite(*content, 0, 0, &paint); 488 bool will_change_pixels = false; 489 filter_bitmap = device->accessBitmap(will_change_pixels); 490 } 491 } 492 493 skia::RefPtr<SkShader> shader; 494 if (filter_bitmap.isNull()) { 495 shader = skia::AdoptRef(SkShader::CreateBitmapShader( 496 *content, content_tile_mode, content_tile_mode)); 497 } else { 498 shader = skia::AdoptRef(SkShader::CreateBitmapShader( 499 filter_bitmap, content_tile_mode, content_tile_mode)); 500 } 501 shader->setLocalMatrix(content_mat); 502 current_paint_.setShader(shader.get()); 503 504 if (quad->mask_resource_id) { 505 ResourceProvider::ScopedReadLockSoftware mask_lock(resource_provider_, 506 quad->mask_resource_id); 507 SkShader::TileMode mask_tile_mode = WrapModeToTileMode( 508 mask_lock.wrap_mode()); 509 510 const SkBitmap* mask = mask_lock.sk_bitmap(); 511 512 SkRect mask_rect = SkRect::MakeXYWH( 513 quad->mask_uv_rect.x() * mask->width(), 514 quad->mask_uv_rect.y() * mask->height(), 515 quad->mask_uv_rect.width() * mask->width(), 516 quad->mask_uv_rect.height() * mask->height()); 517 518 SkMatrix mask_mat; 519 mask_mat.setRectToRect(mask_rect, dest_rect, SkMatrix::kFill_ScaleToFit); 520 521 skia::RefPtr<SkShader> mask_shader = skia::AdoptRef( 522 SkShader::CreateBitmapShader(*mask, mask_tile_mode, mask_tile_mode)); 523 mask_shader->setLocalMatrix(mask_mat); 524 525 SkPaint mask_paint; 526 mask_paint.setShader(mask_shader.get()); 527 528 skia::RefPtr<SkLayerRasterizer> mask_rasterizer = 529 skia::AdoptRef(new SkLayerRasterizer); 530 mask_rasterizer->addLayer(mask_paint); 531 532 current_paint_.setRasterizer(mask_rasterizer.get()); 533 current_canvas_->drawRect(dest_visible_rect, current_paint_); 534 } else { 535 // TODO(skaslev): Apply background filters and blend with content 536 current_canvas_->drawRect(dest_visible_rect, current_paint_); 537 } 538 } 539 540 void SoftwareRenderer::DrawUnsupportedQuad(const DrawingFrame* frame, 541 const DrawQuad* quad) { 542 #ifdef NDEBUG 543 current_paint_.setColor(SK_ColorWHITE); 544 #else 545 current_paint_.setColor(SK_ColorMAGENTA); 546 #endif 547 current_paint_.setAlpha(quad->opacity() * 255); 548 current_canvas_->drawRect(gfx::RectFToSkRect(QuadVertexRect()), 549 current_paint_); 550 } 551 552 void SoftwareRenderer::CopyCurrentRenderPassToBitmap( 553 DrawingFrame* frame, 554 scoped_ptr<CopyOutputRequest> request) { 555 gfx::Rect copy_rect = frame->current_render_pass->output_rect; 556 if (request->has_area()) 557 copy_rect.Intersect(request->area()); 558 gfx::Rect window_copy_rect = MoveFromDrawToWindowSpace(copy_rect); 559 560 scoped_ptr<SkBitmap> bitmap(new SkBitmap); 561 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 562 window_copy_rect.width(), 563 window_copy_rect.height()); 564 current_canvas_->readPixels( 565 bitmap.get(), window_copy_rect.x(), window_copy_rect.y()); 566 567 request->SendBitmapResult(bitmap.Pass()); 568 } 569 570 void SoftwareRenderer::DiscardBackbuffer() { 571 if (is_backbuffer_discarded_) 572 return; 573 574 output_surface_->DiscardBackbuffer(); 575 576 is_backbuffer_discarded_ = true; 577 578 // Damage tracker needs a full reset every time framebuffer is discarded. 579 client_->SetFullRootLayerDamage(); 580 } 581 582 void SoftwareRenderer::EnsureBackbuffer() { 583 if (!is_backbuffer_discarded_) 584 return; 585 586 output_surface_->EnsureBackbuffer(); 587 is_backbuffer_discarded_ = false; 588 } 589 590 void SoftwareRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) { 591 TRACE_EVENT0("cc", "SoftwareRenderer::GetFramebufferPixels"); 592 SkBitmap subset_bitmap; 593 rect += current_viewport_rect_.OffsetFromOrigin(); 594 output_device_->CopyToBitmap(rect, &subset_bitmap); 595 subset_bitmap.copyPixelsTo(pixels, 596 4 * rect.width() * rect.height(), 597 4 * rect.width()); 598 } 599 600 void SoftwareRenderer::SetVisible(bool visible) { 601 if (visible_ == visible) 602 return; 603 visible_ = visible; 604 605 if (visible_) 606 EnsureBackbuffer(); 607 else 608 DiscardBackbuffer(); 609 } 610 611 } // namespace cc 612