Home | History | Annotate | Download | only in plugins
      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