1 /* 2 * Copyright 2009, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 // must include config.h first for webkit to fiddle with new/delete 27 #include "config.h" 28 #include "ANPSurface_npapi.h" 29 30 #include "PluginView.h" 31 #include "PluginWidgetAndroid.h" 32 #include "SkANP.h" 33 #include "android_graphics.h" 34 #include <JNIUtility.h> 35 #include <gui/Surface.h> 36 #include <ui/Rect.h> 37 #include <ui/Region.h> 38 #include <utils/RefBase.h> 39 40 using namespace android; 41 42 // used to cache JNI method and field IDs for Surface Objects 43 static struct ANPSurfaceInterfaceJavaGlue { 44 bool initialized; 45 jmethodID getSurfaceHolder; 46 jmethodID getSurface; 47 jfieldID surfacePointer; 48 } gSurfaceJavaGlue; 49 50 static inline sp<android::Surface> getSurface(JNIEnv* env, jobject view) { 51 if (!env || !view) { 52 return NULL; 53 } 54 55 if (!gSurfaceJavaGlue.initialized) { 56 57 jclass surfaceViewClass = env->FindClass("android/view/SurfaceView"); 58 gSurfaceJavaGlue.getSurfaceHolder = env->GetMethodID(surfaceViewClass, "getHolder", 59 "()Landroid/view/SurfaceHolder;"); 60 61 jclass surfaceHolderClass = env->FindClass("android/view/SurfaceHolder"); 62 gSurfaceJavaGlue.getSurface = env->GetMethodID(surfaceHolderClass, "getSurface", 63 "()Landroid/view/Surface;"); 64 65 jclass surfaceClass = env->FindClass("android/view/Surface"); 66 gSurfaceJavaGlue.surfacePointer = env->GetFieldID(surfaceClass, 67 ANDROID_VIEW_SURFACE_JNI_ID, "I"); 68 69 env->DeleteLocalRef(surfaceClass); 70 env->DeleteLocalRef(surfaceViewClass); 71 env->DeleteLocalRef(surfaceHolderClass); 72 73 gSurfaceJavaGlue.initialized = true; 74 } 75 76 jobject holder = env->CallObjectMethod(view, gSurfaceJavaGlue.getSurfaceHolder); 77 jobject surface = env->CallObjectMethod(holder, gSurfaceJavaGlue.getSurface); 78 jint surfacePointer = env->GetIntField(surface, gSurfaceJavaGlue.surfacePointer); 79 80 env->DeleteLocalRef(holder); 81 env->DeleteLocalRef(surface); 82 83 return sp<android::Surface>((android::Surface*) surfacePointer); 84 } 85 86 static inline ANPBitmapFormat convertPixelFormat(PixelFormat format) { 87 switch (format) { 88 case PIXEL_FORMAT_RGBA_8888: return kRGBA_8888_ANPBitmapFormat; 89 case PIXEL_FORMAT_RGB_565: return kRGB_565_ANPBitmapFormat; 90 default: return kUnknown_ANPBitmapFormat; 91 } 92 } 93 94 static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRectI* dirtyRect) { 95 if (!bitmap || !surfaceView) { 96 return false; 97 } 98 99 sp<android::Surface> surface = getSurface(env, surfaceView); 100 101 if (!bitmap || !android::Surface::isValid(surface)) { 102 return false; 103 } 104 105 Region dirtyRegion; 106 if (dirtyRect) { 107 Rect rect(dirtyRect->left, dirtyRect->top, dirtyRect->right, dirtyRect->bottom); 108 if (!rect.isEmpty()) { 109 dirtyRegion.set(rect); 110 } 111 } else { 112 dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); 113 } 114 115 android::Surface::SurfaceInfo info; 116 status_t err = surface->lock(&info, &dirtyRegion); 117 if (err < 0) { 118 return false; 119 } 120 121 // the surface may have expanded the dirty region so we must to pass that 122 // information back to the plugin. 123 if (dirtyRect) { 124 Rect dirtyBounds = dirtyRegion.getBounds(); 125 dirtyRect->left = dirtyBounds.left; 126 dirtyRect->right = dirtyBounds.right; 127 dirtyRect->top = dirtyBounds.top; 128 dirtyRect->bottom = dirtyBounds.bottom; 129 } 130 131 ssize_t bpr = info.s * bytesPerPixel(info.format); 132 133 bitmap->format = convertPixelFormat(info.format); 134 bitmap->width = info.w; 135 bitmap->height = info.h; 136 bitmap->rowBytes = bpr; 137 138 if (info.w > 0 && info.h > 0) { 139 bitmap->baseAddr = info.bits; 140 } else { 141 bitmap->baseAddr = NULL; 142 return false; 143 } 144 145 return true; 146 } 147 148 static void anp_unlock(JNIEnv* env, jobject surfaceView) { 149 if (!surfaceView) { 150 return; 151 } 152 153 sp<android::Surface> surface = getSurface(env, surfaceView); 154 155 if (!android::Surface::isValid(surface)) { 156 return; 157 } 158 159 surface->unlockAndPost(); 160 } 161 162 /////////////////////////////////////////////////////////////////////////////// 163 164 #define ASSIGN(obj, name) (obj)->name = anp_##name 165 166 void ANPSurfaceInterfaceV0_Init(ANPInterface* value) { 167 ANPSurfaceInterfaceV0* i = reinterpret_cast<ANPSurfaceInterfaceV0*>(value); 168 169 ASSIGN(i, lock); 170 ASSIGN(i, unlock); 171 172 // setup the java glue struct 173 gSurfaceJavaGlue.initialized = false; 174 } 175