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 <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