| 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 |