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
{
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
{
28 JavaCanvasHolder(JNIEnv
* env
,
30 const gfx::Vector2d
& scroll_correction
);
31 ~JavaCanvasHolder() override
;
33 SkCanvas
* GetCanvas() override
;
37 skia::RefPtr
<SkCanvas
> canvas_
;
38 DISALLOW_COPY_AND_ASSIGN(JavaCanvasHolder
);
41 JavaCanvasHolder::JavaCanvasHolder(JNIEnv
* env
,
43 const gfx::Vector2d
& scroll
)
45 if (!g_sw_draw_functions
)
47 pixels_
= g_sw_draw_functions
->access_pixels(env
, java_canvas
);
48 if (!pixels_
|| !pixels_
->state
)
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
)))) {
61 canvas_
->translate(scroll
.x(), scroll
.y());
65 JavaCanvasHolder::~JavaCanvasHolder() {
68 g_sw_draw_functions
->release_pixels(pixels_
);
72 SkCanvas
* JavaCanvasHolder::GetCanvas() {
76 class AuxiliaryCanvasHolder
: public SoftwareCanvasHolder
{
78 AuxiliaryCanvasHolder(JNIEnv
* env
,
80 const gfx::Vector2d
& scroll_correction
,
81 const gfx::Size size
);
82 ~AuxiliaryCanvasHolder() override
;
84 SkCanvas
* GetCanvas() override
;
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(
98 const gfx::Vector2d
& scroll_correction
,
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());
108 AndroidBitmapInfo bitmap_info
;
109 if (AndroidBitmap_getInfo(env
, jbitmap_
.obj(), &bitmap_info
) < 0) {
110 LOG(ERROR
) << "Error getting java bitmap info.";
114 void* pixels
= nullptr;
115 if (AndroidBitmap_lockPixels(env
, jbitmap_
.obj(), &pixels
) < 0) {
116 LOG(ERROR
) << "Error locking java bitmap pixels.";
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() {
131 JNIEnv
* env
= base::android::AttachCurrentThread();
132 if (AndroidBitmap_unlockPixels(env
, jbitmap_
.obj()) < 0) {
133 LOG(ERROR
) << "Error unlocking java bitmap pixels.";
137 Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
138 env
, jbitmap_
.obj(), jcanvas_
.obj(), scroll_
.x(), scroll_
.y());
141 SkCanvas
* AuxiliaryCanvasHolder::GetCanvas() {
142 return canvas_
.get();
147 void RasterHelperSetAwDrawSWFunctionTable(AwDrawSWFunctionTable
* table
) {
148 g_sw_draw_functions
= table
;
152 scoped_ptr
<SoftwareCanvasHolder
> SoftwareCanvasHolder::Create(
154 const gfx::Vector2d
& scroll_correction
,
155 const gfx::Size
& auxiliary_bitmap_size
,
156 bool force_auxiliary_bitmap
) {
157 JNIEnv
* env
= base::android::AttachCurrentThread();
158 scoped_ptr
<SoftwareCanvasHolder
> holder
;
159 if (!force_auxiliary_bitmap
) {
160 holder
.reset(new JavaCanvasHolder(env
, java_canvas
, scroll_correction
));
162 if (!holder
.get() || !holder
->GetCanvas()) {
164 holder
.reset(new AuxiliaryCanvasHolder(env
, java_canvas
, scroll_correction
,
165 auxiliary_bitmap_size
));
167 if (!holder
->GetCanvas()) {
173 bool RegisterJavaBrowserViewRendererHelper(JNIEnv
* env
) {
174 return RegisterNativesImpl(env
);
177 } // namespace android_webview