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 <JNIUtility.h> 34 #include <gui/Surface.h> 35 #include <ui/Rect.h> 36 #include <ui/Region.h> 37 #include <utils/RefBase.h> 38 #include <android_runtime/android_view_Surface.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 } gSurfaceJavaGlue; 48 49 static inline sp<android::Surface> getSurface(JNIEnv* env, jobject view) { 50 if (!env || !view) { 51 return NULL; 52 } 53 54 if (!gSurfaceJavaGlue.initialized) { 55 56 jclass surfaceViewClass = env->FindClass("android/view/SurfaceView"); 57 gSurfaceJavaGlue.getSurfaceHolder = env->GetMethodID(surfaceViewClass, "getHolder", 58 "()Landroid/view/SurfaceHolder;"); 59 60 jclass surfaceHolderClass = env->FindClass("android/view/SurfaceHolder"); 61 gSurfaceJavaGlue.getSurface = env->GetMethodID(surfaceHolderClass, "getSurface", 62 "()Landroid/view/Surface;"); 63 64 env->DeleteLocalRef(surfaceViewClass); 65 env->DeleteLocalRef(surfaceHolderClass); 66 67 gSurfaceJavaGlue.initialized = true; 68 } 69 70 jobject holder = env->CallObjectMethod(view, gSurfaceJavaGlue.getSurfaceHolder); 71 jobject surface = env->CallObjectMethod(holder, gSurfaceJavaGlue.getSurface); 72 73 sp<android::Surface> sur = android_view_Surface_getSurface(env, surface); 74 75 env->DeleteLocalRef(holder); 76 env->DeleteLocalRef(surface); 77 78 return sur; 79 } 80 81 static inline ANPBitmapFormat convertPixelFormat(PixelFormat format) { 82 switch (format) { 83 case PIXEL_FORMAT_RGBA_8888: return kRGBA_8888_ANPBitmapFormat; 84 case PIXEL_FORMAT_RGB_565: return kRGB_565_ANPBitmapFormat; 85 default: return kUnknown_ANPBitmapFormat; 86 } 87 } 88 89 static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRectI* dirtyRect) { 90 if (!bitmap || !surfaceView) { 91 return false; 92 } 93 94 sp<android::Surface> surface = getSurface(env, surfaceView); 95 96 if (!bitmap || !android::Surface::isValid(surface)) { 97 return false; 98 } 99 100 Region dirtyRegion; 101 if (dirtyRect) { 102 Rect rect(dirtyRect->left, dirtyRect->top, dirtyRect->right, dirtyRect->bottom); 103 if (!rect.isEmpty()) { 104 dirtyRegion.set(rect); 105 } 106 } else { 107 dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); 108 } 109 110 111 ANativeWindow_Buffer outBuffer; 112 Rect dirtyBounds(dirtyRegion.getBounds()); 113 status_t err = surface->lock(&outBuffer, &dirtyBounds); 114 if (err < 0) { 115 return false; 116 } 117 118 // the surface may have expanded the dirty region so we must to pass that 119 // information back to the plugin. 120 dirtyRegion.set(dirtyBounds); 121 if (dirtyRect) { 122 Rect dirtyBounds = dirtyRegion.getBounds(); 123 dirtyRect->left = dirtyBounds.left; 124 dirtyRect->right = dirtyBounds.right; 125 dirtyRect->top = dirtyBounds.top; 126 dirtyRect->bottom = dirtyBounds.bottom; 127 } 128 129 ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format); 130 131 bitmap->format = convertPixelFormat(outBuffer.format); 132 bitmap->width = outBuffer.width; 133 bitmap->height = outBuffer.height; 134 bitmap->rowBytes = bpr; 135 136 if (outBuffer.width > 0 && outBuffer.height > 0) { 137 bitmap->baseAddr = outBuffer.bits; 138 } else { 139 bitmap->baseAddr = NULL; 140 return false; 141 } 142 143 return true; 144 } 145 146 static void anp_unlock(JNIEnv* env, jobject surfaceView) { 147 if (!surfaceView) { 148 return; 149 } 150 151 sp<android::Surface> surface = getSurface(env, surfaceView); 152 153 if (!android::Surface::isValid(surface)) { 154 return; 155 } 156 157 surface->unlockAndPost(); 158 } 159 160 /////////////////////////////////////////////////////////////////////////////// 161 162 #define ASSIGN(obj, name) (obj)->name = anp_##name 163 164 void ANPSurfaceInterfaceV0_Init(ANPInterface* value) { 165 ANPSurfaceInterfaceV0* i = reinterpret_cast<ANPSurfaceInterfaceV0*>(value); 166 167 ASSIGN(i, lock); 168 ASSIGN(i, unlock); 169 170 // setup the java glue struct 171 gSurfaceJavaGlue.initialized = false; 172 } 173