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