1991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon/*
2991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * Copyright (C) 2012 The Android Open Source Project
3991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon *
4991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * Licensed under the Apache License, Version 2.0 (the "License");
5991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * you may not use this file except in compliance with the License.
6991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * You may obtain a copy of the License at
7991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon *
8991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon *      http://www.apache.org/licenses/LICENSE-2.0
9991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon *
10991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * Unless required by applicable law or agreed to in writing, software
11991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * distributed under the License is distributed on an "AS IS" BASIS,
12991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * See the License for the specific language governing permissions and
14991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon * limitations under the License.
15991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon */
16991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
17991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon// Provides a webviewchromium glue layer adapter from the internal Android
18991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon// graphics types into the types the chromium stack expects, and back.
19991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
20991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#define LOG_TAG "webviewchromium_plat_support"
21991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
22e4be25a7c5d547be06ed43166d82237cb08ad38aMarcin Kosiba#include "draw_gl.h"
23e4be25a7c5d547be06ed43166d82237cb08ad38aMarcin Kosiba#include "draw_sw.h"
24991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
25991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#include <cstdlib>
26991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#include <jni.h>
27991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#include <utils/Log.h>
28c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu#include "graphic_buffer_impl.h"
29991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#include "GraphicsJNI.h"
30a4f187ef3723a330f2145cea5a4f83e486199137Jonathan Dixon#include "SkCanvasStateUtils.h"
31f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil#include "SkGraphics.h"
32f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil#include "SkPicture.h"
33991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
34991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
35991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
36991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonnamespace android {
37991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonnamespace {
38991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
395c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixonclass PixelInfo : public AwPixelInfo {
405c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon public:
41a4f187ef3723a330f2145cea5a4f83e486199137Jonathan Dixon  PixelInfo(SkCanvas* canvas);
425c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon  ~PixelInfo();
43991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon};
44991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
455c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon
46a4f187ef3723a330f2145cea5a4f83e486199137Jonathan DixonPixelInfo::PixelInfo(SkCanvas* canvas) {
47364e97a049927e74db4888d19c2f4cee17e91a27Jonathan Dixon  memset(this, 0, sizeof(AwPixelInfo));
48364e97a049927e74db4888d19c2f4cee17e91a27Jonathan Dixon  version = kAwPixelInfoVersion;
49a4f187ef3723a330f2145cea5a4f83e486199137Jonathan Dixon  state = SkCanvasStateUtils::CaptureCanvasState(canvas);
50364e97a049927e74db4888d19c2f4cee17e91a27Jonathan Dixon}
515c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon
52a4f187ef3723a330f2145cea5a4f83e486199137Jonathan DixonPixelInfo::~PixelInfo() {
53a4f187ef3723a330f2145cea5a4f83e486199137Jonathan Dixon  if (state)
54a4f187ef3723a330f2145cea5a4f83e486199137Jonathan Dixon    SkCanvasStateUtils::ReleaseCanvasState(state);
555c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon}
565c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon
575c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan DixonAwPixelInfo* GetPixels(JNIEnv* env, jobject java_canvas) {
58165a43df7df4aa5121697893c31b9571492939bcJohn Reck  android::Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, java_canvas);
59165a43df7df4aa5121697893c31b9571492939bcJohn Reck  if (!nativeCanvas)
60165a43df7df4aa5121697893c31b9571492939bcJohn Reck    return NULL;
61165a43df7df4aa5121697893c31b9571492939bcJohn Reck
62165a43df7df4aa5121697893c31b9571492939bcJohn Reck  SkCanvas* canvas = nativeCanvas->asSkCanvas();
635c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon  if (!canvas)
645c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon    return NULL;
655c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon
6686abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // Workarounds for http://crbug.com/271096: SW draw only supports
6786abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // translate & scale transforms, and a simple rectangular clip.
6886abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // (This also avoids significant wasted time in calling
6986abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
70e841604a0e87664b009fe713167db941a41604b4Leon Scroggins  if (!canvas->isClipRect() ||
7186abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon      (canvas->getTotalMatrix().getType() &
7286abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon                ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
7386abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon    return NULL;
7486abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  }
7586abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon
768ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  PixelInfo* pixels = new PixelInfo(canvas);
778ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  if (!pixels->state) {
788ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch      delete pixels;
798ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch      pixels = NULL;
808ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  }
818ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  return pixels;
82991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
83991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
84991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonvoid ReleasePixels(AwPixelInfo* pixels) {
85991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  delete static_cast<PixelInfo*>(pixels);
86991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
87991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
882ddcc98cb29e567ea545b3eba2fedc576d1f5365Ross McIlroyjlong GetDrawSWFunctionTable(JNIEnv* env, jclass) {
894cb347aeb733d199418472de549c24a31d3e7477Bo Liu  static AwDrawSWFunctionTable function_table;
90df44c7670d1fa36fffb614ce04bf16ba25ef65d0Bo Liu  function_table.version = kAwDrawSWFunctionTableVersion;
914cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.access_pixels = &GetPixels;
924cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.release_pixels = &ReleasePixels;
932ddcc98cb29e567ea545b3eba2fedc576d1f5365Ross McIlroy  return reinterpret_cast<intptr_t>(&function_table);
94991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
95991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
962ddcc98cb29e567ea545b3eba2fedc576d1f5365Ross McIlroyjlong GetDrawGLFunctionTable(JNIEnv* env, jclass) {
974cb347aeb733d199418472de549c24a31d3e7477Bo Liu  static AwDrawGLFunctionTable function_table;
98df44c7670d1fa36fffb614ce04bf16ba25ef65d0Bo Liu  function_table.version = kAwDrawGLFunctionTableVersion;
994cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.create_graphic_buffer = &GraphicBufferImpl::Create;
1004cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.release_graphic_buffer = &GraphicBufferImpl::Release;
1014cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.map = &GraphicBufferImpl::MapStatic;
1024cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.unmap = &GraphicBufferImpl::UnmapStatic;
1034cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.get_native_buffer = &GraphicBufferImpl::GetNativeBufferStatic;
1044cb347aeb733d199418472de549c24a31d3e7477Bo Liu  function_table.get_stride = &GraphicBufferImpl::GetStrideStatic;
1052ddcc98cb29e567ea545b3eba2fedc576d1f5365Ross McIlroy  return reinterpret_cast<intptr_t>(&function_table);
106c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu}
107c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu
108991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonconst char kClassName[] = "com/android/webview/chromium/GraphicsUtils";
109991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonconst JNINativeMethod kJniMethods[] = {
11058702ab5d6fe80a179dff41ec1741cf3cd7bf3dfRoss McIlroy    { "nativeGetDrawSWFunctionTable", "()J",
111991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon        reinterpret_cast<void*>(GetDrawSWFunctionTable) },
11258702ab5d6fe80a179dff41ec1741cf3cd7bf3dfRoss McIlroy    { "nativeGetDrawGLFunctionTable", "()J",
113c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu        reinterpret_cast<void*>(GetDrawGLFunctionTable) },
114991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon};
115991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
116991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}  // namespace
117991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
118991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonvoid RegisterGraphicsUtils(JNIEnv* env) {
119991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  jclass clazz = env->FindClass(kClassName);
120991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
121991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
122991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
123991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
124991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
125991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
126991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}  // namespace android
127