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
22c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu#include "android_webview/public/browser/draw_gl.h"
23991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon#include "android_webview/public/browser/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) {
585c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon  SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, java_canvas);
595c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon  if (!canvas)
605c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon    return NULL;
615c324e7af9e99afec4caf6cd48aecf2d1a596b28Jonathan Dixon
6286abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // Workarounds for http://crbug.com/271096: SW draw only supports
6386abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // translate & scale transforms, and a simple rectangular clip.
6486abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // (This also avoids significant wasted time in calling
6586abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  // SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
6686abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  if (!canvas->getTotalClip().isRect() ||
6786abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon      (canvas->getTotalMatrix().getType() &
6886abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon                ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
6986abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon    return NULL;
7086abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon  }
7186abeb66b6f8237f85ccce79495f15ace437a96aJonathan Dixon
728ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  PixelInfo* pixels = new PixelInfo(canvas);
738ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  if (!pixels->state) {
748ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch      delete pixels;
758ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch      pixels = NULL;
768ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  }
778ec5fb8559251164082b3f050c090ceb740a14e8Ben Murdoch  return pixels;
78991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
79991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
80991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonvoid ReleasePixels(AwPixelInfo* pixels) {
81991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  delete static_cast<PixelInfo*>(pixels);
82991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
83991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
84f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Giljobject CreatePicture(JNIEnv* env, SkPicture* picture) {
85f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  jclass clazz = env->FindClass("android/graphics/Picture");
86f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  jmethodID constructor = env->GetMethodID(clazz, "<init>", "(IZ)V");
87f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  ALOG_ASSERT(clazz);
88f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  ALOG_ASSERT(constructor);
89f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  return env->NewObject(clazz, constructor, picture, false);
90f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil}
91f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil
92f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gilbool IsSkiaVersionCompatible(SkiaVersionFunction function) {
93f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  bool compatible = false;
94f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  if (function && function == &SkGraphics::GetVersion) {
95f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil    int android_major, android_minor, android_patch;
96f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil    SkGraphics::GetVersion(&android_major, &android_minor, &android_patch);
97f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil
98f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil    int chromium_major, chromium_minor, chromium_patch;
99f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil    (*function)(&chromium_major, &chromium_minor, &chromium_patch);
100f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil
101f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil    compatible = android_major == chromium_major &&
102f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil                 android_minor == chromium_minor &&
103f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil                 android_patch == chromium_patch;
104f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  }
105f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil  return compatible;
106f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil}
107f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil
108991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonjint GetDrawSWFunctionTable(JNIEnv* env, jclass) {
109991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  static const AwDrawSWFunctionTable function_table = {
110991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon      &GetPixels,
111991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon      &ReleasePixels,
112f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil      &CreatePicture,
113f15e28c8d30c2ccea58871c9d22f8b47e53d6ea4Leandro Gracia Gil      &IsSkiaVersionCompatible,
114991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  };
115991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  return reinterpret_cast<jint>(&function_table);
116991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
117991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
118c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglujint GetDrawGLFunctionTable(JNIEnv* env, jclass) {
119c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu  static const AwDrawGLFunctionTable function_table = {
1201cc1c4153a26307948af9f1ee6d9cde7a7103b94Kaan Baloglu    &GraphicBufferImpl::Create,
1211cc1c4153a26307948af9f1ee6d9cde7a7103b94Kaan Baloglu    &GraphicBufferImpl::Release,
1221cc1c4153a26307948af9f1ee6d9cde7a7103b94Kaan Baloglu    &GraphicBufferImpl::MapStatic,
1231cc1c4153a26307948af9f1ee6d9cde7a7103b94Kaan Baloglu    &GraphicBufferImpl::UnmapStatic,
1241cc1c4153a26307948af9f1ee6d9cde7a7103b94Kaan Baloglu    &GraphicBufferImpl::GetNativeBufferStatic,
1251cc1c4153a26307948af9f1ee6d9cde7a7103b94Kaan Baloglu    &GraphicBufferImpl::GetStrideStatic,
126c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu  };
127c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu  return reinterpret_cast<jint>(&function_table);
128c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu}
129c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu
130991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonconst char kClassName[] = "com/android/webview/chromium/GraphicsUtils";
131991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonconst JNINativeMethod kJniMethods[] = {
132991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon    { "nativeGetDrawSWFunctionTable", "()I",
133991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon        reinterpret_cast<void*>(GetDrawSWFunctionTable) },
134c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu    { "nativeGetDrawGLFunctionTable", "()I",
135c5cde8c18df853e11d1ec528508fd0fe2e742d5cKaan Baloglu        reinterpret_cast<void*>(GetDrawGLFunctionTable) },
136991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon};
137991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
138991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}  // namespace
139991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
140991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixonvoid RegisterGraphicsUtils(JNIEnv* env) {
141991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  jclass clazz = env->FindClass(kClassName);
142991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
143991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
144991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
145991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon  LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
146991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}
147991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon
148991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon}  // namespace android
149