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/scoped_app_gl_state_restore.h" | 9 #include "android_webview/browser/scoped_app_gl_state_restore.h" |
10 #include "android_webview/public/browser/draw_gl.h" | 10 #include "android_webview/public/browser/draw_gl.h" |
11 #include "android_webview/public/browser/draw_sw.h" | 11 #include "android_webview/public/browser/draw_sw.h" |
12 #include "base/android/jni_android.h" | 12 #include "base/android/jni_android.h" |
13 #include "base/auto_reset.h" | 13 #include "base/auto_reset.h" |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
16 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
19 #include "content/public/browser/android/synchronous_compositor.h" | 19 #include "content/public/browser/android/synchronous_compositor.h" |
20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
22 #include "gpu/command_buffer/service/in_process_command_buffer.h" | 22 #include "gpu/command_buffer/service/in_process_command_buffer.h" |
23 #include "skia/ext/refptr.h" | |
24 #include "third_party/skia/include/core/SkBitmap.h" | 23 #include "third_party/skia/include/core/SkBitmap.h" |
25 #include "third_party/skia/include/core/SkCanvas.h" | 24 #include "third_party/skia/include/core/SkCanvas.h" |
26 #include "third_party/skia/include/core/SkDevice.h" | 25 #include "third_party/skia/include/core/SkDevice.h" |
27 #include "third_party/skia/include/core/SkGraphics.h" | 26 #include "third_party/skia/include/core/SkGraphics.h" |
28 #include "third_party/skia/include/core/SkPicture.h" | 27 #include "third_party/skia/include/core/SkPicture.h" |
29 #include "ui/gfx/skia_util.h" | 28 #include "ui/gfx/skia_util.h" |
30 #include "ui/gfx/transform.h" | 29 #include "ui/gfx/transform.h" |
31 #include "ui/gfx/vector2d_conversions.h" | 30 #include "ui/gfx/vector2d_conversions.h" |
32 #include "ui/gfx/vector2d_f.h" | 31 #include "ui/gfx/vector2d_f.h" |
33 | 32 |
(...skipping 21 matching lines...) Expand all Loading... |
55 return NULL; | 54 return NULL; |
56 UserData* data = reinterpret_cast<UserData*>( | 55 UserData* data = reinterpret_cast<UserData*>( |
57 contents->GetUserData(kUserDataKey)); | 56 contents->GetUserData(kUserDataKey)); |
58 return data ? data->instance_ : NULL; | 57 return data ? data->instance_ : NULL; |
59 } | 58 } |
60 | 59 |
61 private: | 60 private: |
62 InProcessViewRenderer* instance_; | 61 InProcessViewRenderer* instance_; |
63 }; | 62 }; |
64 | 63 |
65 typedef base::Callback<bool(SkCanvas*)> RenderMethod; | |
66 | |
67 bool RasterizeIntoBitmap(JNIEnv* env, | 64 bool RasterizeIntoBitmap(JNIEnv* env, |
68 const JavaRef<jobject>& jbitmap, | 65 const JavaRef<jobject>& jbitmap, |
69 int scroll_x, | 66 int scroll_x, |
70 int scroll_y, | 67 int scroll_y, |
71 const RenderMethod& renderer) { | 68 const InProcessViewRenderer::RenderMethod& renderer) { |
72 DCHECK(jbitmap.obj()); | 69 DCHECK(jbitmap.obj()); |
73 | 70 |
74 AndroidBitmapInfo bitmap_info; | 71 AndroidBitmapInfo bitmap_info; |
75 if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) { | 72 if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) { |
76 LOG(ERROR) << "Error getting java bitmap info."; | 73 LOG(ERROR) << "Error getting java bitmap info."; |
77 return false; | 74 return false; |
78 } | 75 } |
79 | 76 |
80 void* pixels = NULL; | 77 void* pixels = NULL; |
81 if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) { | 78 if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) { |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect); | 354 EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect); |
358 } | 355 } |
359 | 356 |
360 void InProcessViewRenderer::SetGlobalVisibleRect( | 357 void InProcessViewRenderer::SetGlobalVisibleRect( |
361 const gfx::Rect& visible_rect) { | 358 const gfx::Rect& visible_rect) { |
362 cached_global_visible_rect_ = visible_rect; | 359 cached_global_visible_rect_ = visible_rect; |
363 } | 360 } |
364 | 361 |
365 bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas, | 362 bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas, |
366 const gfx::Rect& clip) { | 363 const gfx::Rect& clip) { |
367 TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawSW"); | |
368 fallback_tick_.Cancel(); | 364 fallback_tick_.Cancel(); |
369 | 365 |
370 if (clip.IsEmpty()) { | 366 if (clip.IsEmpty()) { |
371 TRACE_EVENT_INSTANT0( | 367 TRACE_EVENT_INSTANT0( |
372 "android_webview", "EarlyOut_EmptyClip", TRACE_EVENT_SCOPE_THREAD); | 368 "android_webview", "EarlyOut_EmptyClip", TRACE_EVENT_SCOPE_THREAD); |
373 return true; | 369 return true; |
374 } | 370 } |
375 | 371 |
376 if (!compositor_) { | 372 if (!compositor_) { |
377 TRACE_EVENT_INSTANT0( | 373 TRACE_EVENT_INSTANT0( |
378 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD); | 374 "android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD); |
379 return false; | 375 return false; |
380 } | 376 } |
381 | 377 |
| 378 return RenderViaAuxilaryBitmapIfNeeded( |
| 379 java_canvas, |
| 380 java_helper_, |
| 381 scroll_at_start_of_frame_, |
| 382 clip, |
| 383 base::Bind(&InProcessViewRenderer::CompositeSW, |
| 384 base::Unretained(this)), |
| 385 web_contents_); |
| 386 } |
| 387 |
| 388 // static |
| 389 bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded( |
| 390 jobject java_canvas, |
| 391 BrowserViewRenderer::JavaHelper* java_helper, |
| 392 const gfx::Vector2d& scroll_correction, |
| 393 const gfx::Rect& clip, |
| 394 InProcessViewRenderer::RenderMethod render_source, |
| 395 void* owner_key) { |
| 396 TRACE_EVENT0("android_webview", |
| 397 "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded"); |
382 JNIEnv* env = AttachCurrentThread(); | 398 JNIEnv* env = AttachCurrentThread(); |
383 | 399 |
384 AwDrawSWFunctionTable* sw_functions = GetAwDrawSWFunctionTable(); | 400 AwDrawSWFunctionTable* sw_functions = GetAwDrawSWFunctionTable(); |
385 AwPixelInfo* pixels = sw_functions ? | 401 AwPixelInfo* pixels = sw_functions ? |
386 sw_functions->access_pixels(env, java_canvas) : NULL; | 402 sw_functions->access_pixels(env, java_canvas) : NULL; |
387 // Render into an auxiliary bitmap if pixel info is not available. | |
388 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); | |
389 if (pixels == NULL) { | 403 if (pixels == NULL) { |
| 404 // Render into an auxiliary bitmap if pixel info is not available. |
| 405 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); |
390 TRACE_EVENT0("android_webview", "RenderToAuxBitmap"); | 406 TRACE_EVENT0("android_webview", "RenderToAuxBitmap"); |
391 ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap( | 407 ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap( |
392 env, clip.width(), clip.height(), jcanvas, web_contents_)); | 408 env, clip.width(), clip.height(), jcanvas, owner_key)); |
393 if (!jbitmap.obj()) { | 409 if (!jbitmap.obj()) { |
394 TRACE_EVENT_INSTANT0("android_webview", | 410 TRACE_EVENT_INSTANT0("android_webview", |
395 "EarlyOut_BitmapAllocFail", | 411 "EarlyOut_BitmapAllocFail", |
396 TRACE_EVENT_SCOPE_THREAD); | 412 TRACE_EVENT_SCOPE_THREAD); |
397 return false; | 413 return false; |
398 } | 414 } |
399 | 415 |
400 if (!RasterizeIntoBitmap(env, jbitmap, | 416 if (!RasterizeIntoBitmap(env, jbitmap, |
401 clip.x() - scroll_at_start_of_frame_.x(), | 417 clip.x() - scroll_correction.x(), |
402 clip.y() - scroll_at_start_of_frame_.y(), | 418 clip.y() - scroll_correction.y(), |
403 base::Bind(&InProcessViewRenderer::CompositeSW, | 419 render_source)) { |
404 base::Unretained(this)))) { | |
405 TRACE_EVENT_INSTANT0("android_webview", | 420 TRACE_EVENT_INSTANT0("android_webview", |
406 "EarlyOut_RasterizeFail", | 421 "EarlyOut_RasterizeFail", |
407 TRACE_EVENT_SCOPE_THREAD); | 422 TRACE_EVENT_SCOPE_THREAD); |
408 return false; | 423 return false; |
409 } | 424 } |
410 | 425 |
411 java_helper_->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, | 426 java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, |
412 clip.x(), clip.y()); | 427 clip.x(), clip.y()); |
413 return true; | 428 return true; |
414 } | 429 } |
415 | 430 |
416 // Draw in a SkCanvas built over the pixel information. | 431 // Draw in a SkCanvas built over the pixel information. |
417 bool succeeded = false; | 432 bool succeeded = false; |
418 { | 433 { |
419 SkBitmap bitmap; | 434 SkBitmap bitmap; |
420 bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config), | 435 bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config), |
421 pixels->width, | 436 pixels->width, |
422 pixels->height, | 437 pixels->height, |
423 pixels->row_bytes); | 438 pixels->row_bytes); |
424 bitmap.setPixels(pixels->pixels); | 439 bitmap.setPixels(pixels->pixels); |
425 SkDevice device(bitmap); | 440 SkDevice device(bitmap); |
426 SkCanvas canvas(&device); | 441 SkCanvas canvas(&device); |
427 SkMatrix matrix; | 442 SkMatrix matrix; |
428 for (int i = 0; i < 9; i++) | 443 for (int i = 0; i < 9; i++) |
429 matrix.set(i, pixels->matrix[i]); | 444 matrix.set(i, pixels->matrix[i]); |
430 canvas.setMatrix(matrix); | 445 canvas.setMatrix(matrix); |
431 | 446 |
432 if (pixels->clip_region_size) { | 447 if (pixels->clip_region_size) { |
433 SkRegion clip_region; | 448 SkRegion clip_region; |
434 size_t bytes_read = clip_region.readFromMemory(pixels->clip_region); | 449 size_t bytes_read = clip_region.readFromMemory(pixels->clip_region); |
435 DCHECK_EQ(pixels->clip_region_size, bytes_read); | 450 DCHECK_EQ(pixels->clip_region_size, bytes_read); |
436 canvas.setClipRegion(clip_region); | 451 canvas.setClipRegion(clip_region); |
437 } else { | 452 } else { |
438 canvas.clipRect(gfx::RectToSkRect(clip)); | 453 canvas.clipRect(gfx::RectToSkRect(clip)); |
439 } | 454 } |
440 canvas.translate(scroll_at_start_of_frame_.x(), | 455 canvas.translate(scroll_correction.x(), |
441 scroll_at_start_of_frame_.y()); | 456 scroll_correction.y()); |
442 | 457 |
443 succeeded = CompositeSW(&canvas); | 458 succeeded = render_source.Run(&canvas); |
444 } | 459 } |
445 | 460 |
446 sw_functions->release_pixels(pixels); | 461 sw_functions->release_pixels(pixels); |
447 return succeeded; | 462 return succeeded; |
448 } | 463 } |
449 | 464 |
450 base::android::ScopedJavaLocalRef<jobject> | 465 skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width, |
451 InProcessViewRenderer::CapturePicture(int width, int height) { | 466 int height) { |
452 if (!compositor_ || !GetAwDrawSWFunctionTable()) { | |
453 TRACE_EVENT_INSTANT0( | |
454 "android_webview", "EarlyOut_CapturePicture", TRACE_EVENT_SCOPE_THREAD); | |
455 return ScopedJavaLocalRef<jobject>(); | |
456 } | |
457 | |
458 // Return empty Picture objects for empty SkPictures. | 467 // Return empty Picture objects for empty SkPictures. |
459 JNIEnv* env = AttachCurrentThread(); | 468 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); |
460 if (width <= 0 || height <= 0) { | 469 if (width <= 0 || height <= 0) { |
461 return java_helper_->RecordBitmapIntoPicture(env, | 470 return picture; |
462 ScopedJavaLocalRef<jobject>()); | |
463 } | 471 } |
464 | 472 |
465 // Reset scroll back to the origin, will go back to the old | 473 // Reset scroll back to the origin, will go back to the old |
466 // value when scroll_reset is out of scope. | 474 // value when scroll_reset is out of scope. |
467 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_css_, | 475 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_css_, |
468 gfx::Vector2d()); | 476 gfx::Vector2d()); |
469 | 477 |
470 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); | |
471 SkCanvas* rec_canvas = picture->beginRecording(width, height, 0); | 478 SkCanvas* rec_canvas = picture->beginRecording(width, height, 0); |
472 if (!CompositeSW(rec_canvas)) | 479 if (compositor_) |
473 return ScopedJavaLocalRef<jobject>(); | 480 CompositeSW(rec_canvas); |
474 picture->endRecording(); | 481 picture->endRecording(); |
475 | 482 return picture; |
476 if (IsSkiaVersionCompatible()) { | |
477 // Add a reference that the create_picture() will take ownership of. | |
478 picture->ref(); | |
479 return ScopedJavaLocalRef<jobject>(env, | |
480 GetAwDrawSWFunctionTable()->create_picture(env, picture.get())); | |
481 } | |
482 | |
483 // If Skia versions are not compatible, workaround it by rasterizing the | |
484 // picture into a bitmap and drawing it into a new Java picture. Pass null | |
485 // for |canvas| as we don't have java canvas at this point (and it would be | |
486 // software anyway). | |
487 ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap( | |
488 env, picture->width(), picture->height(), ScopedJavaLocalRef<jobject>(), | |
489 NULL)); | |
490 if (!jbitmap.obj()) | |
491 return ScopedJavaLocalRef<jobject>(); | |
492 | |
493 if (!RasterizeIntoBitmap(env, jbitmap, 0, 0, | |
494 base::Bind(&RenderPictureToCanvas, | |
495 base::Unretained(picture.get())))) { | |
496 return ScopedJavaLocalRef<jobject>(); | |
497 } | |
498 | |
499 return java_helper_->RecordBitmapIntoPicture(env, jbitmap); | |
500 } | 483 } |
501 | 484 |
502 void InProcessViewRenderer::EnableOnNewPicture(bool enabled) { | 485 void InProcessViewRenderer::EnableOnNewPicture(bool enabled) { |
503 on_new_picture_enable_ = enabled; | 486 on_new_picture_enable_ = enabled; |
504 } | 487 } |
505 | 488 |
506 void InProcessViewRenderer::OnVisibilityChanged(bool visible) { | 489 void InProcessViewRenderer::OnVisibilityChanged(bool visible) { |
507 TRACE_EVENT_INSTANT1("android_webview", | 490 TRACE_EVENT_INSTANT1("android_webview", |
508 "InProcessViewRenderer::OnVisibilityChanged", | 491 "InProcessViewRenderer::OnVisibilityChanged", |
509 TRACE_EVENT_SCOPE_THREAD, | 492 TRACE_EVENT_SCOPE_THREAD, |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 base::StringAppendF(&str, | 757 base::StringAppendF(&str, |
775 "surface width height: [%d %d] ", | 758 "surface width height: [%d %d] ", |
776 draw_info->width, | 759 draw_info->width, |
777 draw_info->height); | 760 draw_info->height); |
778 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); | 761 base::StringAppendF(&str, "is_layer: %d ", draw_info->is_layer); |
779 } | 762 } |
780 return str; | 763 return str; |
781 } | 764 } |
782 | 765 |
783 } // namespace android_webview | 766 } // namespace android_webview |
OLD | NEW |