Port Android relocation packer to chromium build
[chromium-blink-merge.git] / android_webview / native / java_browser_view_renderer_helper.cc
blob6e6ce39c519976fc453e676ef881bfcde064add4
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "android_webview/native/java_browser_view_renderer_helper.h"
7 #include <android/bitmap.h>
9 #include "android_webview/public/browser/draw_sw.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/trace_event/trace_event.h"
12 #include "jni/JavaBrowserViewRendererHelper_jni.h"
13 #include "third_party/skia/include/core/SkBitmap.h"
14 #include "third_party/skia/include/utils/SkCanvasStateUtils.h"
16 using base::android::ScopedJavaLocalRef;
18 namespace android_webview {
20 namespace {
22 // Provides software rendering functions from the Android glue layer.
23 // Allows preventing extra copies of data when rendering.
24 AwDrawSWFunctionTable* g_sw_draw_functions = NULL;
26 class JavaCanvasHolder : public SoftwareCanvasHolder {
27 public:
28 JavaCanvasHolder(JNIEnv* env,
29 jobject java_canvas,
30 const gfx::Vector2d& scroll_correction);
31 ~JavaCanvasHolder() override;
33 SkCanvas* GetCanvas() override;
35 private:
36 AwPixelInfo* pixels_;
37 skia::RefPtr<SkCanvas> canvas_;
38 DISALLOW_COPY_AND_ASSIGN(JavaCanvasHolder);
41 JavaCanvasHolder::JavaCanvasHolder(JNIEnv* env,
42 jobject java_canvas,
43 const gfx::Vector2d& scroll)
44 : pixels_(nullptr) {
45 if (!g_sw_draw_functions)
46 return;
47 pixels_ = g_sw_draw_functions->access_pixels(env, java_canvas);
48 if (!pixels_ || !pixels_->state)
49 return;
51 canvas_ =
52 skia::AdoptRef(SkCanvasStateUtils::CreateFromCanvasState(pixels_->state));
53 // Workarounds for http://crbug.com/271096: SW draw only supports
54 // translate & scale transforms, and a simple rectangular clip.
55 if (canvas_ && (!canvas_->isClipRect() ||
56 (canvas_->getTotalMatrix().getType() &
57 ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)))) {
58 canvas_.clear();
60 if (canvas_) {
61 canvas_->translate(scroll.x(), scroll.y());
65 JavaCanvasHolder::~JavaCanvasHolder() {
66 canvas_.clear();
67 if (pixels_)
68 g_sw_draw_functions->release_pixels(pixels_);
69 pixels_ = nullptr;
72 SkCanvas* JavaCanvasHolder::GetCanvas() {
73 return canvas_.get();
76 class AuxiliaryCanvasHolder : public SoftwareCanvasHolder {
77 public:
78 AuxiliaryCanvasHolder(JNIEnv* env,
79 jobject java_canvas,
80 const gfx::Vector2d& scroll_correction,
81 const gfx::Size size);
82 ~AuxiliaryCanvasHolder() override;
84 SkCanvas* GetCanvas() override;
86 private:
87 ScopedJavaLocalRef<jobject> jcanvas_;
88 ScopedJavaLocalRef<jobject> jbitmap_;
89 gfx::Vector2d scroll_;
90 scoped_ptr<SkBitmap> bitmap_;
91 skia::RefPtr<SkCanvas> canvas_;
92 DISALLOW_COPY_AND_ASSIGN(AuxiliaryCanvasHolder);
95 AuxiliaryCanvasHolder::AuxiliaryCanvasHolder(
96 JNIEnv* env,
97 jobject java_canvas,
98 const gfx::Vector2d& scroll_correction,
99 const gfx::Size size)
100 : jcanvas_(env, java_canvas), scroll_(scroll_correction) {
101 DCHECK(size.width() > 0);
102 DCHECK(size.height() > 0);
103 jbitmap_ = Java_JavaBrowserViewRendererHelper_createBitmap(
104 env, size.width(), size.height(), jcanvas_.obj());
105 if (!jbitmap_.obj())
106 return;
108 AndroidBitmapInfo bitmap_info;
109 if (AndroidBitmap_getInfo(env, jbitmap_.obj(), &bitmap_info) < 0) {
110 LOG(ERROR) << "Error getting java bitmap info.";
111 return;
114 void* pixels = nullptr;
115 if (AndroidBitmap_lockPixels(env, jbitmap_.obj(), &pixels) < 0) {
116 LOG(ERROR) << "Error locking java bitmap pixels.";
117 return;
120 SkImageInfo info =
121 SkImageInfo::MakeN32Premul(bitmap_info.width, bitmap_info.height);
122 bitmap_.reset(new SkBitmap);
123 bitmap_->installPixels(info, pixels, bitmap_info.stride);
124 canvas_ = skia::AdoptRef(new SkCanvas(*bitmap_));
127 AuxiliaryCanvasHolder::~AuxiliaryCanvasHolder() {
128 canvas_.clear();
129 bitmap_.reset();
131 JNIEnv* env = base::android::AttachCurrentThread();
132 if (AndroidBitmap_unlockPixels(env, jbitmap_.obj()) < 0) {
133 LOG(ERROR) << "Error unlocking java bitmap pixels.";
134 return;
137 Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
138 env, jbitmap_.obj(), jcanvas_.obj(), scroll_.x(), scroll_.y());
141 SkCanvas* AuxiliaryCanvasHolder::GetCanvas() {
142 return canvas_.get();
145 } // namespace
147 void RasterHelperSetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table) {
148 g_sw_draw_functions = table;
151 // static
152 scoped_ptr<SoftwareCanvasHolder> SoftwareCanvasHolder::Create(
153 jobject java_canvas,
154 const gfx::Vector2d& scroll_correction,
155 const gfx::Size& auxiliary_bitmap_size) {
156 JNIEnv* env = base::android::AttachCurrentThread();
157 scoped_ptr<SoftwareCanvasHolder> holder(
158 new JavaCanvasHolder(env, java_canvas, scroll_correction));
159 if (!holder->GetCanvas()) {
160 holder.reset();
161 holder.reset(new AuxiliaryCanvasHolder(env, java_canvas, scroll_correction,
162 auxiliary_bitmap_size));
164 if (!holder->GetCanvas()) {
165 holder.reset();
167 return holder;
170 bool RegisterJavaBrowserViewRendererHelper(JNIEnv* env) {
171 return RegisterNativesImpl(env);
174 } // namespace android_webview