1a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon/*
2a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * Copyright (C) 2012 The Android Open Source Project
3a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *
4a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * Licensed under the Apache License, Version 2.0 (the "License");
5a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * you may not use this file except in compliance with the License.
6a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * You may obtain a copy of the License at
7a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *
8a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *      http://www.apache.org/licenses/LICENSE-2.0
9a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon *
10a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * Unless required by applicable law or agreed to in writing, software
11a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * distributed under the License is distributed on an "AS IS" BASIS,
12a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * See the License for the specific language governing permissions and
14a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon * limitations under the License.
15a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon */
16a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
17a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// Provides a webviewchromium glue layer adapter from the internal Android
18a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon// GL Functor data types into the types the chromium stack expects, and back.
19a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
20a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#define LOG_TAG "webviewchromium_plat_support"
21a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
22a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#include "android_webview/public/browser/draw_gl.h"
23a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
24d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu#include <errno.h>
25a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#include <jni.h>
26a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#include <private/hwui/DrawGlInfo.h>
27d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu#include <string.h>
28d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu#include <sys/resource.h>
29d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu#include <sys/time.h>
30a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#include <utils/Functor.h>
31a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#include <utils/Log.h>
32a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
33a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
34a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon#define COMPILE_ASSERT(expr, err) static const char err[(expr) ? 1 : -1] = "";
35a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
36a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonnamespace android {
37a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonnamespace {
38a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
39a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan DixonAwDrawGLFunction* g_aw_drawgl_function = NULL;
40a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
41a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonclass DrawGLFunctor : public Functor {
42a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon public:
43a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  DrawGLFunctor(jint view_context) : view_context_(view_context) {}
44a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  virtual ~DrawGLFunctor() {}
45a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
46a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  // Functor
47a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  virtual status_t operator ()(int what, void* data) {
48a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    using uirenderer::DrawGlInfo;
49a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    if (!g_aw_drawgl_function) {
50a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon      ALOGE("Cannot draw: no DrawGL Function installed");
51a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon      return DrawGlInfo::kStatusDone;
52a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
53a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
54a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    AwDrawGLInfo aw_info;
55a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.mode = (what == DrawGlInfo::kModeProcess) ?
56a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        AwDrawGLInfo::kModeProcess : AwDrawGLInfo::kModeDraw;
57a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    DrawGlInfo* gl_info = reinterpret_cast<DrawGlInfo*>(data);
58a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
59a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Map across the input values.
60a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.clip_left = gl_info->clipLeft;
61a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.clip_top = gl_info->clipTop;
62a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.clip_right = gl_info->clipRight;
63a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.clip_bottom = gl_info->clipBottom;
64a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.width = gl_info->width;
65a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.height = gl_info->height;
66a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.is_layer = gl_info->isLayer;
67a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    COMPILE_ASSERT(NELEM(aw_info.transform) == NELEM(gl_info->transform),
68a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon                   mismatched_transform_matrix_sizes);
69a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    for (int i = 0; i < NELEM(aw_info.transform); ++i) {
70a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon      aw_info.transform[i] = gl_info->transform[i];
71a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
72a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
73a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Also pre-initialize the output fields in case the implementation does
74a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // not modify them.
75a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.status_mask = AwDrawGLInfo::kStatusMaskDone;
76a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.dirty_left = gl_info->dirtyLeft;
77a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.dirty_top = gl_info->dirtyTop;
78a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.dirty_right = gl_info->dirtyRight;
79a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    aw_info.dirty_bottom = gl_info->dirtyBottom;
80a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
81a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Invoke the DrawGL method.
82a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    g_aw_drawgl_function(view_context_, &aw_info, NULL);
83a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
84a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Copy out the outputs.
85a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    gl_info->dirtyLeft = aw_info.dirty_left;
86a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    gl_info->dirtyTop = aw_info.dirty_top;
87a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    gl_info->dirtyRight = aw_info.dirty_right;
88a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    gl_info->dirtyBottom = aw_info.dirty_bottom;
89a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
90a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    // Calculate the return code.
91a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    status_t res = DrawGlInfo::kStatusDone;
92a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    if (aw_info.status_mask & AwDrawGLInfo::kStatusMaskDraw)
93a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon      res |= DrawGlInfo::kStatusDraw;
94a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    if (aw_info.status_mask & AwDrawGLInfo::kStatusMaskInvoke)
95a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon      res |= DrawGlInfo::kStatusInvoke;
96a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
97a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    return res;
98a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  }
99a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
100a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon private:
101a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  int view_context_;
102a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon};
103a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
104d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu// Raise the file handle soft limit to the hard limit since gralloc buffers
105d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu// uses file handles.
106d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liuvoid RaiseFileNumberLimit() {
107d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  static bool have_raised_limit = false;
108d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  if (have_raised_limit)
109d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu    return;
110d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu
111d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  have_raised_limit = true;
112d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  struct rlimit limit_struct;
113d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  limit_struct.rlim_cur = 0;
114d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  limit_struct.rlim_max = 0;
115d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  if (getrlimit(RLIMIT_NOFILE, &limit_struct) == 0) {
116d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu    limit_struct.rlim_cur = limit_struct.rlim_max;
117d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu    if (setrlimit(RLIMIT_NOFILE, &limit_struct) != 0) {
118d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu      ALOGE("setrlimit failed: %s", strerror(errno));
119d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu    }
120d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  } else {
121d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu    ALOGE("getrlimit failed: %s", strerror(errno));
122d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  }
123d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu}
124d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu
125a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonjint CreateGLFunctor(JNIEnv*, jclass, jint view_context) {
126d18983cc7040f96a2283c0a318f25fe4474d72ffBo Liu  RaiseFileNumberLimit();
127a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  return reinterpret_cast<jint>(new DrawGLFunctor(view_context));
128a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}
129a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
130a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonvoid DestroyGLFunctor(JNIEnv*, jclass, jint functor) {
131a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  delete reinterpret_cast<DrawGLFunctor*>(functor);
132a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}
133a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
134a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonvoid SetChromiumAwDrawGLFunction(JNIEnv*, jclass, jint draw_function) {
135a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  g_aw_drawgl_function = reinterpret_cast<AwDrawGLFunction*>(draw_function);
136a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}
137a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
138a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonconst char kClassName[] = "com/android/webview/chromium/DrawGLFunctor";
139a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonconst JNINativeMethod kJniMethods[] = {
140a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    { "nativeCreateGLFunctor", "(I)I",
141991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon        reinterpret_cast<void*>(CreateGLFunctor) },
142a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    { "nativeDestroyGLFunctor", "(I)V",
143991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon        reinterpret_cast<void*>(DestroyGLFunctor) },
144a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    { "nativeSetChromiumAwDrawGLFunction", "(I)V",
145991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon        reinterpret_cast<void*>(SetChromiumAwDrawGLFunction) },
146a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon};
147a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
148a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}  // namespace
149a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
150a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonvoid RegisterDrawGLFunctor(JNIEnv* env) {
151a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  jclass clazz = env->FindClass(kClassName);
152a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
153a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
154a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
155a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon  LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
156a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}
157a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
158a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon}  // namespace android
159