dom/plugins/base/android/ANPSurface.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include <dlfcn.h>
michael@0 7 #include <android/log.h>
michael@0 8 #include "ANPBase.h"
michael@0 9
michael@0 10 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
michael@0 11 #define ASSIGN(obj, name) (obj)->name = anp_surface_##name
michael@0 12
michael@0 13 #define CLEAR_EXCEPTION(env) if (env->ExceptionOccurred()) env->ExceptionClear();
michael@0 14
michael@0 15 #define ANDROID_REGION_SIZE 512
michael@0 16
michael@0 17 enum {
michael@0 18 PIXEL_FORMAT_RGBA_8888 = 1,
michael@0 19 PIXEL_FORMAT_RGB_565 = 4,
michael@0 20 };
michael@0 21
michael@0 22 struct SurfaceInfo {
michael@0 23 uint32_t w;
michael@0 24 uint32_t h;
michael@0 25 uint32_t s;
michael@0 26 uint32_t usage;
michael@0 27 uint32_t format;
michael@0 28 unsigned char* bits;
michael@0 29 uint32_t reserved[2];
michael@0 30 };
michael@0 31
michael@0 32 typedef struct ARect {
michael@0 33 int32_t left;
michael@0 34 int32_t top;
michael@0 35 int32_t right;
michael@0 36 int32_t bottom;
michael@0 37 } ARect;
michael@0 38
michael@0 39
michael@0 40 // used to cache JNI method and field IDs for Surface Objects
michael@0 41 static struct ANPSurfaceInterfaceJavaGlue {
michael@0 42 bool initialized;
michael@0 43 jmethodID getSurfaceHolder;
michael@0 44 jmethodID getSurface;
michael@0 45 jfieldID surfacePointer;
michael@0 46 } gSurfaceJavaGlue;
michael@0 47
michael@0 48 static struct ANPSurfaceFunctions {
michael@0 49 bool initialized;
michael@0 50
michael@0 51 int (* lock)(void*, SurfaceInfo*, void*);
michael@0 52 int (* unlockAndPost)(void*);
michael@0 53
michael@0 54 void* (* regionConstructor)(void*);
michael@0 55 void (* setRegion)(void*, ARect const&);
michael@0 56 } gSurfaceFunctions;
michael@0 57
michael@0 58
michael@0 59 static inline void* getSurface(JNIEnv* env, jobject view) {
michael@0 60 if (!env || !view) {
michael@0 61 return nullptr;
michael@0 62 }
michael@0 63
michael@0 64 if (!gSurfaceJavaGlue.initialized) {
michael@0 65
michael@0 66 jclass surfaceViewClass = env->FindClass("android/view/SurfaceView");
michael@0 67 gSurfaceJavaGlue.getSurfaceHolder = env->GetMethodID(surfaceViewClass, "getHolder", "()Landroid/view/SurfaceHolder;");
michael@0 68
michael@0 69 jclass surfaceHolderClass = env->FindClass("android/view/SurfaceHolder");
michael@0 70 gSurfaceJavaGlue.getSurface = env->GetMethodID(surfaceHolderClass, "getSurface", "()Landroid/view/Surface;");
michael@0 71
michael@0 72 jclass surfaceClass = env->FindClass("android/view/Surface");
michael@0 73 gSurfaceJavaGlue.surfacePointer = env->GetFieldID(surfaceClass,
michael@0 74 "mSurfacePointer", "I");
michael@0 75
michael@0 76 if (!gSurfaceJavaGlue.surfacePointer) {
michael@0 77 CLEAR_EXCEPTION(env);
michael@0 78
michael@0 79 // It was something else in 2.2.
michael@0 80 gSurfaceJavaGlue.surfacePointer = env->GetFieldID(surfaceClass,
michael@0 81 "mSurface", "I");
michael@0 82
michael@0 83 if (!gSurfaceJavaGlue.surfacePointer) {
michael@0 84 CLEAR_EXCEPTION(env);
michael@0 85
michael@0 86 // And something else in 2.3+
michael@0 87 gSurfaceJavaGlue.surfacePointer = env->GetFieldID(surfaceClass,
michael@0 88 "mNativeSurface", "I");
michael@0 89
michael@0 90 CLEAR_EXCEPTION(env);
michael@0 91 }
michael@0 92 }
michael@0 93
michael@0 94 if (!gSurfaceJavaGlue.surfacePointer) {
michael@0 95 LOG("Failed to acquire surface pointer");
michael@0 96 return nullptr;
michael@0 97 }
michael@0 98
michael@0 99 env->DeleteLocalRef(surfaceClass);
michael@0 100 env->DeleteLocalRef(surfaceViewClass);
michael@0 101 env->DeleteLocalRef(surfaceHolderClass);
michael@0 102
michael@0 103 gSurfaceJavaGlue.initialized = (gSurfaceJavaGlue.surfacePointer != nullptr);
michael@0 104 }
michael@0 105
michael@0 106 jobject holder = env->CallObjectMethod(view, gSurfaceJavaGlue.getSurfaceHolder);
michael@0 107 jobject surface = env->CallObjectMethod(holder, gSurfaceJavaGlue.getSurface);
michael@0 108 jint surfacePointer = env->GetIntField(surface, gSurfaceJavaGlue.surfacePointer);
michael@0 109
michael@0 110 env->DeleteLocalRef(holder);
michael@0 111 env->DeleteLocalRef(surface);
michael@0 112
michael@0 113 return (void*)surfacePointer;
michael@0 114 }
michael@0 115
michael@0 116 static ANPBitmapFormat convertPixelFormat(int32_t format) {
michael@0 117 switch (format) {
michael@0 118 case PIXEL_FORMAT_RGBA_8888: return kRGBA_8888_ANPBitmapFormat;
michael@0 119 case PIXEL_FORMAT_RGB_565: return kRGB_565_ANPBitmapFormat;
michael@0 120 default: return kUnknown_ANPBitmapFormat;
michael@0 121 }
michael@0 122 }
michael@0 123
michael@0 124 static int bytesPerPixel(int32_t format) {
michael@0 125 switch (format) {
michael@0 126 case PIXEL_FORMAT_RGBA_8888: return 4;
michael@0 127 case PIXEL_FORMAT_RGB_565: return 2;
michael@0 128 default: return -1;
michael@0 129 }
michael@0 130 }
michael@0 131
michael@0 132 static bool init() {
michael@0 133 if (gSurfaceFunctions.initialized)
michael@0 134 return true;
michael@0 135
michael@0 136 void* handle = dlopen("libsurfaceflinger_client.so", RTLD_LAZY);
michael@0 137
michael@0 138 if (!handle) {
michael@0 139 LOG("Failed to open libsurfaceflinger_client.so");
michael@0 140 return false;
michael@0 141 }
michael@0 142
michael@0 143 gSurfaceFunctions.lock = (int (*)(void*, SurfaceInfo*, void*))dlsym(handle, "_ZN7android7Surface4lockEPNS0_11SurfaceInfoEPNS_6RegionEb");
michael@0 144 gSurfaceFunctions.unlockAndPost = (int (*)(void*))dlsym(handle, "_ZN7android7Surface13unlockAndPostEv");
michael@0 145
michael@0 146
michael@0 147 if (!gSurfaceFunctions.lock) {
michael@0 148 // Stuff changed in 3.0/4.0
michael@0 149 handle = dlopen("libgui.so", RTLD_LAZY);
michael@0 150 gSurfaceFunctions.lock = (int (*)(void*, SurfaceInfo*, void*))dlsym(handle, "_ZN7android7Surface4lockEPNS0_11SurfaceInfoEPNS_6RegionE");
michael@0 151 gSurfaceFunctions.unlockAndPost = (int (*)(void*))dlsym(handle, "_ZN7android7Surface13unlockAndPostEv");
michael@0 152 }
michael@0 153
michael@0 154 handle = dlopen("libui.so", RTLD_LAZY);
michael@0 155 if (!handle) {
michael@0 156 LOG("Failed to open libui.so");
michael@0 157 return false;
michael@0 158 }
michael@0 159
michael@0 160 gSurfaceFunctions.regionConstructor = (void* (*)(void*))dlsym(handle, "_ZN7android6RegionC1Ev");
michael@0 161 gSurfaceFunctions.setRegion = (void (*)(void*, ARect const&))dlsym(handle, "_ZN7android6Region3setERKNS_4RectE");
michael@0 162
michael@0 163 gSurfaceFunctions.initialized = (gSurfaceFunctions.lock && gSurfaceFunctions.unlockAndPost &&
michael@0 164 gSurfaceFunctions.regionConstructor && gSurfaceFunctions.setRegion);
michael@0 165 LOG("Initialized? %d\n", gSurfaceFunctions.initialized);
michael@0 166 return gSurfaceFunctions.initialized;
michael@0 167 }
michael@0 168
michael@0 169 // FIXME: All of this should be changed to use the equivalent things in AndroidBridge, bug 758612
michael@0 170 static bool anp_surface_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRectI* dirtyRect) {
michael@0 171 if (!bitmap || !surfaceView) {
michael@0 172 return false;
michael@0 173 }
michael@0 174
michael@0 175 void* surface = getSurface(env, surfaceView);
michael@0 176
michael@0 177 if (!bitmap || !surface) {
michael@0 178 return false;
michael@0 179 }
michael@0 180
michael@0 181 if (!init()) {
michael@0 182 return false;
michael@0 183 }
michael@0 184
michael@0 185 void* region = nullptr;
michael@0 186 if (dirtyRect) {
michael@0 187 region = malloc(ANDROID_REGION_SIZE);
michael@0 188 gSurfaceFunctions.regionConstructor(region);
michael@0 189
michael@0 190 ARect rect;
michael@0 191 rect.left = dirtyRect->left;
michael@0 192 rect.top = dirtyRect->top;
michael@0 193 rect.right = dirtyRect->right;
michael@0 194 rect.bottom = dirtyRect->bottom;
michael@0 195
michael@0 196 gSurfaceFunctions.setRegion(region, rect);
michael@0 197 }
michael@0 198
michael@0 199 SurfaceInfo info;
michael@0 200 int err = gSurfaceFunctions.lock(surface, &info, region);
michael@0 201 if (err < 0) {
michael@0 202 LOG("Failed to lock surface");
michael@0 203 return false;
michael@0 204 }
michael@0 205
michael@0 206 // the surface may have expanded the dirty region so we must to pass that
michael@0 207 // information back to the plugin.
michael@0 208 if (dirtyRect) {
michael@0 209 ARect* dirtyBounds = (ARect*)region; // The bounds are the first member, so this should work!
michael@0 210
michael@0 211 dirtyRect->left = dirtyBounds->left;
michael@0 212 dirtyRect->right = dirtyBounds->right;
michael@0 213 dirtyRect->top = dirtyBounds->top;
michael@0 214 dirtyRect->bottom = dirtyBounds->bottom;
michael@0 215 }
michael@0 216
michael@0 217 if (region)
michael@0 218 free(region);
michael@0 219
michael@0 220 int bpr = info.s * bytesPerPixel(info.format);
michael@0 221
michael@0 222 bitmap->format = convertPixelFormat(info.format);
michael@0 223 bitmap->width = info.w;
michael@0 224 bitmap->height = info.h;
michael@0 225 bitmap->rowBytes = bpr;
michael@0 226
michael@0 227 if (info.w > 0 && info.h > 0) {
michael@0 228 bitmap->baseAddr = info.bits;
michael@0 229 } else {
michael@0 230 bitmap->baseAddr = nullptr;
michael@0 231 return false;
michael@0 232 }
michael@0 233
michael@0 234 return true;
michael@0 235 }
michael@0 236
michael@0 237 static void anp_surface_unlock(JNIEnv* env, jobject surfaceView) {
michael@0 238 if (!surfaceView) {
michael@0 239 return;
michael@0 240 }
michael@0 241
michael@0 242 if (!init()) {
michael@0 243 return;
michael@0 244 }
michael@0 245
michael@0 246 void* surface = getSurface(env, surfaceView);
michael@0 247
michael@0 248 if (!surface) {
michael@0 249 return;
michael@0 250 }
michael@0 251
michael@0 252 gSurfaceFunctions.unlockAndPost(surface);
michael@0 253 }
michael@0 254
michael@0 255 ///////////////////////////////////////////////////////////////////////////////
michael@0 256
michael@0 257 void InitSurfaceInterface(ANPSurfaceInterfaceV0* i) {
michael@0 258 ASSIGN(i, lock);
michael@0 259 ASSIGN(i, unlock);
michael@0 260
michael@0 261 // setup the java glue struct
michael@0 262 gSurfaceJavaGlue.initialized = false;
michael@0 263
michael@0 264 // setup the function struct
michael@0 265 gSurfaceFunctions.initialized = false;
michael@0 266 }

mercurial