blob: bd2e6694f3f5798082dfac8d492ca81a5aa07f3b [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"
38#include <android_runtime/AndroidRuntime.h>
Dianne Hackborn289b9b62010-07-09 11:44:11 -070039#include <android_runtime/android_view_Surface.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040#include <utils/misc.h>
41
42
43// ----------------------------------------------------------------------------
44
45namespace android {
46
Mathias Agopianaf1e11b2010-03-23 15:31:21 -070047enum {
48 // should match Parcelable.java
49 PARCELABLE_WRITE_RETURN_VALUE = 0x0001
50};
51
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052// ----------------------------------------------------------------------------
53
54static const char* const OutOfResourcesException =
55 "android/view/Surface$OutOfResourcesException";
56
57struct sso_t {
58 jfieldID client;
59};
60static sso_t sso;
61
62struct so_t {
Mathias Agopian17f638b2009-04-16 20:04:08 -070063 jfieldID surfaceControl;
Romain Guy2a83f002011-01-18 18:28:21 -080064 jfieldID surfaceGenerationId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 jfieldID surface;
66 jfieldID saveCount;
67 jfieldID canvas;
68};
69static so_t so;
70
71struct ro_t {
72 jfieldID l;
73 jfieldID t;
74 jfieldID r;
75 jfieldID b;
76};
77static ro_t ro;
78
79struct po_t {
80 jfieldID x;
81 jfieldID y;
82};
83static po_t po;
84
85struct co_t {
86 jfieldID surfaceFormat;
87};
88static co_t co;
89
90struct no_t {
91 jfieldID native_canvas;
92 jfieldID native_region;
93 jfieldID native_parcel;
94};
95static no_t no;
96
97
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098// ----------------------------------------------------------------------------
99// ----------------------------------------------------------------------------
100// ----------------------------------------------------------------------------
101
102static void SurfaceSession_init(JNIEnv* env, jobject clazz)
103{
104 sp<SurfaceComposerClient> client = new SurfaceComposerClient;
105 client->incStrong(clazz);
106 env->SetIntField(clazz, sso.client, (int)client.get());
107}
108
109static void SurfaceSession_destroy(JNIEnv* env, jobject clazz)
110{
111 SurfaceComposerClient* client =
112 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
113 if (client != 0) {
114 client->decStrong(clazz);
115 env->SetIntField(clazz, sso.client, 0);
116 }
117}
118
119static void SurfaceSession_kill(JNIEnv* env, jobject clazz)
120{
121 SurfaceComposerClient* client =
122 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
123 if (client != 0) {
124 client->dispose();
125 client->decStrong(clazz);
126 env->SetIntField(clazz, sso.client, 0);
127 }
128}
129
130// ----------------------------------------------------------------------------
131
Mathias Agopian17f638b2009-04-16 20:04:08 -0700132static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
133{
134 SurfaceControl* const p =
135 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
136 return sp<SurfaceControl>(p);
137}
138
139static void setSurfaceControl(JNIEnv* env, jobject clazz,
140 const sp<SurfaceControl>& surface)
141{
142 SurfaceControl* const p =
143 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
144 if (surface.get()) {
145 surface->incStrong(clazz);
146 }
147 if (p) {
148 p->decStrong(clazz);
149 }
150 env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
151}
152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
154{
Mathias Agopian69d62092009-04-16 20:30:22 -0700155 sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
156 if (result == 0) {
157 /*
158 * if this method is called from the WindowManager's process, it means
159 * the client is is not remote, and therefore is allowed to have
160 * a Surface (data), so we create it here.
161 * If we don't have a SurfaceControl, it means we're in a different
162 * process.
163 */
164
165 SurfaceControl* const control =
166 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
167 if (control) {
168 result = control->getSurface();
169 if (result != 0) {
170 result->incStrong(clazz);
171 env->SetIntField(clazz, so.surface, (int)result.get());
172 }
173 }
174 }
175 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176}
177
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700178sp<ANativeWindow> android_Surface_getNativeWindow(
Mathias Agopian8b73ae42010-06-10 17:02:51 -0700179 JNIEnv* env, jobject clazz) {
Mathias Agopian32a55cf62011-02-25 16:11:44 -0800180 return getSurface(env, clazz);
Mathias Agopian8b73ae42010-06-10 17:02:51 -0700181}
182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
184{
185 Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
186 if (surface.get()) {
187 surface->incStrong(clazz);
188 }
189 if (p) {
190 p->decStrong(clazz);
191 }
192 env->SetIntField(clazz, so.surface, (int)surface.get());
Romain Guy2a83f002011-01-18 18:28:21 -0800193 // This test is conservative and it would be better to compare the ISurfaces
194 if (p && p != surface.get()) {
195 jint generationId = env->GetIntField(clazz, so.surfaceGenerationId);
196 generationId++;
197 env->SetIntField(clazz, so.surfaceGenerationId, generationId);
198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199}
200
201// ----------------------------------------------------------------------------
202
203static void Surface_init(
204 JNIEnv* env, jobject clazz,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800205 jobject session,
206 jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207{
208 if (session == NULL) {
209 doThrow(env, "java/lang/NullPointerException");
210 return;
211 }
212
213 SurfaceComposerClient* client =
214 (SurfaceComposerClient*)env->GetIntField(session, sso.client);
215
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800216 sp<SurfaceControl> surface;
217 if (jname == NULL) {
218 surface = client->createSurface(pid, dpy, w, h, format, flags);
219 } else {
220 const jchar* str = env->GetStringCritical(jname, 0);
221 const String8 name(str, env->GetStringLength(jname));
222 env->ReleaseStringCritical(jname, str);
223 surface = client->createSurface(pid, name, dpy, w, h, format, flags);
224 }
225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 if (surface == 0) {
227 doThrow(env, OutOfResourcesException);
228 return;
229 }
Mathias Agopian17f638b2009-04-16 20:04:08 -0700230 setSurfaceControl(env, clazz, surface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231}
232
233static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
234{
235 Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
236 if (parcel == NULL) {
237 doThrow(env, "java/lang/NullPointerException", NULL);
238 return;
239 }
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700240
Jamie Gennis5ee65f02010-07-15 17:29:15 -0700241 sp<Surface> sur(Surface::readFromParcel(*parcel));
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700242 setSurface(env, clazz, sur);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243}
244
Marco Nelissen8138cb42010-04-26 16:05:48 -0700245static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
246{
247 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
248 if (control != 0) return (jint) control->getIdentity();
249 const sp<Surface>& surface(getSurface(env, clazz));
250 if (surface != 0) return (jint) surface->getIdentity();
251 return -1;
252}
253
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700254static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700256 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
257 if (SurfaceControl::isValid(surface)) {
Mathias Agopian402c3462009-04-14 18:21:47 -0700258 surface->clear();
259 }
Mathias Agopian17f638b2009-04-16 20:04:08 -0700260 setSurfaceControl(env, clazz, 0);
Mathias Agopian402c3462009-04-14 18:21:47 -0700261 setSurface(env, clazz, 0);
262}
263
264static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
265{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700266 setSurfaceControl(env, clazz, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 setSurface(env, clazz, 0);
268}
269
270static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
271{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700272 const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
273 if (surfaceControl != 0) {
274 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
275 }
276 const sp<Surface>& surface(getSurface(env, clazz));
Mathias Agopian402c3462009-04-14 18:21:47 -0700277 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278}
279
280static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
281{
Mathias Agopianf1e5b0d2009-08-07 20:55:14 -0700282 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 we can map to SkBitmap::kARGB_8888_Config, and optionally call
284 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
285 */
Marco Nelissen8138cb42010-04-26 16:05:48 -0700286 switch (format) {
287 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
289 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config;
Marco Nelissen8138cb42010-04-26 16:05:48 -0700290 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
291 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config;
292 default: return SkBitmap::kNo_Config;
293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294}
295
296static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
297{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700298 const sp<Surface>& surface(getSurface(env, clazz));
Romain Guyfea12b82011-01-27 15:36:40 -0800299 if (!Surface::isValid(surface)) {
300 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 return 0;
Romain Guyfea12b82011-01-27 15:36:40 -0800302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303
304 // get dirty region
305 Region dirtyRegion;
306 if (dirtyRect) {
307 Rect dirty;
308 dirty.left = env->GetIntField(dirtyRect, ro.l);
309 dirty.top = env->GetIntField(dirtyRect, ro.t);
310 dirty.right = env->GetIntField(dirtyRect, ro.r);
311 dirty.bottom= env->GetIntField(dirtyRect, ro.b);
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700312 if (!dirty.isEmpty()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 dirtyRegion.set(dirty);
314 }
315 } else {
316 dirtyRegion.set(Rect(0x3FFF,0x3FFF));
317 }
318
319 Surface::SurfaceInfo info;
320 status_t err = surface->lock(&info, &dirtyRegion);
321 if (err < 0) {
322 const char* const exception = (err == NO_MEMORY) ?
323 OutOfResourcesException :
324 "java/lang/IllegalArgumentException";
325 doThrow(env, exception, NULL);
326 return 0;
327 }
328
329 // Associate a SkCanvas object to this surface
330 jobject canvas = env->GetObjectField(clazz, so.canvas);
331 env->SetIntField(canvas, co.surfaceFormat, info.format);
332
333 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
334 SkBitmap bitmap;
Mathias Agopian1473f462009-04-10 14:24:30 -0700335 ssize_t bpr = info.s * bytesPerPixel(info.format);
336 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
Mathias Agopianf1e5b0d2009-08-07 20:55:14 -0700337 if (info.format == PIXEL_FORMAT_RGBX_8888) {
338 bitmap.setIsOpaque(true);
339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 if (info.w > 0 && info.h > 0) {
341 bitmap.setPixels(info.bits);
342 } else {
343 // be safe with an empty bitmap.
344 bitmap.setPixels(NULL);
345 }
346 nativeCanvas->setBitmapDevice(bitmap);
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700347
348 SkRegion clipReg;
349 if (dirtyRegion.isRect()) { // very common case
Mathias Agopiana8a0aa82010-04-21 15:24:11 -0700350 const Rect b(dirtyRegion.getBounds());
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700351 clipReg.setRect(b.left, b.top, b.right, b.bottom);
352 } else {
353 size_t count;
354 Rect const* r = dirtyRegion.getArray(&count);
355 while (count) {
356 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
357 r++, count--;
358 }
359 }
360
361 nativeCanvas->clipRegion(clipReg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362
363 int saveCount = nativeCanvas->save();
364 env->SetIntField(clazz, so.saveCount, saveCount);
365
366 if (dirtyRect) {
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700367 const Rect& bounds(dirtyRegion.getBounds());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 env->SetIntField(dirtyRect, ro.l, bounds.left);
369 env->SetIntField(dirtyRect, ro.t, bounds.top);
370 env->SetIntField(dirtyRect, ro.r, bounds.right);
371 env->SetIntField(dirtyRect, ro.b, bounds.bottom);
372 }
373
Marco Nelissen8138cb42010-04-26 16:05:48 -0700374 return canvas;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375}
376
377static void Surface_unlockCanvasAndPost(
378 JNIEnv* env, jobject clazz, jobject argCanvas)
379{
380 jobject canvas = env->GetObjectField(clazz, so.canvas);
381 if (canvas != argCanvas) {
382 doThrow(env, "java/lang/IllegalArgumentException", NULL);
383 return;
384 }
385
Mathias Agopian17f638b2009-04-16 20:04:08 -0700386 const sp<Surface>& surface(getSurface(env, clazz));
Mathias Agopian402c3462009-04-14 18:21:47 -0700387 if (!Surface::isValid(surface))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 return;
389
390 // detach the canvas from the surface
391 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
392 int saveCount = env->GetIntField(clazz, so.saveCount);
393 nativeCanvas->restoreToCount(saveCount);
394 nativeCanvas->setBitmapDevice(SkBitmap());
395 env->SetIntField(clazz, so.saveCount, 0);
396
397 // unlock surface
398 status_t err = surface->unlockAndPost();
399 if (err < 0) {
400 doThrow(env, "java/lang/IllegalArgumentException", NULL);
401 }
402}
403
404static void Surface_unlockCanvas(
405 JNIEnv* env, jobject clazz, jobject argCanvas)
406{
Mathias Agopian1473f462009-04-10 14:24:30 -0700407 // XXX: this API has been removed
408 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409}
410
411static void Surface_openTransaction(
412 JNIEnv* env, jobject clazz)
413{
414 SurfaceComposerClient::openGlobalTransaction();
415}
416
417static void Surface_closeTransaction(
418 JNIEnv* env, jobject clazz)
419{
420 SurfaceComposerClient::closeGlobalTransaction();
421}
422
423static void Surface_setOrientation(
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700424 JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425{
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700426 int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 if (err < 0) {
428 doThrow(env, "java/lang/IllegalArgumentException", NULL);
429 }
430}
431
432static void Surface_freezeDisplay(
433 JNIEnv* env, jobject clazz, jint display)
434{
435 int err = SurfaceComposerClient::freezeDisplay(display, 0);
436 if (err < 0) {
437 doThrow(env, "java/lang/IllegalArgumentException", NULL);
438 }
439}
440
441static void Surface_unfreezeDisplay(
442 JNIEnv* env, jobject clazz, jint display)
443{
444 int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
445 if (err < 0) {
446 doThrow(env, "java/lang/IllegalArgumentException", NULL);
447 }
448}
449
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800450class ScreenshotPixelRef : public SkPixelRef {
Dianne Hackborna1111872010-11-23 20:55:11 -0800451public:
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800452 ScreenshotPixelRef(SkColorTable* ctable) {
453 fCTable = ctable;
Derek Sollenberger6062c592011-02-22 13:55:04 -0500454 SkSafeRef(ctable);
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800455 setImmutable();
456 }
457 virtual ~ScreenshotPixelRef() {
458 SkSafeUnref(fCTable);
Dianne Hackborna1111872010-11-23 20:55:11 -0800459 }
460
Dianne Hackbornd2835932010-12-13 16:28:46 -0800461 status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) {
Dianne Hackborna1111872010-11-23 20:55:11 -0800462 status_t res = (width > 0 && height > 0)
Dianne Hackbornd2835932010-12-13 16:28:46 -0800463 ? (allLayers
464 ? mScreenshot.update(width, height)
465 : mScreenshot.update(width, height, minLayer, maxLayer))
Dianne Hackborna1111872010-11-23 20:55:11 -0800466 : mScreenshot.update();
467 if (res != NO_ERROR) {
468 return res;
469 }
470
Dianne Hackborna1111872010-11-23 20:55:11 -0800471 return NO_ERROR;
472 }
473
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800474 uint32_t getWidth() const {
475 return mScreenshot.getWidth();
476 }
477
478 uint32_t getHeight() const {
479 return mScreenshot.getHeight();
480 }
481
482 uint32_t getStride() const {
483 return mScreenshot.getStride();
484 }
485
486 uint32_t getFormat() const {
487 return mScreenshot.getFormat();
488 }
489
490protected:
491 // overrides from SkPixelRef
492 virtual void* onLockPixels(SkColorTable** ct) {
493 *ct = fCTable;
494 return (void*)mScreenshot.getPixels();
495 }
496
497 virtual void onUnlockPixels() {
498 }
499
Dianne Hackborna1111872010-11-23 20:55:11 -0800500private:
501 ScreenshotClient mScreenshot;
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800502 SkColorTable* fCTable;
503
504 typedef SkPixelRef INHERITED;
Dianne Hackborna1111872010-11-23 20:55:11 -0800505};
506
Dianne Hackbornd2835932010-12-13 16:28:46 -0800507static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height,
508 jint minLayer, jint maxLayer, bool allLayers)
Dianne Hackborna1111872010-11-23 20:55:11 -0800509{
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800510 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
Dianne Hackbornd2835932010-12-13 16:28:46 -0800511 if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) {
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800512 delete pixels;
Dianne Hackborna1111872010-11-23 20:55:11 -0800513 return 0;
514 }
515
Dianne Hackborn1f5b1952010-11-29 14:41:46 -0800516 uint32_t w = pixels->getWidth();
517 uint32_t h = pixels->getHeight();
518 uint32_t s = pixels->getStride();
519 uint32_t f = pixels->getFormat();
520 ssize_t bpr = s * android::bytesPerPixel(f);
521
522 SkBitmap* bitmap = new SkBitmap();
523 bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
524 if (f == PIXEL_FORMAT_RGBX_8888) {
525 bitmap->setIsOpaque(true);
526 }
527
528 if (w > 0 && h > 0) {
529 bitmap->setPixelRef(pixels)->unref();
530 bitmap->lockPixels();
531 } else {
532 // be safe with an empty bitmap.
533 delete pixels;
534 bitmap->setPixels(NULL);
535 }
536
Dianne Hackborna1111872010-11-23 20:55:11 -0800537 return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
538}
539
Dianne Hackbornd2835932010-12-13 16:28:46 -0800540static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
541{
542 return doScreenshot(env, clazz, width, height, 0, 0, true);
543}
544
545static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
546 jint minLayer, jint maxLayer, bool allLayers)
547{
548 return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
549}
550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551static void Surface_setLayer(
552 JNIEnv* env, jobject clazz, jint zorder)
553{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700554 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
555 if (surface == 0) return;
556 status_t err = surface->setLayer(zorder);
557 if (err<0 && err!=NO_INIT)
558 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559}
560
561static void Surface_setPosition(
562 JNIEnv* env, jobject clazz, jint x, jint y)
563{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700564 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
565 if (surface == 0) return;
566 status_t err = surface->setPosition(x, y);
567 if (err<0 && err!=NO_INIT)
568 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569}
570
571static void Surface_setSize(
572 JNIEnv* env, jobject clazz, jint w, jint h)
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->setSize(w, h);
577 if (err<0 && err!=NO_INIT)
578 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579}
580
581static void Surface_hide(
582 JNIEnv* env, jobject clazz)
583{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700584 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
585 if (surface == 0) return;
586 status_t err = surface->hide();
587 if (err<0 && err!=NO_INIT)
588 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589}
590
591static void Surface_show(
592 JNIEnv* env, jobject clazz)
593{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700594 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
595 if (surface == 0) return;
596 status_t err = surface->show();
597 if (err<0 && err!=NO_INIT)
598 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599}
600
601static void Surface_freeze(
602 JNIEnv* env, jobject clazz)
603{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700604 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
605 if (surface == 0) return;
606 status_t err = surface->freeze();
607 if (err<0 && err!=NO_INIT)
608 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609}
610
611static void Surface_unfreeze(
612 JNIEnv* env, jobject clazz)
613{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700614 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
615 if (surface == 0) return;
616 status_t err = surface->unfreeze();
617 if (err<0 && err!=NO_INIT)
618 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619}
620
621static void Surface_setFlags(
622 JNIEnv* env, jobject clazz, jint flags, jint mask)
623{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700624 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
625 if (surface == 0) return;
626 status_t err = surface->setFlags(flags, mask);
627 if (err<0 && err!=NO_INIT)
628 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629}
630
631static void Surface_setTransparentRegion(
632 JNIEnv* env, jobject clazz, jobject argRegion)
633{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700634 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
635 if (surface == 0) return;
636 SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
Mathias Agopian6158b1b2009-05-11 00:03:41 -0700637
638 const SkIRect& b(nativeRegion->getBounds());
639 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
640 if (nativeRegion->isComplex()) {
641 SkRegion::Iterator it(*nativeRegion);
642 while (!it.done()) {
643 const SkIRect& r(it.rect());
644 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
645 it.next();
646 }
647 }
648
649 status_t err = surface->setTransparentRegionHint(reg);
Mathias Agopian17f638b2009-04-16 20:04:08 -0700650 if (err<0 && err!=NO_INIT)
651 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652}
653
654static void Surface_setAlpha(
655 JNIEnv* env, jobject clazz, jfloat alpha)
656{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700657 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
658 if (surface == 0) return;
659 status_t err = surface->setAlpha(alpha);
660 if (err<0 && err!=NO_INIT)
661 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662}
663
664static void Surface_setMatrix(
665 JNIEnv* env, jobject clazz,
666 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
667{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700668 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
669 if (surface == 0) return;
670 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
671 if (err<0 && err!=NO_INIT)
672 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673}
674
675static void Surface_setFreezeTint(
676 JNIEnv* env, jobject clazz,
677 jint tint)
678{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700679 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
680 if (surface == 0) return;
681 status_t err = surface->setFreezeTint(tint);
682 if (err<0 && err!=NO_INIT)
683 doThrow(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684}
685
Mathias Agopian17f638b2009-04-16 20:04:08 -0700686// ----------------------------------------------------------------------------
687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688static void Surface_copyFrom(
689 JNIEnv* env, jobject clazz, jobject other)
690{
691 if (clazz == other)
692 return;
693
694 if (other == NULL) {
695 doThrow(env, "java/lang/NullPointerException", NULL);
696 return;
697 }
698
Mathias Agopian17f638b2009-04-16 20:04:08 -0700699 /*
700 * This is used by the WindowManagerService just after constructing
701 * a Surface and is necessary for returning the Surface reference to
702 * the caller. At this point, we should only have a SurfaceControl.
Mathias Agopian17f638b2009-04-16 20:04:08 -0700703 */
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700704
Mathias Agopian17f638b2009-04-16 20:04:08 -0700705 const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
706 const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
707 if (!SurfaceControl::isSameSurface(surface, rhs)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 // we reassign the surface only if it's a different one
709 // otherwise we would loose our client-side state.
Mathias Agopian17f638b2009-04-16 20:04:08 -0700710 setSurfaceControl(env, clazz, rhs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 }
712}
713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714static void Surface_readFromParcel(
715 JNIEnv* env, jobject clazz, jobject argParcel)
716{
717 Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
718 if (parcel == NULL) {
719 doThrow(env, "java/lang/NullPointerException", NULL);
720 return;
721 }
722
Jamie Gennis5ee65f02010-07-15 17:29:15 -0700723 sp<Surface> sur(Surface::readFromParcel(*parcel));
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700724 setSurface(env, clazz, sur);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725}
726
727static void Surface_writeToParcel(
728 JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
729{
730 Parcel* parcel = (Parcel*)env->GetIntField(
731 argParcel, no.native_parcel);
732
733 if (parcel == NULL) {
734 doThrow(env, "java/lang/NullPointerException", NULL);
735 return;
736 }
737
Mathias Agopian17f638b2009-04-16 20:04:08 -0700738 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
739 SurfaceControl::writeSurfaceToParcel(control, parcel);
Mathias Agopianaf1e11b2010-03-23 15:31:21 -0700740 if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
741 setSurfaceControl(env, clazz, 0);
742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743}
744
745// ----------------------------------------------------------------------------
746// ----------------------------------------------------------------------------
747// ----------------------------------------------------------------------------
748
749const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
750const char* const kSurfaceClassPathName = "android/view/Surface";
751static void nativeClassInit(JNIEnv* env, jclass clazz);
752
753static JNINativeMethod gSurfaceSessionMethods[] = {
Marco Nelissen8138cb42010-04-26 16:05:48 -0700754 {"init", "()V", (void*)SurfaceSession_init },
755 {"destroy", "()V", (void*)SurfaceSession_destroy },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 {"kill", "()V", (void*)SurfaceSession_kill },
757};
758
759static JNINativeMethod gSurfaceMethods[] = {
760 {"nativeClassInit", "()V", (void*)nativeClassInit },
Mathias Agopian5d26c1e2010-03-01 16:09:43 -0800761 {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel },
Marco Nelissen8138cb42010-04-26 16:05:48 -0700763 {"getIdentity", "()I", (void*)Surface_getIdentity },
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700764 {"destroy", "()V", (void*)Surface_destroy },
Mathias Agopian402c3462009-04-14 18:21:47 -0700765 {"release", "()V", (void*)Surface_release },
Marco Nelissen8138cb42010-04-26 16:05:48 -0700766 {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom },
767 {"isValid", "()Z", (void*)Surface_isValid },
768 {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas },
769 {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
770 {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
771 {"openTransaction", "()V", (void*)Surface_openTransaction },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 {"closeTransaction", "()V", (void*)Surface_closeTransaction },
Mathias Agopianeb0c86e2009-03-27 18:11:38 -0700773 {"setOrientation", "(III)V", (void*)Surface_setOrientation },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay },
775 {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay },
Dianne Hackbornd2835932010-12-13 16:28:46 -0800776 {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
777 {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 {"setLayer", "(I)V", (void*)Surface_setLayer },
Marco Nelissen8138cb42010-04-26 16:05:48 -0700779 {"setPosition", "(II)V",(void*)Surface_setPosition },
780 {"setSize", "(II)V",(void*)Surface_setSize },
781 {"hide", "()V", (void*)Surface_hide },
782 {"show", "()V", (void*)Surface_show },
783 {"freeze", "()V", (void*)Surface_freeze },
784 {"unfreeze", "()V", (void*)Surface_unfreeze },
785 {"setFlags", "(II)V",(void*)Surface_setFlags },
786 {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
787 {"setAlpha", "(F)V", (void*)Surface_setAlpha },
788 {"setMatrix", "(FFFF)V", (void*)Surface_setMatrix },
789 {"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint },
790 {"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
791 {"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792};
793
794void nativeClassInit(JNIEnv* env, jclass clazz)
795{
Mathias Agopian8b138322010-04-12 16:22:15 -0700796 so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
Romain Guy2a83f002011-01-18 18:28:21 -0800797 so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I");
Mathias Agopian17f638b2009-04-16 20:04:08 -0700798 so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
Marco Nelissen8138cb42010-04-26 16:05:48 -0700799 so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
800 so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801
802 jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
Marco Nelissen8138cb42010-04-26 16:05:48 -0700803 sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804
805 jclass canvas = env->FindClass("android/graphics/Canvas");
806 no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
807 co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
808
809 jclass region = env->FindClass("android/graphics/Region");
810 no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
811
812 jclass parcel = env->FindClass("android/os/Parcel");
813 no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
814
815 jclass rect = env->FindClass("android/graphics/Rect");
816 ro.l = env->GetFieldID(rect, "left", "I");
817 ro.t = env->GetFieldID(rect, "top", "I");
818 ro.r = env->GetFieldID(rect, "right", "I");
819 ro.b = env->GetFieldID(rect, "bottom", "I");
820
821 jclass point = env->FindClass("android/graphics/Point");
822 po.x = env->GetFieldID(point, "x", "I");
823 po.y = env->GetFieldID(point, "y", "I");
824}
825
826int register_android_view_Surface(JNIEnv* env)
827{
828 int err;
829 err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
830 gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
831
832 err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
833 gSurfaceMethods, NELEM(gSurfaceMethods));
834 return err;
835}
836
837};