• 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 #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 
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         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 
convertPixelFormat(PixelFormat format)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 
anp_lock(JNIEnv * env,jobject surfaceView,ANPBitmap * bitmap,ANPRectI * dirtyRect)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 
anp_unlock(JNIEnv * env,jobject surfaceView)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 
ANPSurfaceInterfaceV0_Init(ANPInterface * value)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