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