Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: android_webview/native/aw_contents.cc

Issue 11823027: [Android WebView] Implement the capture picture API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/native/aw_contents.h" 5 #include "android_webview/native/aw_contents.h"
6 6
7 #include <android/bitmap.h>
7 #include <sys/system_properties.h> 8 #include <sys/system_properties.h>
8 9
9 #include "android_webview/browser/aw_browser_main_parts.h" 10 #include "android_webview/browser/aw_browser_main_parts.h"
10 #include "android_webview/browser/net_disk_cache_remover.h" 11 #include "android_webview/browser/net_disk_cache_remover.h"
11 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h" 12 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
12 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_dele gate.h" 13 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_dele gate.h"
13 #include "android_webview/common/aw_hit_test_data.h" 14 #include "android_webview/common/aw_hit_test_data.h"
14 #include "android_webview/common/renderer_picture_map.h" 15 #include "android_webview/common/renderer_picture_map.h"
15 #include "android_webview/native/aw_browser_dependency_factory.h" 16 #include "android_webview/native/aw_browser_dependency_factory.h"
16 #include "android_webview/native/aw_contents_io_thread_client_impl.h" 17 #include "android_webview/native/aw_contents_io_thread_client_impl.h"
(...skipping 13 matching lines...) Expand all
30 #include "content/components/navigation_interception/intercept_navigation_delega te.h" 31 #include "content/components/navigation_interception/intercept_navigation_delega te.h"
31 #include "content/public/browser/android/content_view_core.h" 32 #include "content/public/browser/android/content_view_core.h"
32 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/cert_store.h" 34 #include "content/public/browser/cert_store.h"
34 #include "content/public/browser/navigation_entry.h" 35 #include "content/public/browser/navigation_entry.h"
35 #include "content/public/browser/render_process_host.h" 36 #include "content/public/browser/render_process_host.h"
36 #include "content/public/browser/web_contents.h" 37 #include "content/public/browser/web_contents.h"
37 #include "content/public/common/ssl_status.h" 38 #include "content/public/common/ssl_status.h"
38 #include "jni/AwContents_jni.h" 39 #include "jni/AwContents_jni.h"
39 #include "net/base/x509_certificate.h" 40 #include "net/base/x509_certificate.h"
40 #include "skia/ext/refptr.h"
41 #include "third_party/skia/include/core/SkBitmap.h" 41 #include "third_party/skia/include/core/SkBitmap.h"
42 #include "third_party/skia/include/core/SkCanvas.h" 42 #include "third_party/skia/include/core/SkCanvas.h"
43 #include "third_party/skia/include/core/SkDevice.h" 43 #include "third_party/skia/include/core/SkDevice.h"
44 #include "third_party/skia/include/core/SkPicture.h" 44 #include "third_party/skia/include/core/SkGraphics.h"
45 #include "ui/gfx/transform.h" 45 #include "ui/gfx/transform.h"
46 #include "ui/gl/gl_bindings.h" 46 #include "ui/gl/gl_bindings.h"
47 47
48 // TODO(leandrogracia): remove when crbug.com/164140 is closed. 48 // TODO(leandrogracia): remove when crbug.com/164140 is closed.
49 // Borrowed from gl2ext.h. Cannot be included due to conflicts with 49 // Borrowed from gl2ext.h. Cannot be included due to conflicts with
50 // gl_bindings.h and the EGL library methods (eglGetCurrentContext). 50 // gl_bindings.h and the EGL library methods (eglGetCurrentContext).
51 #ifndef GL_TEXTURE_EXTERNAL_OES 51 #ifndef GL_TEXTURE_EXTERNAL_OES
52 #define GL_TEXTURE_EXTERNAL_OES 0x8D65 52 #define GL_TEXTURE_EXTERNAL_OES 0x8D65
53 #endif 53 #endif
54 54
(...skipping 24 matching lines...) Expand all
79 reinterpret_cast<android_webview::AwContents*>(view_context)->DrawGL( 79 reinterpret_cast<android_webview::AwContents*>(view_context)->DrawGL(
80 draw_info); 80 draw_info);
81 } 81 }
82 } 82 }
83 83
84 namespace android_webview { 84 namespace android_webview {
85 85
86 namespace { 86 namespace {
87 87
88 AwDrawSWFunctionTable* g_draw_sw_functions = NULL; 88 AwDrawSWFunctionTable* g_draw_sw_functions = NULL;
89 bool g_is_skia_version_compatible = false;
89 90
90 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; 91 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
91 92
92 class AwContentsUserData : public base::SupportsUserData::Data { 93 class AwContentsUserData : public base::SupportsUserData::Data {
93 public: 94 public:
94 AwContentsUserData(AwContents* ptr) : contents_(ptr) {} 95 AwContentsUserData(AwContents* ptr) : contents_(ptr) {}
95 96
96 static AwContents* GetContents(WebContents* web_contents) { 97 static AwContents* GetContents(WebContents* web_contents) {
97 if (!web_contents) 98 if (!web_contents)
98 return NULL; 99 return NULL;
(...skipping 15 matching lines...) Expand all
114 115
115 AwContents::AwContents(JNIEnv* env, 116 AwContents::AwContents(JNIEnv* env,
116 jobject obj, 117 jobject obj,
117 jobject web_contents_delegate) 118 jobject web_contents_delegate)
118 : java_ref_(env, obj), 119 : java_ref_(env, obj),
119 web_contents_delegate_( 120 web_contents_delegate_(
120 new AwWebContentsDelegate(env, web_contents_delegate)), 121 new AwWebContentsDelegate(env, web_contents_delegate)),
121 view_visible_(false), 122 view_visible_(false),
122 compositor_visible_(false), 123 compositor_visible_(false),
123 is_composite_pending_(false), 124 is_composite_pending_(false),
125 on_new_picture_mode_(kOnNewPictureDisabled),
124 last_frame_context_(NULL) { 126 last_frame_context_(NULL) {
125 RendererPictureMap::CreateInstance(); 127 RendererPictureMap::CreateInstance();
126 android_webview::AwBrowserDependencyFactory* dependency_factory = 128 android_webview::AwBrowserDependencyFactory* dependency_factory =
127 android_webview::AwBrowserDependencyFactory::GetInstance(); 129 android_webview::AwBrowserDependencyFactory::GetInstance();
128 130
129 // TODO(joth): rather than create and set the WebContents here, expose the 131 // TODO(joth): rather than create and set the WebContents here, expose the
130 // factory method to java side and have that orchestrate the construction 132 // factory method to java side and have that orchestrate the construction
131 // order. 133 // order.
132 SetWebContents(dependency_factory->CreateWebContents()); 134 SetWebContents(dependency_factory->CreateWebContents());
133 } 135 }
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 374
373 glScissor(scissor_box[0], scissor_box[1], scissor_box[2], 375 glScissor(scissor_box[0], scissor_box[1], scissor_box[2],
374 scissor_box[3]); 376 scissor_box[3]);
375 377
376 glUseProgram(current_program); 378 glUseProgram(current_program);
377 } 379 }
378 // --------------------------------------------------------------------------- 380 // ---------------------------------------------------------------------------
379 } 381 }
380 382
381 bool AwContents::DrawSW(JNIEnv* env, jobject obj, jobject java_canvas) { 383 bool AwContents::DrawSW(JNIEnv* env, jobject obj, jobject java_canvas) {
382 skia::RefPtr<SkPicture> picture = 384 // TODO(leandrogracia): once Ubercompositor is ready and we support software
palmer 2013/01/15 01:16:19 I'd file a bug and refer to it here.
Leandro Graciá Gil 2013/01/15 18:49:23 Done.
383 RendererPictureMap::GetInstance()->GetRendererPicture( 385 // rendering mode, we should avoid this as much as we can, ideally always.
384 web_contents_->GetRoutingID()); 386 // This includes finding a proper replacement for onDraw calls in hardware
387 // mode with software canvases.
388 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture();
385 if (!picture) 389 if (!picture)
386 return false; 390 return false;
387 391
388 AwPixelInfo* pixels; 392 AwPixelInfo* pixels;
389 if (!g_draw_sw_functions || 393 if (!g_draw_sw_functions ||
390 (pixels = g_draw_sw_functions->access_pixels(env, java_canvas)) == NULL) { 394 (pixels = g_draw_sw_functions->access_pixels(env, java_canvas)) == NULL) {
391 // TODO(joth): Fall back to slow path rendering via temporary bitmap. 395 // TODO(joth): Fall back to slow path rendering via temporary bitmap.
392 return false; 396 return false;
393 } 397 }
394 398
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 } 459 }
456 460
457 void AwContents::Destroy(JNIEnv* env, jobject obj) { 461 void AwContents::Destroy(JNIEnv* env, jobject obj) {
458 delete this; 462 delete this;
459 } 463 }
460 464
461 // static 465 // static
462 void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) { 466 void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) {
463 g_draw_sw_functions = 467 g_draw_sw_functions =
464 reinterpret_cast<AwDrawSWFunctionTable*>(function_table); 468 reinterpret_cast<AwDrawSWFunctionTable*>(function_table);
469 // TODO(leandrogracia): uncomment once the glue layer implements this method.
palmer 2013/01/15 01:16:19 Here, too.
Leandro Graciá Gil 2013/01/15 18:49:23 This one is intended to be very shortly-lived, pro
470 //g_is_skia_version_compatible =
471 // g_draw_sw_functions->is_skia_version_compatible(&SkGraphics::GetVersion);
472 if (!g_is_skia_version_compatible)
473 LOG(WARNING) << "Skia native versions are not compatible.";
465 } 474 }
466 475
467 // static 476 // static
468 jint GetAwDrawGLFunction(JNIEnv* env, jclass) { 477 jint GetAwDrawGLFunction(JNIEnv* env, jclass) {
469 return reinterpret_cast<jint>(&DrawGLFunction); 478 return reinterpret_cast<jint>(&DrawGLFunction);
470 } 479 }
471 480
472 namespace { 481 namespace {
473 // |message| is passed as base::Owned, so it will automatically be deleted 482 // |message| is passed as base::Owned, so it will automatically be deleted
474 // when the callback goes out of scope. 483 // when the callback goes out of scope.
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 is_composite_pending_ = true; 698 is_composite_pending_ = true;
690 Invalidate(); 699 Invalidate();
691 } 700 }
692 701
693 void AwContents::Invalidate() { 702 void AwContents::Invalidate() {
694 JNIEnv* env = AttachCurrentThread(); 703 JNIEnv* env = AttachCurrentThread();
695 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 704 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
696 if (obj.is_null()) 705 if (obj.is_null())
697 return; 706 return;
698 707
699 Java_AwContents_invalidate(env, obj.obj()); 708 if (view_visible_)
709 Java_AwContents_invalidate(env, obj.obj());
710
711 // When not in invalidation-only mode onNewPicture will be triggered
712 // from the OnPictureUpdated callback.
713 if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly)
714 Java_AwContents_onNewPicture(env, obj.obj(), NULL);
700 } 715 }
701 716
702 void AwContents::SetCompositorVisibility(bool visible) { 717 void AwContents::SetCompositorVisibility(bool visible) {
703 if (compositor_visible_ != visible) { 718 if (compositor_visible_ != visible) {
704 compositor_visible_ = visible; 719 compositor_visible_ = visible;
705 compositor_->SetVisible(compositor_visible_); 720 compositor_->SetVisible(compositor_visible_);
706 } 721 }
707 } 722 }
708 723
709 void AwContents::OnSwapBuffersCompleted() { 724 void AwContents::OnSwapBuffersCompleted() {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 } 856 }
842 857
843 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { 858 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) {
844 web_contents_->FocusThroughTabTraversal(false); 859 web_contents_->FocusThroughTabTraversal(false);
845 } 860 }
846 861
847 jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) { 862 jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) {
848 return reinterpret_cast<jint>(pending_contents_.release()); 863 return reinterpret_cast<jint>(pending_contents_.release());
849 } 864 }
850 865
866 ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env,
867 jobject obj) {
868 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture();
869 if (!picture || !g_draw_sw_functions)
870 return ScopedJavaLocalRef<jobject>();
871
872 if (g_is_skia_version_compatible)
873 return ScopedJavaLocalRef<jobject>(env,
874 g_draw_sw_functions->create_picture(env, picture->clone()));
875
876 // If Skia versions are not compatible, workaround it by rasterizing the
877 // picture into a bitmap and drawing it into a new Java picture.
878 return ScopedJavaLocalRef<jobject>(
879 Java_AwContents_rasterizeIntoPicture(env, obj,
880 reinterpret_cast<jint>(picture.get()),
881 picture->width(), picture->height()));
882 }
883
884 // static
885 jboolean RasterizePicture(JNIEnv* env,
886 jclass clazz,
887 jobject jbitmap,
888 jint native_picture) {
889 DCHECK(jbitmap);
890 DCHECK(native_picture);
891
892 AndroidBitmapInfo bitmap_info;
893 if (AndroidBitmap_getInfo(env, jbitmap, &bitmap_info) < 0) {
894 LOG(WARNING) << "Error getting java bitmap info.";
895 return false;
896 }
897
898 void* pixels = NULL;
899 if (AndroidBitmap_lockPixels(env, jbitmap, &pixels) < 0) {
900 LOG(WARNING) << "Error locking java bitmap pixels.";
901 return false;
902 }
903
904 {
905 SkBitmap bitmap;
906 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
907 bitmap_info.width,
908 bitmap_info.height,
909 bitmap_info.stride);
910 bitmap.setPixels(pixels);
911
912 SkDevice device(bitmap);
913 SkCanvas canvas(&device);
914 SkPicture* picture = reinterpret_cast<SkPicture*>(native_picture);
915 picture->draw(&canvas);
916 }
917
918 if (AndroidBitmap_unlockPixels(env, jbitmap) < 0) {
919 LOG(WARNING) << "Error unlocking java bitmap pixels.";
920 return false;
921 }
922
923 return true;
924 }
925
926 void AwContents::EnableOnNewPicture(JNIEnv* env,
927 jobject obj,
928 jboolean enabled,
929 jboolean invalidation_only) {
930 if (enabled) {
931 on_new_picture_mode_ = invalidation_only ? kOnNewPictureInvalidationOnly :
932 kOnNewPictureEnabled;
933 } else {
934 on_new_picture_mode_ = kOnNewPictureDisabled;
935 }
936
937 // If onNewPicture is triggered only on invalidation do not capture
938 // pictures on every new frame.
939 if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly)
940 enabled = false;
941
942 // TODO(leandrogracia): uncomment when sw rendering uses Ubercompositor.
943 // Until then we need the callback enabled for SW mode invalidation.
944 // render_view_host_ext_->EnableCapturePictureCallback(enabled);
945 }
946
851 void AwContents::OnPictureUpdated(int process_id, int render_view_id) { 947 void AwContents::OnPictureUpdated(int process_id, int render_view_id) {
852 CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id); 948 CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id);
853 if (render_view_id != web_contents_->GetRoutingID()) 949 if (render_view_id != web_contents_->GetRoutingID())
854 return; 950 return;
855 951
952 // TODO(leandrogracia): this can be made unconditional once software rendering
953 // uses Ubercompositor. Until then this path is required for SW invalidations.
954 if (on_new_picture_mode_ == kOnNewPictureEnabled) {
955 JNIEnv* env = AttachCurrentThread();
956 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
957 if (!obj.is_null()) {
958 ScopedJavaLocalRef<jobject> picture = CapturePicture(env, obj.obj());
959 Java_AwContents_onNewPicture(env, obj.obj(), picture.obj());
960 }
961 }
962
856 // TODO(leandrogracia): delete when sw rendering uses Ubercompositor. 963 // TODO(leandrogracia): delete when sw rendering uses Ubercompositor.
857 // Invalidation should be provided by the compositor only. 964 // Invalidation should be provided by the compositor only.
858 Invalidate(); 965 Invalidate();
859 } 966 }
860 967
968 skia::RefPtr<SkPicture> AwContents::GetLastCapturedPicture() {
969 // Use the latest available picture if the listener callback is enabled.
970 skia::RefPtr<SkPicture> picture;
971 if (on_new_picture_mode_ == kOnNewPictureEnabled)
972 picture = RendererPictureMap::GetInstance()->GetRendererPicture(
973 web_contents_->GetRoutingID());
974
975 // If not available or not in listener mode get it synchronously.
976 if (!picture) {
977 render_view_host_ext_->CapturePictureSync();
978 picture = RendererPictureMap::GetInstance()->GetRendererPicture(
979 web_contents_->GetRoutingID());
980 }
981
982 return picture;
983 }
984
861 } // namespace android_webview 985 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698