android_view_Surface.cpp revision b40696cc216f6a5874189fe83055ddaa7b428ce0
1/* 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 17#define LOG_TAG "Surface" 18 19#include <stdio.h> 20 21#include "android_util_Binder.h" 22#include "android/graphics/GraphicsJNI.h" 23 24#include <binder/IMemory.h> 25 26#include <gui/Surface.h> 27#include <gui/SurfaceComposerClient.h> 28#include <gui/SurfaceTexture.h> 29 30#include <ui/Rect.h> 31#include <ui/Region.h> 32 33#include <EGL/egl.h> 34 35#include <SkCanvas.h> 36#include <SkBitmap.h> 37#include <SkRegion.h> 38#include <SkPixelRef.h> 39 40#include "jni.h" 41#include "JNIHelp.h" 42#include <android_runtime/AndroidRuntime.h> 43#include <android_runtime/android_view_Surface.h> 44#include <android_runtime/android_graphics_SurfaceTexture.h> 45#include <utils/misc.h> 46 47 48// ---------------------------------------------------------------------------- 49 50namespace android { 51 52enum { 53 // should match Parcelable.java 54 PARCELABLE_WRITE_RETURN_VALUE = 0x0001 55}; 56 57// ---------------------------------------------------------------------------- 58 59static const char* const OutOfResourcesException = 60 "android/view/Surface$OutOfResourcesException"; 61 62const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession"; 63const char* const kSurfaceClassPathName = "android/view/Surface"; 64 65struct sso_t { 66 jfieldID client; 67}; 68static sso_t sso; 69 70struct so_t { 71 jfieldID surfaceControl; 72 jfieldID surfaceGenerationId; 73 jfieldID surface; 74 jfieldID saveCount; 75 jfieldID canvas; 76}; 77static so_t so; 78 79struct ro_t { 80 jfieldID l; 81 jfieldID t; 82 jfieldID r; 83 jfieldID b; 84}; 85static ro_t ro; 86 87struct po_t { 88 jfieldID x; 89 jfieldID y; 90}; 91static po_t po; 92 93struct co_t { 94 jfieldID surfaceFormat; 95}; 96static co_t co; 97 98struct no_t { 99 jfieldID native_canvas; 100 jfieldID native_region; 101 jfieldID native_parcel; 102}; 103static no_t no; 104 105 106// ---------------------------------------------------------------------------- 107// ---------------------------------------------------------------------------- 108// ---------------------------------------------------------------------------- 109 110static void SurfaceSession_init(JNIEnv* env, jobject clazz) 111{ 112 sp<SurfaceComposerClient> client = new SurfaceComposerClient; 113 client->incStrong(clazz); 114 env->SetIntField(clazz, sso.client, (int)client.get()); 115} 116 117static void SurfaceSession_destroy(JNIEnv* env, jobject clazz) 118{ 119 SurfaceComposerClient* client = 120 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client); 121 if (client != 0) { 122 client->decStrong(clazz); 123 env->SetIntField(clazz, sso.client, 0); 124 } 125} 126 127static void SurfaceSession_kill(JNIEnv* env, jobject clazz) 128{ 129 SurfaceComposerClient* client = 130 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client); 131 if (client != 0) { 132 client->dispose(); 133 client->decStrong(clazz); 134 env->SetIntField(clazz, sso.client, 0); 135 } 136} 137 138// ---------------------------------------------------------------------------- 139 140static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz) 141{ 142 SurfaceControl* const p = 143 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); 144 return sp<SurfaceControl>(p); 145} 146 147static void setSurfaceControl(JNIEnv* env, jobject clazz, 148 const sp<SurfaceControl>& surface) 149{ 150 SurfaceControl* const p = 151 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); 152 if (surface.get()) { 153 surface->incStrong(clazz); 154 } 155 if (p) { 156 p->decStrong(clazz); 157 } 158 env->SetIntField(clazz, so.surfaceControl, (int)surface.get()); 159} 160 161static sp<Surface> getSurface(JNIEnv* env, jobject clazz) 162{ 163 sp<Surface> result(Surface_getSurface(env, clazz)); 164 if (result == 0) { 165 /* 166 * if this method is called from the WindowManager's process, it means 167 * the client is is not remote, and therefore is allowed to have 168 * a Surface (data), so we create it here. 169 * If we don't have a SurfaceControl, it means we're in a different 170 * process. 171 */ 172 173 SurfaceControl* const control = 174 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); 175 if (control) { 176 result = control->getSurface(); 177 if (result != 0) { 178 result->incStrong(clazz); 179 env->SetIntField(clazz, so.surface, (int)result.get()); 180 } 181 } 182 } 183 return result; 184} 185 186sp<ANativeWindow> android_Surface_getNativeWindow( 187 JNIEnv* env, jobject clazz) { 188 return getSurface(env, clazz); 189} 190 191bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj) { 192 jclass surfaceClass = env->FindClass(kSurfaceClassPathName); 193 return env->IsInstanceOf(obj, surfaceClass); 194} 195 196sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) { 197 sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface)); 198 return surface; 199} 200 201void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface) 202{ 203 Surface* const p = (Surface*)env->GetIntField(clazz, so.surface); 204 if (surface.get()) { 205 surface->incStrong(clazz); 206 } 207 if (p) { 208 p->decStrong(clazz); 209 } 210 env->SetIntField(clazz, so.surface, (int)surface.get()); 211 // This test is conservative and it would be better to compare the ISurfaces 212 if (p && p != surface.get()) { 213 jint generationId = env->GetIntField(clazz, so.surfaceGenerationId); 214 generationId++; 215 env->SetIntField(clazz, so.surfaceGenerationId, generationId); 216 } 217} 218 219// ---------------------------------------------------------------------------- 220 221static void Surface_init( 222 JNIEnv* env, jobject clazz, 223 jobject session, 224 jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags) 225{ 226 if (session == NULL) { 227 doThrowNPE(env); 228 return; 229 } 230 231 SurfaceComposerClient* client = 232 (SurfaceComposerClient*)env->GetIntField(session, sso.client); 233 234 sp<SurfaceControl> surface; 235 if (jname == NULL) { 236 surface = client->createSurface(dpy, w, h, format, flags); 237 } else { 238 const jchar* str = env->GetStringCritical(jname, 0); 239 const String8 name(str, env->GetStringLength(jname)); 240 env->ReleaseStringCritical(jname, str); 241 surface = client->createSurface(name, dpy, w, h, format, flags); 242 } 243 244 if (surface == 0) { 245 jniThrowException(env, OutOfResourcesException, NULL); 246 return; 247 } 248 setSurfaceControl(env, clazz, surface); 249} 250 251static void Surface_initFromSurfaceTexture( 252 JNIEnv* env, jobject clazz, jobject jst) 253{ 254 sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst)); 255 256 if (st == NULL) { 257 jniThrowException(env, "java/lang/IllegalArgumentException", 258 "SurfaceTexture has already been released"); 259 return; 260 } 261 sp<ISurfaceTexture> bq = st->getBufferQueue(); 262 263 sp<Surface> surface(new Surface(bq)); 264 if (surface == NULL) { 265 jniThrowException(env, OutOfResourcesException, NULL); 266 return; 267 } 268 setSurfaceControl(env, clazz, NULL); 269 setSurface(env, clazz, surface); 270} 271 272static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) 273{ 274 Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); 275 if (parcel == NULL) { 276 doThrowNPE(env); 277 return; 278 } 279 280 sp<Surface> sur(Surface::readFromParcel(*parcel)); 281 setSurface(env, clazz, sur); 282} 283 284static jint Surface_getIdentity(JNIEnv* env, jobject clazz) 285{ 286 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); 287 if (control != 0) return (jint) control->getIdentity(); 288 const sp<Surface>& surface(getSurface(env, clazz)); 289 if (surface != 0) return (jint) surface->getIdentity(); 290 return -1; 291} 292 293static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack) 294{ 295 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 296 if (SurfaceControl::isValid(surface)) { 297 surface->clear(); 298 } 299 setSurfaceControl(env, clazz, 0); 300 setSurface(env, clazz, 0); 301} 302 303static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack) 304{ 305 setSurfaceControl(env, clazz, 0); 306 setSurface(env, clazz, 0); 307} 308 309static jboolean Surface_isValid(JNIEnv* env, jobject clazz) 310{ 311 const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz)); 312 if (surfaceControl != 0) { 313 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE; 314 } 315 const sp<Surface>& surface(getSurface(env, clazz)); 316 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE; 317} 318 319static jboolean Surface_isConsumerRunningBehind(JNIEnv* env, jobject clazz) 320{ 321 int value = 0; 322 const sp<Surface>& surface(getSurface(env, clazz)); 323 if (!Surface::isValid(surface)) { 324 doThrowIAE(env); 325 return 0; 326 } 327 ANativeWindow* anw = static_cast<ANativeWindow *>(surface.get()); 328 anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value); 329 return (jboolean)value; 330} 331 332static inline SkBitmap::Config convertPixelFormat(PixelFormat format) 333{ 334 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then 335 we can map to SkBitmap::kARGB_8888_Config, and optionally call 336 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator) 337 */ 338 switch (format) { 339 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; 340 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; 341 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; 342 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; 343 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; 344 default: return SkBitmap::kNo_Config; 345 } 346} 347 348static void Surface_setActiveRect(JNIEnv* env, jobject thiz, jobject activeRect) 349{ 350 const sp<Surface>& surface(getSurface(env, thiz)); 351 if (!Surface::isValid(surface)) { 352 doThrowIAE(env); 353 return; 354 } 355 356 android_native_rect_t nativeRect; 357 if (activeRect) { 358 nativeRect.left = env->GetIntField(activeRect, ro.l); 359 nativeRect.top = env->GetIntField(activeRect, ro.t); 360 nativeRect.right = env->GetIntField(activeRect, ro.r); 361 nativeRect.bottom= env->GetIntField(activeRect, ro.b); 362 } else { 363 doThrowIAE(env, "activeRect may not be null"); 364 return; 365 } 366 367 int err = native_window_set_active_rect(surface.get(), &nativeRect); 368 if (err != NO_ERROR) { 369 doThrowRE(env, String8::format( 370 "Surface::setActiveRect returned an error: %d", err).string()); 371 } 372} 373 374static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) 375{ 376 const sp<Surface>& surface(getSurface(env, clazz)); 377 if (!Surface::isValid(surface)) { 378 doThrowIAE(env); 379 return 0; 380 } 381 382 // get dirty region 383 Region dirtyRegion; 384 if (dirtyRect) { 385 Rect dirty; 386 dirty.left = env->GetIntField(dirtyRect, ro.l); 387 dirty.top = env->GetIntField(dirtyRect, ro.t); 388 dirty.right = env->GetIntField(dirtyRect, ro.r); 389 dirty.bottom= env->GetIntField(dirtyRect, ro.b); 390 if (!dirty.isEmpty()) { 391 dirtyRegion.set(dirty); 392 } 393 } else { 394 dirtyRegion.set(Rect(0x3FFF,0x3FFF)); 395 } 396 397 Surface::SurfaceInfo info; 398 status_t err = surface->lock(&info, &dirtyRegion); 399 if (err < 0) { 400 const char* const exception = (err == NO_MEMORY) ? 401 OutOfResourcesException : 402 "java/lang/IllegalArgumentException"; 403 jniThrowException(env, exception, NULL); 404 return 0; 405 } 406 407 // Associate a SkCanvas object to this surface 408 jobject canvas = env->GetObjectField(clazz, so.canvas); 409 env->SetIntField(canvas, co.surfaceFormat, info.format); 410 411 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); 412 SkBitmap bitmap; 413 ssize_t bpr = info.s * bytesPerPixel(info.format); 414 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); 415 if (info.format == PIXEL_FORMAT_RGBX_8888) { 416 bitmap.setIsOpaque(true); 417 } 418 if (info.w > 0 && info.h > 0) { 419 bitmap.setPixels(info.bits); 420 } else { 421 // be safe with an empty bitmap. 422 bitmap.setPixels(NULL); 423 } 424 nativeCanvas->setBitmapDevice(bitmap); 425 426 SkRegion clipReg; 427 if (dirtyRegion.isRect()) { // very common case 428 const Rect b(dirtyRegion.getBounds()); 429 clipReg.setRect(b.left, b.top, b.right, b.bottom); 430 } else { 431 size_t count; 432 Rect const* r = dirtyRegion.getArray(&count); 433 while (count) { 434 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op); 435 r++, count--; 436 } 437 } 438 439 nativeCanvas->clipRegion(clipReg); 440 441 int saveCount = nativeCanvas->save(); 442 env->SetIntField(clazz, so.saveCount, saveCount); 443 444 if (dirtyRect) { 445 const Rect& bounds(dirtyRegion.getBounds()); 446 env->SetIntField(dirtyRect, ro.l, bounds.left); 447 env->SetIntField(dirtyRect, ro.t, bounds.top); 448 env->SetIntField(dirtyRect, ro.r, bounds.right); 449 env->SetIntField(dirtyRect, ro.b, bounds.bottom); 450 } 451 452 return canvas; 453} 454 455static void Surface_unlockCanvasAndPost( 456 JNIEnv* env, jobject clazz, jobject argCanvas) 457{ 458 jobject canvas = env->GetObjectField(clazz, so.canvas); 459 if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) { 460 doThrowIAE(env); 461 return; 462 } 463 464 const sp<Surface>& surface(getSurface(env, clazz)); 465 if (!Surface::isValid(surface)) 466 return; 467 468 // detach the canvas from the surface 469 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); 470 int saveCount = env->GetIntField(clazz, so.saveCount); 471 nativeCanvas->restoreToCount(saveCount); 472 nativeCanvas->setBitmapDevice(SkBitmap()); 473 env->SetIntField(clazz, so.saveCount, 0); 474 475 // unlock surface 476 status_t err = surface->unlockAndPost(); 477 if (err < 0) { 478 doThrowIAE(env); 479 } 480} 481 482static void Surface_unlockCanvas( 483 JNIEnv* env, jobject clazz, jobject argCanvas) 484{ 485 // XXX: this API has been removed 486 doThrowIAE(env); 487} 488 489static void Surface_openTransaction( 490 JNIEnv* env, jobject clazz) 491{ 492 SurfaceComposerClient::openGlobalTransaction(); 493} 494 495static void Surface_closeTransaction( 496 JNIEnv* env, jobject clazz) 497{ 498 SurfaceComposerClient::closeGlobalTransaction(); 499} 500 501static void Surface_setOrientation( 502 JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags) 503{ 504 int err = SurfaceComposerClient::setOrientation(display, orientation, flags); 505 if (err < 0) { 506 doThrowIAE(env); 507 } 508} 509 510static void Surface_freezeDisplay( 511 JNIEnv* env, jobject clazz, jint display) 512{ 513 int err = SurfaceComposerClient::freezeDisplay(display, 0); 514 if (err < 0) { 515 doThrowIAE(env); 516 } 517} 518 519static void Surface_unfreezeDisplay( 520 JNIEnv* env, jobject clazz, jint display) 521{ 522 int err = SurfaceComposerClient::unfreezeDisplay(display, 0); 523 if (err < 0) { 524 doThrowIAE(env); 525 } 526} 527 528class ScreenshotPixelRef : public SkPixelRef { 529public: 530 ScreenshotPixelRef(SkColorTable* ctable) { 531 fCTable = ctable; 532 SkSafeRef(ctable); 533 setImmutable(); 534 } 535 virtual ~ScreenshotPixelRef() { 536 SkSafeUnref(fCTable); 537 } 538 539 status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) { 540 status_t res = (width > 0 && height > 0) 541 ? (allLayers 542 ? mScreenshot.update(width, height) 543 : mScreenshot.update(width, height, minLayer, maxLayer)) 544 : mScreenshot.update(); 545 if (res != NO_ERROR) { 546 return res; 547 } 548 549 return NO_ERROR; 550 } 551 552 uint32_t getWidth() const { 553 return mScreenshot.getWidth(); 554 } 555 556 uint32_t getHeight() const { 557 return mScreenshot.getHeight(); 558 } 559 560 uint32_t getStride() const { 561 return mScreenshot.getStride(); 562 } 563 564 uint32_t getFormat() const { 565 return mScreenshot.getFormat(); 566 } 567 568protected: 569 // overrides from SkPixelRef 570 virtual void* onLockPixels(SkColorTable** ct) { 571 *ct = fCTable; 572 return (void*)mScreenshot.getPixels(); 573 } 574 575 virtual void onUnlockPixels() { 576 } 577 578private: 579 ScreenshotClient mScreenshot; 580 SkColorTable* fCTable; 581 582 typedef SkPixelRef INHERITED; 583}; 584 585static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height, 586 jint minLayer, jint maxLayer, bool allLayers) 587{ 588 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); 589 if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) { 590 delete pixels; 591 return 0; 592 } 593 594 uint32_t w = pixels->getWidth(); 595 uint32_t h = pixels->getHeight(); 596 uint32_t s = pixels->getStride(); 597 uint32_t f = pixels->getFormat(); 598 ssize_t bpr = s * android::bytesPerPixel(f); 599 600 SkBitmap* bitmap = new SkBitmap(); 601 bitmap->setConfig(convertPixelFormat(f), w, h, bpr); 602 if (f == PIXEL_FORMAT_RGBX_8888) { 603 bitmap->setIsOpaque(true); 604 } 605 606 if (w > 0 && h > 0) { 607 bitmap->setPixelRef(pixels)->unref(); 608 bitmap->lockPixels(); 609 } else { 610 // be safe with an empty bitmap. 611 delete pixels; 612 bitmap->setPixels(NULL); 613 } 614 615 return GraphicsJNI::createBitmap(env, bitmap, false, NULL); 616} 617 618static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height) 619{ 620 return doScreenshot(env, clazz, width, height, 0, 0, true); 621} 622 623static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height, 624 jint minLayer, jint maxLayer) 625{ 626 return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false); 627} 628 629static void Surface_setLayer( 630 JNIEnv* env, jobject clazz, jint zorder) 631{ 632 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 633 if (surface == 0) return; 634 status_t err = surface->setLayer(zorder); 635 if (err<0 && err!=NO_INIT) { 636 doThrowIAE(env); 637 } 638} 639 640static void Surface_setPosition( 641 JNIEnv* env, jobject clazz, jfloat x, jfloat y) 642{ 643 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 644 if (surface == 0) return; 645 status_t err = surface->setPosition(x, y); 646 if (err<0 && err!=NO_INIT) { 647 doThrowIAE(env); 648 } 649} 650 651static void Surface_setSize( 652 JNIEnv* env, jobject clazz, jint w, jint h) 653{ 654 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 655 if (surface == 0) return; 656 status_t err = surface->setSize(w, h); 657 if (err<0 && err!=NO_INIT) { 658 doThrowIAE(env); 659 } 660} 661 662static void Surface_hide( 663 JNIEnv* env, jobject clazz) 664{ 665 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 666 if (surface == 0) return; 667 status_t err = surface->hide(); 668 if (err<0 && err!=NO_INIT) { 669 doThrowIAE(env); 670 } 671} 672 673static void Surface_show( 674 JNIEnv* env, jobject clazz) 675{ 676 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 677 if (surface == 0) return; 678 status_t err = surface->show(); 679 if (err<0 && err!=NO_INIT) { 680 doThrowIAE(env); 681 } 682} 683 684static void Surface_freeze( 685 JNIEnv* env, jobject clazz) 686{ 687 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 688 if (surface == 0) return; 689 status_t err = surface->freeze(); 690 if (err<0 && err!=NO_INIT) { 691 doThrowIAE(env); 692 } 693} 694 695static void Surface_unfreeze( 696 JNIEnv* env, jobject clazz) 697{ 698 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 699 if (surface == 0) return; 700 status_t err = surface->unfreeze(); 701 if (err<0 && err!=NO_INIT) { 702 doThrowIAE(env); 703 } 704} 705 706static void Surface_setFlags( 707 JNIEnv* env, jobject clazz, jint flags, jint mask) 708{ 709 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 710 if (surface == 0) return; 711 status_t err = surface->setFlags(flags, mask); 712 if (err<0 && err!=NO_INIT) { 713 doThrowIAE(env); 714 } 715} 716 717static void Surface_setTransparentRegion( 718 JNIEnv* env, jobject clazz, jobject argRegion) 719{ 720 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 721 if (surface == 0) return; 722 SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region); 723 724 const SkIRect& b(nativeRegion->getBounds()); 725 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); 726 if (nativeRegion->isComplex()) { 727 SkRegion::Iterator it(*nativeRegion); 728 while (!it.done()) { 729 const SkIRect& r(it.rect()); 730 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); 731 it.next(); 732 } 733 } 734 735 status_t err = surface->setTransparentRegionHint(reg); 736 if (err<0 && err!=NO_INIT) { 737 doThrowIAE(env); 738 } 739} 740 741static void Surface_setAlpha( 742 JNIEnv* env, jobject clazz, jfloat alpha) 743{ 744 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 745 if (surface == 0) return; 746 status_t err = surface->setAlpha(alpha); 747 if (err<0 && err!=NO_INIT) { 748 doThrowIAE(env); 749 } 750} 751 752static void Surface_setMatrix( 753 JNIEnv* env, jobject clazz, 754 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) 755{ 756 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 757 if (surface == 0) return; 758 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy); 759 if (err<0 && err!=NO_INIT) { 760 doThrowIAE(env); 761 } 762} 763 764static void Surface_setFreezeTint( 765 JNIEnv* env, jobject clazz, 766 jint tint) 767{ 768 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 769 if (surface == 0) return; 770 status_t err = surface->setFreezeTint(tint); 771 if (err<0 && err!=NO_INIT) { 772 doThrowIAE(env); 773 } 774} 775 776// ---------------------------------------------------------------------------- 777 778static void Surface_copyFrom( 779 JNIEnv* env, jobject clazz, jobject other) 780{ 781 if (clazz == other) 782 return; 783 784 if (other == NULL) { 785 doThrowNPE(env); 786 return; 787 } 788 789 /* 790 * This is used by the WindowManagerService just after constructing 791 * a Surface and is necessary for returning the Surface reference to 792 * the caller. At this point, we should only have a SurfaceControl. 793 */ 794 795 const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz); 796 const sp<SurfaceControl>& rhs = getSurfaceControl(env, other); 797 if (!SurfaceControl::isSameSurface(surface, rhs)) { 798 // we reassign the surface only if it's a different one 799 // otherwise we would loose our client-side state. 800 setSurfaceControl(env, clazz, rhs); 801 } 802} 803 804static void Surface_transferFrom( 805 JNIEnv* env, jobject clazz, jobject other) 806{ 807 if (clazz == other) 808 return; 809 810 if (other == NULL) { 811 doThrowNPE(env); 812 return; 813 } 814 815 sp<SurfaceControl> control(getSurfaceControl(env, other)); 816 sp<Surface> surface(Surface_getSurface(env, other)); 817 setSurfaceControl(env, clazz, control); 818 setSurface(env, clazz, surface); 819 setSurfaceControl(env, other, 0); 820 setSurface(env, other, 0); 821} 822 823static void Surface_readFromParcel( 824 JNIEnv* env, jobject clazz, jobject argParcel) 825{ 826 Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel); 827 if (parcel == NULL) { 828 doThrowNPE(env); 829 return; 830 } 831 832 sp<Surface> sur(Surface::readFromParcel(*parcel)); 833 setSurface(env, clazz, sur); 834} 835 836static void Surface_writeToParcel( 837 JNIEnv* env, jobject clazz, jobject argParcel, jint flags) 838{ 839 Parcel* parcel = (Parcel*)env->GetIntField( 840 argParcel, no.native_parcel); 841 842 if (parcel == NULL) { 843 doThrowNPE(env); 844 return; 845 } 846 847 // The Java instance may have a SurfaceControl (in the case of the 848 // WindowManager or a system app). In that case, we defer to the 849 // SurfaceControl to send its ISurface. Otherwise, if the Surface is 850 // available we let it parcel itself. Finally, if the Surface is also 851 // NULL we fall back to using the SurfaceControl path which sends an 852 // empty surface; this matches legacy behavior. 853 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); 854 if (control != NULL) { 855 SurfaceControl::writeSurfaceToParcel(control, parcel); 856 } else { 857 sp<Surface> surface(Surface_getSurface(env, clazz)); 858 if (surface != NULL) { 859 Surface::writeToParcel(surface, parcel); 860 } else { 861 SurfaceControl::writeSurfaceToParcel(NULL, parcel); 862 } 863 } 864 if (flags & PARCELABLE_WRITE_RETURN_VALUE) { 865 setSurfaceControl(env, clazz, NULL); 866 setSurface(env, clazz, NULL); 867 } 868} 869 870// ---------------------------------------------------------------------------- 871// ---------------------------------------------------------------------------- 872// ---------------------------------------------------------------------------- 873 874static void nativeClassInit(JNIEnv* env, jclass clazz); 875 876static JNINativeMethod gSurfaceSessionMethods[] = { 877 {"init", "()V", (void*)SurfaceSession_init }, 878 {"destroy", "()V", (void*)SurfaceSession_destroy }, 879 {"kill", "()V", (void*)SurfaceSession_kill }, 880}; 881 882static JNINativeMethod gSurfaceMethods[] = { 883 {"nativeClassInit", "()V", (void*)nativeClassInit }, 884 {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init }, 885 {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel }, 886 {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture }, 887 {"getIdentity", "()I", (void*)Surface_getIdentity }, 888 {"destroy", "()V", (void*)Surface_destroy }, 889 {"release", "()V", (void*)Surface_release }, 890 {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom }, 891 {"transferFrom", "(Landroid/view/Surface;)V", (void*)Surface_transferFrom }, 892 {"isValid", "()Z", (void*)Surface_isValid }, 893 {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas }, 894 {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost }, 895 {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas }, 896 {"openTransaction", "()V", (void*)Surface_openTransaction }, 897 {"closeTransaction", "()V", (void*)Surface_closeTransaction }, 898 {"setOrientation", "(III)V", (void*)Surface_setOrientation }, 899 {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay }, 900 {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay }, 901 {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll }, 902 {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot }, 903 {"setLayer", "(I)V", (void*)Surface_setLayer }, 904 {"setPosition", "(FF)V",(void*)Surface_setPosition }, 905 {"setSize", "(II)V",(void*)Surface_setSize }, 906 {"hide", "()V", (void*)Surface_hide }, 907 {"show", "()V", (void*)Surface_show }, 908 {"freeze", "()V", (void*)Surface_freeze }, 909 {"unfreeze", "()V", (void*)Surface_unfreeze }, 910 {"setFlags", "(II)V",(void*)Surface_setFlags }, 911 {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion }, 912 {"setAlpha", "(F)V", (void*)Surface_setAlpha }, 913 {"setMatrix", "(FFFF)V", (void*)Surface_setMatrix }, 914 {"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint }, 915 {"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel }, 916 {"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel }, 917 {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind }, 918 {"setActiveRect", "(Landroid/graphics/Rect;)V", (void*)Surface_setActiveRect }, 919}; 920 921void nativeClassInit(JNIEnv* env, jclass clazz) 922{ 923 so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 924 so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I"); 925 so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I"); 926 so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I"); 927 so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;"); 928 929 jclass surfaceSession = env->FindClass("android/view/SurfaceSession"); 930 sso.client = env->GetFieldID(surfaceSession, "mClient", "I"); 931 932 jclass canvas = env->FindClass("android/graphics/Canvas"); 933 no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I"); 934 co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I"); 935 936 jclass region = env->FindClass("android/graphics/Region"); 937 no.native_region = env->GetFieldID(region, "mNativeRegion", "I"); 938 939 jclass parcel = env->FindClass("android/os/Parcel"); 940 no.native_parcel = env->GetFieldID(parcel, "mNativePtr", "I"); 941 942 jclass rect = env->FindClass("android/graphics/Rect"); 943 ro.l = env->GetFieldID(rect, "left", "I"); 944 ro.t = env->GetFieldID(rect, "top", "I"); 945 ro.r = env->GetFieldID(rect, "right", "I"); 946 ro.b = env->GetFieldID(rect, "bottom", "I"); 947 948 jclass point = env->FindClass("android/graphics/Point"); 949 po.x = env->GetFieldID(point, "x", "I"); 950 po.y = env->GetFieldID(point, "y", "I"); 951} 952 953int register_android_view_Surface(JNIEnv* env) 954{ 955 int err; 956 err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName, 957 gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods)); 958 959 err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName, 960 gSurfaceMethods, NELEM(gSurfaceMethods)); 961 return err; 962} 963 964}; 965