OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "android_webview/browser/in_process_view_renderer.h" | 5 #include "android_webview/browser/in_process_view_renderer.h" |
6 | 6 |
7 #include <android/bitmap.h> | 7 #include <android/bitmap.h> |
8 | 8 |
9 #include "android_webview/browser/aw_gl_surface.h" | 9 #include "android_webview/browser/aw_gl_surface.h" |
10 #include "android_webview/browser/scoped_app_gl_state_restore.h" | 10 #include "android_webview/browser/scoped_app_gl_state_restore.h" |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 return RenderViaAuxilaryBitmapIfNeeded( | 416 return RenderViaAuxilaryBitmapIfNeeded( |
417 java_canvas, | 417 java_canvas, |
418 java_helper_, | 418 java_helper_, |
419 scroll_at_start_of_frame_, | 419 scroll_at_start_of_frame_, |
420 clip, | 420 clip, |
421 base::Bind(&InProcessViewRenderer::CompositeSW, | 421 base::Bind(&InProcessViewRenderer::CompositeSW, |
422 base::Unretained(this)), | 422 base::Unretained(this)), |
423 web_contents_); | 423 web_contents_); |
424 } | 424 } |
425 | 425 |
426 // static | 426 namespace { |
427 bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded( | |
428 jobject java_canvas, | |
429 BrowserViewRenderer::JavaHelper* java_helper, | |
430 const gfx::Vector2d& scroll_correction, | |
431 const gfx::Rect& clip, | |
432 InProcessViewRenderer::RenderMethod render_source, | |
433 void* owner_key) { | |
434 TRACE_EVENT0("android_webview", | |
435 "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded"); | |
436 | 427 |
437 JNIEnv* env = AttachCurrentThread(); | 428 struct LayerImportState { |
| 429 bool SetBitmap(const AwBitmapInfo& info) { |
| 430 SkBitmap::Config config = |
| 431 info.config == AwConfig_ARGB_8888 ? SkBitmap::kARGB_8888_Config : |
| 432 info.config == AwConfig_RGB_565 ? SkBitmap::kRGB_565_Config : |
| 433 SkBitmap::kNo_Config; |
| 434 if (config == SkBitmap::kNo_Config) |
| 435 return false; |
| 436 bitmap.setConfig(config, info.width, info.height, info.row_bytes); |
| 437 bitmap.setPixels(info.pixels); |
| 438 |
| 439 LOG(WARNING) << "JOTH decode: " << info.x << ", " << info.y |
| 440 << ", " << info.width << ", " << info.height; |
| 441 return true; |
| 442 } |
| 443 SkBitmap bitmap; |
| 444 bool importing; |
| 445 }; |
| 446 |
| 447 class LayerImportDevice : public SkDevice { |
| 448 public: |
| 449 LayerImportDevice(const LayerImportState* state) |
| 450 : SkDevice(state->bitmap), |
| 451 state_(state) { |
| 452 DCHECK(state_->importing); |
| 453 } |
| 454 |
| 455 SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, |
| 456 int width, int height, |
| 457 bool isOpaque, |
| 458 Usage usage) { |
| 459 const SkBitmap& bitmap = state_->bitmap; |
| 460 if (!state_->importing) { |
| 461 DCHECK(bitmap.empty() && state_->bitmap.isNull()); |
| 462 return new SkDevice(config, width, height, isOpaque); |
| 463 } |
| 464 DCHECK(usage != SkDevice::kGeneral_Usage); |
| 465 DCHECK(bitmap.config() == config); |
| 466 DCHECK(bitmap.width() == width); |
| 467 DCHECK(bitmap.height() == height); |
| 468 DCHECK(width == 0 || height == 0 || !bitmap.isNull()); |
| 469 return new LayerImportDevice(state_); |
| 470 } |
| 471 |
| 472 private: |
| 473 const LayerImportState* state_; |
| 474 }; |
| 475 |
| 476 bool RenderDirectToCanvas(JNIEnv* env, |
| 477 jobject java_canvas, |
| 478 BrowserViewRenderer::JavaHelper* java_helper, |
| 479 const gfx::Vector2d& scroll_correction, |
| 480 InProcessViewRenderer::RenderMethod render_source) { |
438 ScopedPixelAccess auto_release_pixels(env, java_canvas); | 481 ScopedPixelAccess auto_release_pixels(env, java_canvas); |
439 AwPixelInfo* pixels = auto_release_pixels.pixels(); | 482 AwPixelInfo* pixels = auto_release_pixels.pixels(); |
| 483 if (!pixels) |
| 484 return false; |
| 485 |
440 SkMatrix matrix; | 486 SkMatrix matrix; |
441 SkBitmap::Config config(SkBitmap::kNo_Config); | 487 for (int i = 0; i < 9; i++) { |
442 if (pixels) { | 488 matrix.set(i, pixels->matrix[i]); |
443 switch (pixels->config) { | |
444 case AwConfig_ARGB_8888: | |
445 config = SkBitmap::kARGB_8888_Config; | |
446 break; | |
447 case AwConfig_RGB_565: | |
448 config = SkBitmap::kRGB_565_Config; | |
449 break; | |
450 } | |
451 | |
452 for (int i = 0; i < 9; i++) { | |
453 matrix.set(i, pixels->matrix[i]); | |
454 } | |
455 // Workaround for http://crbug.com/271096: SW draw only supports | |
456 // translate & scale transforms. | |
457 if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) | |
458 config = SkBitmap::kNo_Config; | |
459 } | 489 } |
460 | 490 // Workarounds for http://crbug.com/271096: SW draw only supports |
461 if (config == SkBitmap::kNo_Config) { | 491 // translate & scale transforms, and a simple rectangular clip. |
462 // Render into an auxiliary bitmap if pixel info is not available. | 492 if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) |
463 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); | 493 return false; |
464 TRACE_EVENT0("android_webview", "RenderToAuxBitmap"); | 494 if (pixels->clip_rect_count > 1) |
465 ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap( | 495 return false; |
466 env, clip.width(), clip.height(), jcanvas, owner_key)); | |
467 if (!jbitmap.obj()) { | |
468 TRACE_EVENT_INSTANT0("android_webview", | |
469 "EarlyOut_BitmapAllocFail", | |
470 TRACE_EVENT_SCOPE_THREAD); | |
471 return false; | |
472 } | |
473 | |
474 if (!RasterizeIntoBitmap(env, jbitmap, | |
475 clip.x() - scroll_correction.x(), | |
476 clip.y() - scroll_correction.y(), | |
477 render_source)) { | |
478 TRACE_EVENT_INSTANT0("android_webview", | |
479 "EarlyOut_RasterizeFail", | |
480 TRACE_EVENT_SCOPE_THREAD); | |
481 return false; | |
482 } | |
483 | |
484 java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, | |
485 clip.x(), clip.y()); | |
486 return true; | |
487 } | |
488 | 496 |
489 // Draw in a SkCanvas built over the pixel information. | 497 // Draw in a SkCanvas built over the pixel information. |
490 SkBitmap bitmap; | 498 if (pixels->layer_count < 1) |
491 bitmap.setConfig(config, | 499 return false; |
492 pixels->width, | 500 LayerImportState layer; |
493 pixels->height, | 501 layer.importing = true; |
494 pixels->row_bytes); | 502 if (!layer.SetBitmap(pixels->layers[0])) |
495 bitmap.setPixels(pixels->pixels); | 503 return false; |
496 SkDevice device(bitmap); | 504 LayerImportDevice device(&layer); |
497 SkCanvas canvas(&device); | 505 SkCanvas canvas(&device); |
498 canvas.setMatrix(matrix); | 506 |
| 507 // Iterate over the layers above the root (hence, starting a 1). |
| 508 for (int i = 1; i < pixels->layer_count; ++i) { |
| 509 const AwBitmapInfo& bitmap = pixels->layers[i]; |
| 510 layer.SetBitmap(bitmap); |
| 511 SkRect rect = SkRect::MakeXYWH(bitmap.x, bitmap.y, |
| 512 bitmap.width, bitmap.height); |
| 513 // Use a "dest" xfer so that our shadow-layer stack restore is a no-op. |
| 514 SkPaint dest_mode; |
| 515 dest_mode.setXfermodeMode(SkXfermode::kDst_Mode); |
| 516 canvas.saveLayer(&rect, &dest_mode, SkCanvas::kARGB_NoClipLayer_SaveFlag); |
| 517 DCHECK(canvas.getTopDevice()->getOrigin() == |
| 518 SkIPoint::Make(bitmap.x, bitmap.y)); |
| 519 } |
| 520 layer.bitmap.reset(); |
| 521 layer.importing = false; |
499 | 522 |
500 if (pixels->clip_rect_count) { | 523 if (pixels->clip_rect_count) { |
501 SkRegion clip; | 524 SkRegion clip; |
502 for (int i = 0; i < pixels->clip_rect_count; ++i) { | 525 for (int i = 0; i < pixels->clip_rect_count; ++i) { |
503 clip.op(SkIRect::MakeXYWH(pixels->clip_rects[i + 0], | 526 clip.op(SkIRect::MakeXYWH(pixels->clip_rects[i + 0], |
504 pixels->clip_rects[i + 1], | 527 pixels->clip_rects[i + 1], |
505 pixels->clip_rects[i + 2], | 528 pixels->clip_rects[i + 2], |
506 pixels->clip_rects[i + 3]), | 529 pixels->clip_rects[i + 3]), |
507 SkRegion::kUnion_Op); | 530 SkRegion::kUnion_Op); |
508 } | 531 } |
509 canvas.setClipRegion(clip); | 532 canvas.setClipRegion(clip); |
510 } | 533 } |
511 | 534 canvas.setMatrix(matrix); |
512 canvas.translate(scroll_correction.x(), | 535 canvas.translate(scroll_correction.x(), |
513 scroll_correction.y()); | 536 scroll_correction.y()); |
514 | 537 |
515 return render_source.Run(&canvas); | 538 return render_source.Run(&canvas); |
516 } | 539 } |
517 | 540 |
| 541 } // namespace |
| 542 |
| 543 bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded( |
| 544 jobject java_canvas, |
| 545 BrowserViewRenderer::JavaHelper* java_helper, |
| 546 const gfx::Vector2d& scroll_correction, |
| 547 const gfx::Rect& clip, |
| 548 InProcessViewRenderer::RenderMethod render_source, |
| 549 void* owner_key) { |
| 550 TRACE_EVENT0("android_webview", |
| 551 "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded"); |
| 552 |
| 553 JNIEnv* env = AttachCurrentThread(); |
| 554 if (RenderDirectToCanvas(env, |
| 555 java_canvas, |
| 556 java_helper, |
| 557 scroll_correction, |
| 558 render_source)) { |
| 559 return true; |
| 560 } |
| 561 // Render into an auxiliary bitmap if pixel info is not available. |
| 562 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); |
| 563 TRACE_EVENT0("android_webview", "RenderToAuxBitmap"); |
| 564 ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap( |
| 565 env, clip.width(), clip.height(), jcanvas, owner_key)); |
| 566 if (!jbitmap.obj()) { |
| 567 TRACE_EVENT_INSTANT0("android_webview", |
| 568 "EarlyOut_BitmapAllocFail", |
| 569 TRACE_EVENT_SCOPE_THREAD); |
| 570 return false; |
| 571 } |
| 572 |
| 573 if (!RasterizeIntoBitmap(env, jbitmap, |
| 574 clip.x() - scroll_correction.x(), |
| 575 clip.y() - scroll_correction.y(), |
| 576 render_source)) { |
| 577 TRACE_EVENT_INSTANT0("android_webview", |
| 578 "EarlyOut_RasterizeFail", |
| 579 TRACE_EVENT_SCOPE_THREAD); |
| 580 return false; |
| 581 } |
| 582 |
| 583 java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, |
| 584 clip.x(), clip.y()); |
| 585 return true; |
| 586 } |
| 587 |
518 skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width, | 588 skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width, |
519 int height) { | 589 int height) { |
520 TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture"); | 590 TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture"); |
521 | 591 |
522 // Return empty Picture objects for empty SkPictures. | 592 // Return empty Picture objects for empty SkPictures. |
523 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); | 593 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); |
524 if (width <= 0 || height <= 0) { | 594 if (width <= 0 || height <= 0) { |
525 return picture; | 595 return picture; |
526 } | 596 } |
527 | 597 |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 base::StringAppendF(&str, | 890 base::StringAppendF(&str, |
821 "surface width height: [%d %d] ", | 891 "surface width height: [%d %d] ", |
822 draw_info->width, | 892 draw_info->width, |
823 draw_info->height); | 893 draw_info->height); |
824 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); | 894 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); |
825 } | 895 } |
826 return str; | 896 return str; |
827 } | 897 } |
828 | 898 |
829 } // namespace android_webview | 899 } // namespace android_webview |
OLD | NEW |