blob: 70c2f7b41251070f562476e88168fbe90ea38ebe [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mathias Agopianfae5cb22010-06-04 18:26:32 -070017#define LOG_TAG "Surface"
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019#include <stdio.h>
20
21#include "android_util_Binder.h"
Dianne Hackborna1111872010-11-23 20:55:11 -080022#include "android/graphics/GraphicsJNI.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
Dianne Hackborna1111872010-11-23 20:55:11 -080024#include <binder/IMemory.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080025#include <surfaceflinger/SurfaceComposerClient.h>
Mathias Agopian8b138322010-04-12 16:22:15 -070026#include <surfaceflinger/Surface.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027#include <ui/Region.h>
28#include <ui/Rect.h>
29
Mathias Agopian8b73ae42010-06-10 17:02:51 -070030#include <EGL/egl.h>
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032#include <SkCanvas.h>
33#include <SkBitmap.h>
Mathias Agopian6158b1b2009-05-11 00:03:41 -070034#include <SkRegion.h>
Dianne Hackborn1f5b1952010-11-29 14:41:46 -080035#include <SkPixelRef.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
37#include "jni.h"
Elliott Hughes8451b252011-04-07 19:17:57 -070038#include "JNIHelp.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039#include <android_runtime/AndroidRuntime.h>
Dianne Hackborn289b9b62010-07-09 11:44:11 -070040#include <android_runtime/android_view_Surface.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041#include <utils/misc.h>
42
43
44// ----------------------------------------------------------------------------
45
46namespace android {
47
Mathias Agopianaf1e11b2010-03-23 15:31:21 -070048enum {
49 // should match Parcelable.java
50 PARCELABLE_WRITE_RETURN_VALUE = 0x0001
51};
52
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053// ----------------------------------------------------------------------------
54
55static const char* const OutOfResourcesException =
56 "android/view/Surface$OutOfResourcesException";
57
tedbo05031612011-06-06 16:02:47 -070058const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
59const char* const kSurfaceClassPathName = "android/view/Surface";
60
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061struct sso_t {
62 jfieldID client;
63};
64static sso_t sso;
65
66struct so_t {
Mathias Agopian17f638b2009-04-16 20:04:08 -070067 jfieldID surfaceControl;
Romain Guy2a83f002011-01-18 18:28:21 -080068 jfieldID surfaceGenerationId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 jfieldID surface;
70 jfieldID saveCount;
71 jfieldID canvas;
72};
73static so_t so;
74
75struct ro_t {
76 jfieldID l;
77 jfieldID t;
78 jfieldID r;
79 jfieldID b;
80};
81static ro_t ro;
82
83struct po_t {
84 jfieldID x;
85 jfieldID y;
86};
87static po_t po;
88
89struct co_t {
90 jfieldID surfaceFormat;
91};
92static co_t co;
93
94struct no_t {
95 jfieldID native_canvas;
96 jfieldID native_region;
97 jfieldID native_parcel;
98};
99static no_t no;
100
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102// ----------------------------------------------------------------------------
103// ----------------------------------------------------------------------------
104// ----------------------------------------------------------------------------
105
106static void SurfaceSession_init(JNIEnv* env, jobject clazz)
107{
108 sp<SurfaceComposerClient> client = new SurfaceComposerClient;
109 client->incStrong(clazz);
110 env->SetIntField(clazz, sso.client, (int)client.get());
111}
112
113static void SurfaceSession_destroy(JNIEnv* env, jobject clazz)
114{
115 SurfaceComposerClient* client =
116 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
117 if (client != 0) {
118 client->decStrong(clazz);
119 env->SetIntField(clazz, sso.client, 0);
120 }
121}
122
123static void SurfaceSession_kill(JNIEnv* env, jobject clazz)
124{
125 SurfaceComposerClient* client =
126 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
127 if (client != 0) {
128 client->dispose();
129 client->decStrong(clazz);
130 env->SetIntField(clazz, sso.client, 0);
131 }
132}
133
134// ----------------------------------------------------------------------------
135
Mathias Agopian17f638b2009-04-16 20:04:08 -0700136static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
137{
Elliott Hughes8451b252011-04-07 19:17:57 -0700138 SurfaceControl* const p =
Mathias Agopian17f638b2009-04-16 20:04:08 -0700139 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
140 return sp<SurfaceControl>(p);
141}
142
Elliott Hughes8451b252011-04-07 19:17:57 -0700143static void setSurfaceControl(JNIEnv* env, jobject clazz,
Mathias Agopian17f638b2009-04-16 20:04:08 -0700144 const sp<SurfaceControl>& surface)
145{
Elliott Hughes8451b252011-04-07 19:17:57 -0700146 SurfaceControl* const p =
Mathias Agopian17f638b2009-04-16 20:04:08 -0700147 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
148 if (surface.get()) {
149 surface->incStrong(clazz);
150 }
151 if (p) {
152 p->decStrong(clazz);
153 }
154 env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
155}
156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
158{
Mathias Agopian69d62092009-04-16 20:30:22 -0700159 sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
160 if (result == 0) {
161 /*
162 * if this method is called from the WindowManager's process, it means
163 * the client is is not remote, and therefore is allowed to have
Elliott Hughes8451b252011-04-07 19:17:57 -0700164 * a Surface (data), so we create it here.
Mathias Agopian69d62092009-04-16 20:30:22 -0700165 * If we don't have a SurfaceControl, it means we're in a different
166 * process.
167 */
Elliott Hughes8451b252011-04-07 19:17:57 -0700168
169 SurfaceControl* const control =
Mathias Agopian69d62092009-04-16 20:30:22 -0700170 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
171 if (control) {
172 result = control->getSurface();
173 if (result != 0) {
174 result->incStrong(clazz);
175 env->SetIntField(clazz, so.surface, (int)result.get());
176 }
177 }
178 }
179 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180}
181
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700182sp<ANativeWindow> android_Surface_getNativeWindow(
Mathias Agopian8b73ae42010-06-10 17:02:51 -0700183 JNIEnv* env, jobject clazz) {
Mathias Agopian32a55cf62011-02-25 16:11:44 -0800184 return getSurface(env, clazz);
Mathias Agopian8b73ae42010-06-10 17:02:51 -0700185}
186
tedbo05031612011-06-06 16:02:47 -0700187bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
188 jclass surfaceClass = env->FindClass(kSurfaceClassPathName);
189 return env->IsInstanceOf(obj, surfaceClass);
190}
191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
193{
194 Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
195 if (surface.get()) {
196 surface->incStrong(clazz);
197 }
198 if (p) {
199 p->decStrong(clazz);
200 }
201 env->SetIntField(clazz, so.surface, (int)surface.get());
Romain Guy2a83f002011-01-18 18:28:21 -0800202 // This test is conservative and it would be better to compare the ISurfaces
203 if (p && p != surface.get()) {
204 jint generationId = env->GetIntField(clazz, so.surfaceGenerationId);
205 generationId++;
206 env->SetIntField(clazz, so.surfaceGenerationId, generationId);
207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208}
209
210// ----------------------------------------------------------------------------
211
212static void Surface_init(
Elliott Hughes8451b252011-04-07 19:17:57 -0700213 JNIEnv* env, jobject clazz,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800214 jobject session,
Mathias Agopian9638e5c2011-04-20 14:19:32 -0700215 jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216{
217 if (session == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700218 doThrowNPE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 return;
220 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 SurfaceComposerClient* client =
223 (SurfaceComposerClient*)env->GetIntField(session, sso.client);
224
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800225 sp<SurfaceControl> surface;
226 if (jname == NULL) {
Mathias Agopian9638e5c2011-04-20 14:19:32 -0700227 surface = client->createSurface(dpy, w, h, format, flags);
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800228 } else {
229 const jchar* str = env->GetStringCritical(jname, 0);
230 const String8 name(str, env->GetStringLength(jname));
231 env->ReleaseStringCritical(jname, str);
Mathias Agopian9638e5c2011-04-20 14:19:32 -0700232 surface = client->createSurface(name, dpy, w, h, format, flags);
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800233 }
234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 if (surface == 0) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700236 jniThrowException(env, OutOfResourcesException, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 return;
238 }
Mathias Agopian17f638b2009-04-16 20:04:08 -0700239 setSurfaceControl(env, clazz, surface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240}
241
242static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
243{
244 Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
245 if (parcel == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700246 doThrowNPE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 return;
248 }
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700249
Jamie Gennis5ee65f02010-07-15 17:29:15 -0700250 sp<Surface> sur(Surface::readFromParcel(*parcel));
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700251 setSurface(env, clazz, sur);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252}
253
Marco Nelissen8138cb42010-04-26 16:05:48 -0700254static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
255{
256 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
257 if (control != 0) return (jint) control->getIdentity();
258 const sp<Surface>& surface(getSurface(env, clazz));
259 if (surface != 0) return (jint) surface->getIdentity();
260 return -1;
261}
262
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700263static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700265 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
266 if (SurfaceControl::isValid(surface)) {
Mathias Agopian402c3462009-04-14 18:21:47 -0700267 surface->clear();
268 }
Mathias Agopian17f638b2009-04-16 20:04:08 -0700269 setSurfaceControl(env, clazz, 0);
Mathias Agopian402c3462009-04-14 18:21:47 -0700270 setSurface(env, clazz, 0);
271}
272
273static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
274{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700275 setSurfaceControl(env, clazz, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 setSurface(env, clazz, 0);
277}
278
279static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
280{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700281 const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
282 if (surfaceControl != 0) {
283 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
284 }
285 const sp<Surface>& surface(getSurface(env, clazz));
Mathias Agopian402c3462009-04-14 18:21:47 -0700286 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287}
288
289static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
290{
Mathias Agopianf1e5b0d2009-08-07 20:55:14 -0700291 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 we can map to SkBitmap::kARGB_8888_Config, and optionally call
293 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
294 */
Marco Nelissen8138cb42010-04-26 16:05:48 -0700295 switch (format) {
296 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
298 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config;
Marco Nelissen8138cb42010-04-26 16:05:48 -0700299 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
300 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config;
301 default: return SkBitmap::kNo_Config;
302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303}
304
305static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
306{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700307 const sp<Surface>& surface(getSurface(env, clazz));
Romain Guyfea12b82011-01-27 15:36:40 -0800308 if (!Surface::isValid(surface)) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700309 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 return 0;
Romain Guyfea12b82011-01-27 15:36:40 -0800311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
313 // get dirty region
314 Region dirtyRegion;
315 if (dirtyRect) {
316 Rect dirty;
317 dirty.left = env->GetIntField(dirtyRect, ro.l);
318 dirty.top = env->GetIntField(dirtyRect, ro.t);
319 dirty.right = env->GetIntField(dirtyRect, ro.r);
320 dirty.bottom= env->GetIntField(dirtyRect, ro.b);
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700321 if (!dirty.isEmpty()) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700322 dirtyRegion.set(dirty);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 }
324 } else {
325 dirtyRegion.set(Rect(0x3FFF,0x3FFF));
326 }
327
328 Surface::SurfaceInfo info;
329 status_t err = surface->lock(&info, &dirtyRegion);
330 if (err < 0) {
331 const char* const exception = (err == NO_MEMORY) ?
332 OutOfResourcesException :
333 "java/lang/IllegalArgumentException";
Elliott Hughes8451b252011-04-07 19:17:57 -0700334 jniThrowException(env, exception, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 return 0;
336 }
337
338 // Associate a SkCanvas object to this surface
339 jobject canvas = env->GetObjectField(clazz, so.canvas);
340 env->SetIntField(canvas, co.surfaceFormat, info.format);
341
342 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
343 SkBitmap bitmap;
Mathias Agopian1473f462009-04-10 14:24:30 -0700344 ssize_t bpr = info.s * bytesPerPixel(info.format);
345 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
Mathias Agopianf1e5b0d2009-08-07 20:55:14 -0700346 if (info.format == PIXEL_FORMAT_RGBX_8888) {
347 bitmap.setIsOpaque(true);
348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 if (info.w > 0 && info.h > 0) {
350 bitmap.setPixels(info.bits);
351 } else {
352 // be safe with an empty bitmap.
353 bitmap.setPixels(NULL);
354 }
355 nativeCanvas->setBitmapDevice(bitmap);
Elliott Hughes8451b252011-04-07 19:17:57 -0700356
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700357 SkRegion clipReg;
358 if (dirtyRegion.isRect()) { // very common case
Mathias Agopiana8a0aa82010-04-21 15:24:11 -0700359 const Rect b(dirtyRegion.getBounds());
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700360 clipReg.setRect(b.left, b.top, b.right, b.bottom);
361 } else {
362 size_t count;
363 Rect const* r = dirtyRegion.getArray(&count);
364 while (count) {
365 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
366 r++, count--;
367 }
368 }
369
370 nativeCanvas->clipRegion(clipReg);
Elliott Hughes8451b252011-04-07 19:17:57 -0700371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 int saveCount = nativeCanvas->save();
373 env->SetIntField(clazz, so.saveCount, saveCount);
374
375 if (dirtyRect) {
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700376 const Rect& bounds(dirtyRegion.getBounds());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 env->SetIntField(dirtyRect, ro.l, bounds.left);
378 env->SetIntField(dirtyRect, ro.t, bounds.top);
379 env->SetIntField(dirtyRect, ro.r, bounds.right);
380 env->SetIntField(dirtyRect, ro.b, bounds.bottom);
381 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700382
Marco Nelissen8138cb42010-04-26 16:05:48 -0700383 return canvas;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384}
385
386static void Surface_unlockCanvasAndPost(
387 JNIEnv* env, jobject clazz, jobject argCanvas)
388{
389 jobject canvas = env->GetObjectField(clazz, so.canvas);
Carl Shapiro375aa0b2011-03-03 17:00:38 -0800390 if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700391 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 return;
393 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700394
Mathias Agopian17f638b2009-04-16 20:04:08 -0700395 const sp<Surface>& surface(getSurface(env, clazz));
Mathias Agopian402c3462009-04-14 18:21:47 -0700396 if (!Surface::isValid(surface))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 return;
398
399 // detach the canvas from the surface
400 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
401 int saveCount = env->GetIntField(clazz, so.saveCount);
402 nativeCanvas->restoreToCount(saveCount);
403 nativeCanvas->setBitmapDevice(SkBitmap());
404 env->SetIntField(clazz, so.saveCount, 0);
405
406 // unlock surface
407 status_t err = surface->unlockAndPost();
408 if (err < 0) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700409 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 }
411}
412
413static void Surface_unlockCanvas(
414 JNIEnv* env, jobject clazz, jobject argCanvas)
415{
Mathias Agopian1473f462009-04-10 14:24:30 -0700416 // XXX: this API has been removed
Elliott Hughes8451b252011-04-07 19:17:57 -0700417 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418}
419
420static void Surface_openTransaction(
421 JNIEnv* env, jobject clazz)
422{
423 SurfaceComposerClient::openGlobalTransaction();
424}
425
426static void Surface_closeTransaction(
427 JNIEnv* env, jobject clazz)
428{
429 SurfaceComposerClient::closeGlobalTransaction();
430}
431
432static void Surface_setOrientation(
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700433 JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434{
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700435 int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 if (err < 0) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700437 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 }
439}
440
441static void Surface_freezeDisplay(
442 JNIEnv* env, jobject clazz, jint display)
443{
444 int err = SurfaceComposerClient::freezeDisplay(display, 0);
445 if (err < 0) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700446 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 }
448}
449
450static void Surface_unfreezeDisplay(
451 JNIEnv* env, jobject clazz, jint display)
452{
453 int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
454 if (err < 0) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700455 doThrowIAE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 }
457}
458
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800459class ScreenshotPixelRef : public SkPixelRef {
Dianne Hackborna1111872010-11-23 20:55:11 -0800460public:
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800461 ScreenshotPixelRef(SkColorTable* ctable) {
462 fCTable = ctable;
Derek Sollenberger6062c592011-02-22 13:55:04 -0500463 SkSafeRef(ctable);
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800464 setImmutable();
465 }
466 virtual ~ScreenshotPixelRef() {
467 SkSafeUnref(fCTable);
Dianne Hackborna1111872010-11-23 20:55:11 -0800468 }
469
Dianne Hackbornd2835932010-12-13 16:28:46 -0800470 status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) {
Dianne Hackborna1111872010-11-23 20:55:11 -0800471 status_t res = (width > 0 && height > 0)
Dianne Hackbornd2835932010-12-13 16:28:46 -0800472 ? (allLayers
473 ? mScreenshot.update(width, height)
474 : mScreenshot.update(width, height, minLayer, maxLayer))
Dianne Hackborna1111872010-11-23 20:55:11 -0800475 : mScreenshot.update();
476 if (res != NO_ERROR) {
477 return res;
478 }
479
Dianne Hackborna1111872010-11-23 20:55:11 -0800480 return NO_ERROR;
481 }
482
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800483 uint32_t getWidth() const {
484 return mScreenshot.getWidth();
485 }
486
487 uint32_t getHeight() const {
488 return mScreenshot.getHeight();
489 }
490
491 uint32_t getStride() const {
492 return mScreenshot.getStride();
493 }
494
495 uint32_t getFormat() const {
496 return mScreenshot.getFormat();
497 }
498
499protected:
500 // overrides from SkPixelRef
501 virtual void* onLockPixels(SkColorTable** ct) {
502 *ct = fCTable;
503 return (void*)mScreenshot.getPixels();
504 }
505
506 virtual void onUnlockPixels() {
507 }
508
Dianne Hackborna1111872010-11-23 20:55:11 -0800509private:
510 ScreenshotClient mScreenshot;
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800511 SkColorTable* fCTable;
512
513 typedef SkPixelRef INHERITED;
Dianne Hackborna1111872010-11-23 20:55:11 -0800514};
515
Dianne Hackbornd2835932010-12-13 16:28:46 -0800516static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height,
517 jint minLayer, jint maxLayer, bool allLayers)
Dianne Hackborna1111872010-11-23 20:55:11 -0800518{
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800519 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
Dianne Hackbornd2835932010-12-13 16:28:46 -0800520 if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) {
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800521 delete pixels;
Dianne Hackborna1111872010-11-23 20:55:11 -0800522 return 0;
523 }
524
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800525 uint32_t w = pixels->getWidth();
526 uint32_t h = pixels->getHeight();
527 uint32_t s = pixels->getStride();
528 uint32_t f = pixels->getFormat();
529 ssize_t bpr = s * android::bytesPerPixel(f);
530
531 SkBitmap* bitmap = new SkBitmap();
532 bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
533 if (f == PIXEL_FORMAT_RGBX_8888) {
534 bitmap->setIsOpaque(true);
535 }
536
537 if (w > 0 && h > 0) {
538 bitmap->setPixelRef(pixels)->unref();
539 bitmap->lockPixels();
540 } else {
541 // be safe with an empty bitmap.
542 delete pixels;
543 bitmap->setPixels(NULL);
544 }
545
Dianne Hackborna1111872010-11-23 20:55:11 -0800546 return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
547}
548
Dianne Hackbornd2835932010-12-13 16:28:46 -0800549static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
550{
551 return doScreenshot(env, clazz, width, height, 0, 0, true);
552}
553
554static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
555 jint minLayer, jint maxLayer, bool allLayers)
556{
557 return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
558}
559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560static void Surface_setLayer(
561 JNIEnv* env, jobject clazz, jint zorder)
562{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700563 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
564 if (surface == 0) return;
565 status_t err = surface->setLayer(zorder);
Elliott Hughes8451b252011-04-07 19:17:57 -0700566 if (err<0 && err!=NO_INIT) {
567 doThrowIAE(env);
568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569}
570
571static void Surface_setPosition(
572 JNIEnv* env, jobject clazz, jint x, jint y)
573{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700574 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
575 if (surface == 0) return;
576 status_t err = surface->setPosition(x, y);
Elliott Hughes8451b252011-04-07 19:17:57 -0700577 if (err<0 && err!=NO_INIT) {
578 doThrowIAE(env);
579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580}
581
582static void Surface_setSize(
583 JNIEnv* env, jobject clazz, jint w, jint h)
584{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700585 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
586 if (surface == 0) return;
587 status_t err = surface->setSize(w, h);
Elliott Hughes8451b252011-04-07 19:17:57 -0700588 if (err<0 && err!=NO_INIT) {
589 doThrowIAE(env);
590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591}
592
593static void Surface_hide(
594 JNIEnv* env, jobject clazz)
595{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700596 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
597 if (surface == 0) return;
598 status_t err = surface->hide();
Elliott Hughes8451b252011-04-07 19:17:57 -0700599 if (err<0 && err!=NO_INIT) {
600 doThrowIAE(env);
601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602}
603
604static void Surface_show(
605 JNIEnv* env, jobject clazz)
606{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700607 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
608 if (surface == 0) return;
609 status_t err = surface->show();
Elliott Hughes8451b252011-04-07 19:17:57 -0700610 if (err<0 && err!=NO_INIT) {
611 doThrowIAE(env);
612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613}
614
615static void Surface_freeze(
616 JNIEnv* env, jobject clazz)
617{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700618 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
619 if (surface == 0) return;
620 status_t err = surface->freeze();
Elliott Hughes8451b252011-04-07 19:17:57 -0700621 if (err<0 && err!=NO_INIT) {
622 doThrowIAE(env);
623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624}
625
626static void Surface_unfreeze(
627 JNIEnv* env, jobject clazz)
628{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700629 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
630 if (surface == 0) return;
631 status_t err = surface->unfreeze();
Elliott Hughes8451b252011-04-07 19:17:57 -0700632 if (err<0 && err!=NO_INIT) {
633 doThrowIAE(env);
634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635}
636
637static void Surface_setFlags(
638 JNIEnv* env, jobject clazz, jint flags, jint mask)
639{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700640 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
641 if (surface == 0) return;
642 status_t err = surface->setFlags(flags, mask);
Elliott Hughes8451b252011-04-07 19:17:57 -0700643 if (err<0 && err!=NO_INIT) {
644 doThrowIAE(env);
645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646}
647
648static void Surface_setTransparentRegion(
649 JNIEnv* env, jobject clazz, jobject argRegion)
650{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700651 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
652 if (surface == 0) return;
653 SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
Elliott Hughes8451b252011-04-07 19:17:57 -0700654
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700655 const SkIRect& b(nativeRegion->getBounds());
656 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
657 if (nativeRegion->isComplex()) {
658 SkRegion::Iterator it(*nativeRegion);
659 while (!it.done()) {
660 const SkIRect& r(it.rect());
661 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
662 it.next();
663 }
664 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700665
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700666 status_t err = surface->setTransparentRegionHint(reg);
Elliott Hughes8451b252011-04-07 19:17:57 -0700667 if (err<0 && err!=NO_INIT) {
668 doThrowIAE(env);
669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670}
671
672static void Surface_setAlpha(
673 JNIEnv* env, jobject clazz, jfloat alpha)
674{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700675 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
676 if (surface == 0) return;
677 status_t err = surface->setAlpha(alpha);
Elliott Hughes8451b252011-04-07 19:17:57 -0700678 if (err<0 && err!=NO_INIT) {
679 doThrowIAE(env);
680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681}
682
683static void Surface_setMatrix(
684 JNIEnv* env, jobject clazz,
685 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
686{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700687 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
688 if (surface == 0) return;
689 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
Elliott Hughes8451b252011-04-07 19:17:57 -0700690 if (err<0 && err!=NO_INIT) {
691 doThrowIAE(env);
692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693}
694
695static void Surface_setFreezeTint(
696 JNIEnv* env, jobject clazz,
697 jint tint)
698{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700699 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
700 if (surface == 0) return;
701 status_t err = surface->setFreezeTint(tint);
Elliott Hughes8451b252011-04-07 19:17:57 -0700702 if (err<0 && err!=NO_INIT) {
703 doThrowIAE(env);
704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705}
706
Mathias Agopian17f638b2009-04-16 20:04:08 -0700707// ----------------------------------------------------------------------------
708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709static void Surface_copyFrom(
710 JNIEnv* env, jobject clazz, jobject other)
711{
712 if (clazz == other)
713 return;
714
715 if (other == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700716 doThrowNPE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 return;
718 }
719
Mathias Agopian17f638b2009-04-16 20:04:08 -0700720 /*
721 * This is used by the WindowManagerService just after constructing
722 * a Surface and is necessary for returning the Surface reference to
723 * the caller. At this point, we should only have a SurfaceControl.
Mathias Agopian17f638b2009-04-16 20:04:08 -0700724 */
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700725
Mathias Agopian17f638b2009-04-16 20:04:08 -0700726 const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
727 const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
728 if (!SurfaceControl::isSameSurface(surface, rhs)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 // we reassign the surface only if it's a different one
730 // otherwise we would loose our client-side state.
Mathias Agopian17f638b2009-04-16 20:04:08 -0700731 setSurfaceControl(env, clazz, rhs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
733}
734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735static void Surface_readFromParcel(
736 JNIEnv* env, jobject clazz, jobject argParcel)
737{
738 Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
739 if (parcel == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700740 doThrowNPE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 return;
742 }
743
Jamie Gennis5ee65f02010-07-15 17:29:15 -0700744 sp<Surface> sur(Surface::readFromParcel(*parcel));
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700745 setSurface(env, clazz, sur);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746}
747
748static void Surface_writeToParcel(
749 JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
750{
751 Parcel* parcel = (Parcel*)env->GetIntField(
752 argParcel, no.native_parcel);
753
754 if (parcel == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700755 doThrowNPE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 return;
757 }
758
Mathias Agopian17f638b2009-04-16 20:04:08 -0700759 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
760 SurfaceControl::writeSurfaceToParcel(control, parcel);
Mathias Agopianaf1e11b2010-03-23 15:31:21 -0700761 if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
762 setSurfaceControl(env, clazz, 0);
763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764}
765
766// ----------------------------------------------------------------------------
767// ----------------------------------------------------------------------------
768// ----------------------------------------------------------------------------
769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770static void nativeClassInit(JNIEnv* env, jclass clazz);
771
772static JNINativeMethod gSurfaceSessionMethods[] = {
Marco Nelissen8138cb42010-04-26 16:05:48 -0700773 {"init", "()V", (void*)SurfaceSession_init },
774 {"destroy", "()V", (void*)SurfaceSession_destroy },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 {"kill", "()V", (void*)SurfaceSession_kill },
776};
777
778static JNINativeMethod gSurfaceMethods[] = {
779 {"nativeClassInit", "()V", (void*)nativeClassInit },
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800780 {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel },
Marco Nelissen8138cb42010-04-26 16:05:48 -0700782 {"getIdentity", "()I", (void*)Surface_getIdentity },
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700783 {"destroy", "()V", (void*)Surface_destroy },
Mathias Agopian402c3462009-04-14 18:21:47 -0700784 {"release", "()V", (void*)Surface_release },
Marco Nelissen8138cb42010-04-26 16:05:48 -0700785 {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom },
786 {"isValid", "()Z", (void*)Surface_isValid },
787 {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas },
788 {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
789 {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
790 {"openTransaction", "()V", (void*)Surface_openTransaction },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 {"closeTransaction", "()V", (void*)Surface_closeTransaction },
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700792 {"setOrientation", "(III)V", (void*)Surface_setOrientation },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay },
794 {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay },
Dianne Hackbornd2835932010-12-13 16:28:46 -0800795 {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
796 {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 {"setLayer", "(I)V", (void*)Surface_setLayer },
Marco Nelissen8138cb42010-04-26 16:05:48 -0700798 {"setPosition", "(II)V",(void*)Surface_setPosition },
799 {"setSize", "(II)V",(void*)Surface_setSize },
800 {"hide", "()V", (void*)Surface_hide },
801 {"show", "()V", (void*)Surface_show },
802 {"freeze", "()V", (void*)Surface_freeze },
803 {"unfreeze", "()V", (void*)Surface_unfreeze },
804 {"setFlags", "(II)V",(void*)Surface_setFlags },
805 {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
806 {"setAlpha", "(F)V", (void*)Surface_setAlpha },
807 {"setMatrix", "(FFFF)V", (void*)Surface_setMatrix },
808 {"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint },
809 {"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
810 {"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811};
812
813void nativeClassInit(JNIEnv* env, jclass clazz)
814{
Mathias Agopian8b138322010-04-12 16:22:15 -0700815 so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
Romain Guy2a83f002011-01-18 18:28:21 -0800816 so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I");
Mathias Agopian17f638b2009-04-16 20:04:08 -0700817 so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
Marco Nelissen8138cb42010-04-26 16:05:48 -0700818 so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
819 so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820
821 jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
Marco Nelissen8138cb42010-04-26 16:05:48 -0700822 sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823
824 jclass canvas = env->FindClass("android/graphics/Canvas");
825 no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
826 co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
827
828 jclass region = env->FindClass("android/graphics/Region");
829 no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
830
831 jclass parcel = env->FindClass("android/os/Parcel");
832 no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
833
834 jclass rect = env->FindClass("android/graphics/Rect");
835 ro.l = env->GetFieldID(rect, "left", "I");
836 ro.t = env->GetFieldID(rect, "top", "I");
837 ro.r = env->GetFieldID(rect, "right", "I");
838 ro.b = env->GetFieldID(rect, "bottom", "I");
839
840 jclass point = env->FindClass("android/graphics/Point");
841 po.x = env->GetFieldID(point, "x", "I");
842 po.y = env->GetFieldID(point, "y", "I");
843}
844
845int register_android_view_Surface(JNIEnv* env)
846{
847 int err;
848 err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
849 gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
850
851 err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
852 gSurfaceMethods, NELEM(gSurfaceMethods));
853 return err;
854}
855
856};