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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: android_webview/native/aw_contents.cc
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index a44fb06c5c6945cbc8b05ac3e8faea6b47783fce..6387537b0d3527b57548f55904c43194b741f975 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -4,6 +4,7 @@
#include "android_webview/native/aw_contents.h"
+#include <android/bitmap.h>
#include <sys/system_properties.h>
#include "android_webview/browser/aw_browser_main_parts.h"
@@ -37,11 +38,10 @@
#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 "third_party/skia/include/core/SkGraphics.h"
#include "ui/gfx/transform.h"
#include "ui/gl/gl_bindings.h"
@@ -86,6 +86,7 @@ namespace android_webview {
namespace {
AwDrawSWFunctionTable* g_draw_sw_functions = NULL;
+bool g_is_skia_version_compatible = false;
const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
@@ -121,6 +122,7 @@ AwContents::AwContents(JNIEnv* env,
view_visible_(false),
compositor_visible_(false),
is_composite_pending_(false),
+ on_new_picture_mode_(kOnNewPictureDisabled),
last_frame_context_(NULL) {
RendererPictureMap::CreateInstance();
android_webview::AwBrowserDependencyFactory* dependency_factory =
@@ -379,9 +381,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
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.
+ // 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;
@@ -462,6 +466,11 @@ void AwContents::Destroy(JNIEnv* env, jobject obj) {
void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) {
g_draw_sw_functions =
reinterpret_cast<AwDrawSWFunctionTable*>(function_table);
+ // 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
+ //g_is_skia_version_compatible =
+ // g_draw_sw_functions->is_skia_version_compatible(&SkGraphics::GetVersion);
+ if (!g_is_skia_version_compatible)
+ LOG(WARNING) << "Skia native versions are not compatible.";
}
// static
@@ -696,7 +705,13 @@ void AwContents::Invalidate() {
if (obj.is_null())
return;
- Java_AwContents_invalidate(env, obj.obj());
+ if (view_visible_)
+ Java_AwContents_invalidate(env, obj.obj());
+
+ // When not in invalidation-only mode onNewPicture will be triggered
+ // from the OnPictureUpdated callback.
+ if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly)
+ Java_AwContents_onNewPicture(env, obj.obj(), NULL);
}
void AwContents::SetCompositorVisibility(bool visible) {
@@ -848,14 +863,123 @@ jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) {
return reinterpret_cast<jint>(pending_contents_.release());
}
+ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env,
+ jobject obj) {
+ skia::RefPtr<SkPicture> picture = GetLastCapturedPicture();
+ if (!picture || !g_draw_sw_functions)
+ return ScopedJavaLocalRef<jobject>();
+
+ if (g_is_skia_version_compatible)
+ return ScopedJavaLocalRef<jobject>(env,
+ g_draw_sw_functions->create_picture(env, picture->clone()));
+
+ // If Skia versions are not compatible, workaround it by rasterizing the
+ // picture into a bitmap and drawing it into a new Java picture.
+ return ScopedJavaLocalRef<jobject>(
+ Java_AwContents_rasterizeIntoPicture(env, obj,
+ reinterpret_cast<jint>(picture.get()),
+ picture->width(), picture->height()));
+}
+
+// static
+jboolean RasterizePicture(JNIEnv* env,
+ jclass clazz,
+ jobject jbitmap,
+ jint native_picture) {
+ DCHECK(jbitmap);
+ DCHECK(native_picture);
+
+ AndroidBitmapInfo bitmap_info;
+ if (AndroidBitmap_getInfo(env, jbitmap, &bitmap_info) < 0) {
+ LOG(WARNING) << "Error getting java bitmap info.";
+ return false;
+ }
+
+ void* pixels = NULL;
+ if (AndroidBitmap_lockPixels(env, jbitmap, &pixels) < 0) {
+ LOG(WARNING) << "Error locking java bitmap pixels.";
+ return false;
+ }
+
+ {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ bitmap_info.width,
+ bitmap_info.height,
+ bitmap_info.stride);
+ bitmap.setPixels(pixels);
+
+ SkDevice device(bitmap);
+ SkCanvas canvas(&device);
+ SkPicture* picture = reinterpret_cast<SkPicture*>(native_picture);
+ picture->draw(&canvas);
+ }
+
+ if (AndroidBitmap_unlockPixels(env, jbitmap) < 0) {
+ LOG(WARNING) << "Error unlocking java bitmap pixels.";
+ return false;
+ }
+
+ return true;
+}
+
+void AwContents::EnableOnNewPicture(JNIEnv* env,
+ jobject obj,
+ jboolean enabled,
+ jboolean invalidation_only) {
+ if (enabled) {
+ on_new_picture_mode_ = invalidation_only ? kOnNewPictureInvalidationOnly :
+ kOnNewPictureEnabled;
+ } else {
+ on_new_picture_mode_ = kOnNewPictureDisabled;
+ }
+
+ // If onNewPicture is triggered only on invalidation do not capture
+ // pictures on every new frame.
+ if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly)
+ enabled = false;
+
+ // 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_mode_ == kOnNewPictureEnabled) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (!obj.is_null()) {
+ ScopedJavaLocalRef<jobject> picture = CapturePicture(env, obj.obj());
+ Java_AwContents_onNewPicture(env, obj.obj(), picture.obj());
+ }
+ }
+
// 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_mode_ == kOnNewPictureEnabled)
+ 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

Powered by Google App Engine
This is Rietveld 408576698