Index: android_webview/native/aw_contents.cc |
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc |
index 8d7e53c9c984bbf520d0f3f3fdc852ab970bb04f..51c6b14fb5e5652ab0ea333a9acdf1f4881b36c2 100644 |
--- a/android_webview/native/aw_contents.cc |
+++ b/android_webview/native/aw_contents.cc |
@@ -37,11 +37,9 @@ |
#include "content/public/common/ssl_status.h" |
#include "jni/AwContents_jni.h" |
#include "net/base/x509_certificate.h" |
-#include "skia/ext/refptr.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
#include "third_party/skia/include/core/SkDevice.h" |
-#include "third_party/skia/include/core/SkPicture.h" |
#include "ui/gfx/transform.h" |
#include "ui/gl/gl_bindings.h" |
@@ -61,6 +59,8 @@ using base::android::ConvertJavaStringToUTF16; |
using base::android::ConvertJavaStringToUTF8; |
using base::android::ConvertUTF16ToJavaString; |
using base::android::ConvertUTF8ToJavaString; |
+using base::android::GetClass; |
+using base::android::GetFieldID; |
using base::android::JavaRef; |
using base::android::ScopedJavaGlobalRef; |
using base::android::ScopedJavaLocalRef; |
@@ -122,6 +122,8 @@ AwContents::AwContents(JNIEnv* env, |
view_visible_(false), |
compositor_visible_(false), |
is_composite_pending_(false), |
+ on_new_picture_enabled_(false), |
+ on_new_picture_invalidation_only_(false), |
last_frame_context_(NULL) { |
RendererPictureMap::CreateInstance(); |
android_webview::AwBrowserDependencyFactory* dependency_factory = |
@@ -380,9 +382,11 @@ void AwContents::DrawGL(AwDrawGLInfo* draw_info) { |
} |
bool AwContents::DrawSW(JNIEnv* env, jobject obj, jobject java_canvas) { |
- skia::RefPtr<SkPicture> picture = |
- RendererPictureMap::GetInstance()->GetRendererPicture( |
- web_contents_->GetRoutingID()); |
+ // TODO(leandrogracia): once Ubercompositor is ready and we support software |
+ // rendering mode, we should avoid this as much as we can, ideally always. |
+ // This includes finding a proper replacement for onDraw calls in hardware |
+ // mode with software canvases. |
+ skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
if (!picture) |
return false; |
@@ -683,7 +687,11 @@ void AwContents::Invalidate() { |
if (obj.is_null()) |
return; |
- Java_AwContents_invalidate(env, obj.obj()); |
+ if (view_visible_) |
+ Java_AwContents_invalidate(env, obj.obj()); |
+ |
+ if (on_new_picture_enabled_ && on_new_picture_invalidation_only_) |
+ Java_AwContents_onNewPicture(env, obj.obj(), 0, 0, 0); |
} |
void AwContents::SetCompositorVisibility(bool visible) { |
@@ -835,14 +843,79 @@ jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) { |
return reinterpret_cast<jint>(pending_contents_.release()); |
} |
+void AwContents::CapturePicture(JNIEnv* env, |
+ jobject obj, |
+ jobject picture_data) { |
+ skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
+ ScopedJavaLocalRef<jclass> external_picture_class = GetClass(env, |
+ "org/chromium/android_webview/AwContentsClient$ExternalPictureData"); |
+ env->SetIntField(picture_data, |
+ GetFieldID(env, external_picture_class, "nativePicture", "I"), |
+ reinterpret_cast<jint>(picture.get())); |
+ env->SetIntField(picture_data, |
+ GetFieldID(env, external_picture_class, "width", "I"), |
+ picture ? picture->width() : 0); |
+ env->SetIntField(picture_data, |
+ GetFieldID(env, external_picture_class, "height", "I"), |
+ picture ? picture->height() : 0); |
+} |
+ |
+void AwContents::EnableOnNewPicture(JNIEnv* env, |
+ jobject obj, |
+ jboolean enabled, |
+ jboolean invalidation_only) { |
+ on_new_picture_enabled_ = enabled; |
+ on_new_picture_invalidation_only_ = invalidation_only; |
+ |
+ // If onNewPicture is triggered only on invalidation do not capture |
+ // pictures on every new frame. |
+ if (on_new_picture_invalidation_only_) |
+ return; |
+ |
+ // TODO(leandrogracia): uncomment when sw rendering uses Ubercompositor. |
+ // Until then we need the callback enabled for SW mode invalidation. |
+ // render_view_host_ext_->EnableCapturePictureCallback(enabled); |
+} |
+ |
void AwContents::OnPictureUpdated(int process_id, int render_view_id) { |
CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id); |
if (render_view_id != web_contents_->GetRoutingID()) |
return; |
+ // TODO(leandrogracia): this can be made unconditional once software rendering |
+ // uses Ubercompositor. Until then this path is required for SW invalidations. |
+ if (on_new_picture_enabled_ && !on_new_picture_invalidation_only_) { |
+ JNIEnv* env = AttachCurrentThread(); |
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
+ if (!obj.is_null()) { |
+ skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
+ Java_AwContents_onNewPicture(env, obj.obj(), |
+ reinterpret_cast<jint>(picture.get()), |
+ picture ? picture->width() : 0, |
+ picture ? picture->height() : 0); |
+ } |
+ } |
+ |
// TODO(leandrogracia): delete when sw rendering uses Ubercompositor. |
// Invalidation should be provided by the compositor only. |
Invalidate(); |
} |
+skia::RefPtr<SkPicture> AwContents::GetLastCapturedPicture() { |
+ // Use the latest available picture if the listener callback is enabled. |
+ skia::RefPtr<SkPicture> picture; |
+ if (on_new_picture_enabled_) |
+ picture = RendererPictureMap::GetInstance()->GetRendererPicture( |
+ web_contents_->GetRoutingID()); |
+ |
+ // If not available or not in listener mode get it synchronously. |
+ if (!picture) { |
+ render_view_host_ext_->CapturePictureSync(); |
+ picture = RendererPictureMap::GetInstance()->GetRendererPicture( |
+ web_contents_->GetRoutingID()); |
+ } |
+ |
+ return picture; |
+} |
+ |
} // namespace android_webview |