12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "android_webview/native/java_browser_view_renderer_helper.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <android/bitmap.h>
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "android_webview/common/aw_switches.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "android_webview/public/browser/draw_sw.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/debug/trace_event.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "jni/JavaBrowserViewRendererHelper_jni.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/skia/include/utils/SkCanvasStateUtils.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::JavaRef;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::ScopedJavaLocalRef;
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace android_webview {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Provides software rendering functions from the Android glue layer.
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Allows preventing extra copies of data when rendering.
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AwDrawSWFunctionTable* g_sw_draw_functions = NULL;
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ScopedPixelAccess {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScopedPixelAccess(JNIEnv* env, jobject java_canvas) : pixels_(NULL) {
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (g_sw_draw_functions && !switches::ForceAuxiliaryBitmap())
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      pixels_ = g_sw_draw_functions->access_pixels(env, java_canvas);
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ~ScopedPixelAccess() {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (pixels_)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      g_sw_draw_functions->release_pixels(pixels_);
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AwPixelInfo* pixels() { return pixels_; }
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AwPixelInfo* pixels_;
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess);
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable(
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    AwDrawSWFunctionTable* table) {
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  g_sw_draw_functions = table;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochJavaBrowserViewRendererHelper* JavaBrowserViewRendererHelper::GetInstance() {
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static JavaBrowserViewRendererHelper* g_instance =
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new JavaBrowserViewRendererHelper;
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return g_instance;
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserViewRendererJavaHelper* BrowserViewRendererJavaHelper::GetInstance() {
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return JavaBrowserViewRendererHelper::GetInstance();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)JavaBrowserViewRendererHelper::JavaBrowserViewRendererHelper() {}
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() {}
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmapIfNeeded(
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    jobject java_canvas,
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Vector2d& scroll_correction,
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& auxiliary_bitmap_size,
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    RenderMethod render_source) {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TRACE_EVENT0("android_webview", "RenderViaAuxilaryBitmapIfNeeded");
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScopedPixelAccess auto_release_pixels(env, java_canvas);
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AwPixelInfo* pixels = auto_release_pixels.pixels();
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (pixels && pixels->state) {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        SkCanvasStateUtils::CreateFromCanvasState(pixels->state));
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Workarounds for http://crbug.com/271096: SW draw only supports
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // translate & scale transforms, and a simple rectangular clip.
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (canvas && (!canvas->isClipRect() ||
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   (canvas->getTotalMatrix().getType() &
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)))) {
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      canvas.clear();
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (canvas) {
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      canvas->translate(scroll_correction.x(), scroll_correction.y());
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return render_source.Run(canvas.get());
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return RenderViaAuxilaryBitmap(env,
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 java_canvas,
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 scroll_correction,
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 auxiliary_bitmap_size,
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 render_source);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmap(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    JNIEnv* env,
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    jobject java_canvas,
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Vector2d& scroll_correction,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& auxiliary_bitmap_size,
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const RenderMethod& render_source) {
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Render into an auxiliary bitmap if pixel info is not available.
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (auxiliary_bitmap_size.width() <= 0 || auxiliary_bitmap_size.height() <= 0)
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScopedJavaLocalRef<jobject> jbitmap(
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Java_JavaBrowserViewRendererHelper_createBitmap(
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          env,
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          auxiliary_bitmap_size.width(),
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          auxiliary_bitmap_size.height(),
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          jcanvas.obj()));
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!jbitmap.obj())
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!RasterizeIntoBitmap(env,
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           jbitmap,
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           render_source)) {
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      env,
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      jbitmap.obj(),
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      jcanvas.obj(),
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scroll_correction.x(),
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scroll_correction.y());
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool RegisterJavaBrowserViewRendererHelper(JNIEnv* env) {
1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return RegisterNativesImpl(env);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool JavaBrowserViewRendererHelper::RasterizeIntoBitmap(
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    JNIEnv* env,
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const JavaRef<jobject>& jbitmap,
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const JavaBrowserViewRendererHelper::RenderMethod& renderer) {
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(jbitmap.obj());
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AndroidBitmapInfo bitmap_info;
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) {
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Error getting java bitmap info.";
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void* pixels = NULL;
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) {
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Error locking java bitmap pixels.";
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool succeeded;
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  {
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SkImageInfo info =
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        SkImageInfo::MakeN32Premul(bitmap_info.width, bitmap_info.height);
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SkBitmap bitmap;
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bitmap.installPixels(info, pixels, bitmap_info.stride);
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SkCanvas canvas(bitmap);
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    succeeded = renderer.Run(&canvas);
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (AndroidBitmap_unlockPixels(env, jbitmap.obj()) < 0) {
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Error unlocking java bitmap pixels.";
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return succeeded;
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace android_webview
183