• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
39 using namespace android;
40 
41 // used to cache JNI method and field IDs for Surface Objects
42 static struct ANPSurfaceInterfaceJavaGlue {
43     bool        initialized;
44     jmethodID   getSurfaceHolder;
45     jmethodID   getSurface;
46     jfieldID    surfacePointer;
47 } gSurfaceJavaGlue;
48 
getSurface(JNIEnv * env,jobject view)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         jclass surfaceClass = env->FindClass("android/view/Surface");
65         gSurfaceJavaGlue.surfacePointer = env->GetFieldID(surfaceClass,
66                 ANDROID_VIEW_SURFACE_JNI_ID, "I");
67 
68         env->DeleteLocalRef(surfaceClass);
69         env->DeleteLocalRef(surfaceViewClass);
70         env->DeleteLocalRef(surfaceHolderClass);
71 
72         gSurfaceJavaGlue.initialized = true;
73     }
74 
75     jobject holder = env->CallObjectMethod(view, gSurfaceJavaGlue.getSurfaceHolder);
76     jobject surface = env->CallObjectMethod(holder, gSurfaceJavaGlue.getSurface);
77     jint surfacePointer = env->GetIntField(surface, gSurfaceJavaGlue.surfacePointer);
78 
79     env->DeleteLocalRef(holder);
80     env->DeleteLocalRef(surface);
81 
82     return sp<android::Surface>((android::Surface*) surfacePointer);
83 }
84 
convertPixelFormat(PixelFormat format)85 static inline ANPBitmapFormat convertPixelFormat(PixelFormat format) {
86     switch (format) {
87         case PIXEL_FORMAT_RGBA_8888:    return kRGBA_8888_ANPBitmapFormat;
88         case PIXEL_FORMAT_RGB_565:      return kRGB_565_ANPBitmapFormat;
89         default:                        return kUnknown_ANPBitmapFormat;
90     }
91 }
92 
anp_lock(JNIEnv * env,jobject surfaceView,ANPBitmap * bitmap,ANPRectI * dirtyRect)93 static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRectI* dirtyRect) {
94     if (!bitmap || !surfaceView) {
95         return false;
96     }
97 
98     sp<android::Surface> surface = getSurface(env, surfaceView);
99 
100     if (!bitmap || !android::Surface::isValid(surface)) {
101             return false;
102     }
103 
104     Region dirtyRegion;
105     if (dirtyRect) {
106         Rect rect(dirtyRect->left, dirtyRect->top, dirtyRect->right, dirtyRect->bottom);
107         if (!rect.isEmpty()) {
108             dirtyRegion.set(rect);
109         }
110     } else {
111         dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
112     }
113 
114     android::Surface::SurfaceInfo info;
115     status_t err = surface->lock(&info, &dirtyRegion);
116     if (err < 0) {
117         return false;
118     }
119 
120     // the surface may have expanded the dirty region so we must to pass that
121     // information back to the plugin.
122     if (dirtyRect) {
123         Rect dirtyBounds = dirtyRegion.getBounds();
124         dirtyRect->left = dirtyBounds.left;
125         dirtyRect->right = dirtyBounds.right;
126         dirtyRect->top = dirtyBounds.top;
127         dirtyRect->bottom = dirtyBounds.bottom;
128     }
129 
130     ssize_t bpr = info.s * bytesPerPixel(info.format);
131 
132     bitmap->format = convertPixelFormat(info.format);
133     bitmap->width = info.w;
134     bitmap->height = info.h;
135     bitmap->rowBytes = bpr;
136 
137     if (info.w > 0 && info.h > 0) {
138         bitmap->baseAddr = info.bits;
139     } else {
140         bitmap->baseAddr = NULL;
141         return false;
142     }
143 
144     return true;
145 }
146 
anp_unlock(JNIEnv * env,jobject surfaceView)147 static void anp_unlock(JNIEnv* env, jobject surfaceView) {
148     if (!surfaceView) {
149         return;
150     }
151 
152     sp<android::Surface> surface = getSurface(env, surfaceView);
153 
154     if (!android::Surface::isValid(surface)) {
155         return;
156     }
157 
158     surface->unlockAndPost();
159 }
160 
161 ///////////////////////////////////////////////////////////////////////////////
162 
163 #define ASSIGN(obj, name)   (obj)->name = anp_##name
164 
ANPSurfaceInterfaceV0_Init(ANPInterface * value)165 void ANPSurfaceInterfaceV0_Init(ANPInterface* value) {
166     ANPSurfaceInterfaceV0* i = reinterpret_cast<ANPSurfaceInterfaceV0*>(value);
167 
168     ASSIGN(i, lock);
169     ASSIGN(i, unlock);
170 
171     // setup the java glue struct
172     gSurfaceJavaGlue.initialized = false;
173 }
174