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 <stdint.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <errno.h> 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 26 #include <utils/Errors.h> 27 #include <utils/threads.h> 28 #include <utils/CallStack.h> 29 #include <utils/Log.h> 30 31 #include <pixelflinger/pixelflinger.h> 32 33 #include <binder/IPCThreadState.h> 34 #include <binder/IMemory.h> 35 36 #include <ui/DisplayInfo.h> 37 #include <ui/GraphicBuffer.h> 38 #include <ui/GraphicBufferMapper.h> 39 #include <ui/Rect.h> 40 41 #include <surfaceflinger/Surface.h> 42 #include <surfaceflinger/ISurface.h> 43 #include <surfaceflinger/ISurfaceComposer.h> 44 #include <surfaceflinger/SurfaceComposerClient.h> 45 46 #include <private/surfaceflinger/SharedBufferStack.h> 47 #include <private/surfaceflinger/LayerState.h> 48 49 namespace android { 50 51 // ---------------------------------------------------------------------- 52 53 static status_t copyBlt( 54 const sp<GraphicBuffer>& dst, 55 const sp<GraphicBuffer>& src, 56 const Region& reg) 57 { 58 status_t err; 59 uint8_t const * src_bits = NULL; 60 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); 61 LOGE_IF(err, "error locking src buffer %s", strerror(-err)); 62 63 uint8_t* dst_bits = NULL; 64 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); 65 LOGE_IF(err, "error locking dst buffer %s", strerror(-err)); 66 67 Region::const_iterator head(reg.begin()); 68 Region::const_iterator tail(reg.end()); 69 if (head != tail && src_bits && dst_bits) { 70 // NOTE: dst and src must be the same format 71 const size_t bpp = bytesPerPixel(src->format); 72 const size_t dbpr = dst->stride * bpp; 73 const size_t sbpr = src->stride * bpp; 74 75 while (head != tail) { 76 const Rect& r(*head++); 77 ssize_t h = r.height(); 78 if (h <= 0) continue; 79 size_t size = r.width() * bpp; 80 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; 81 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; 82 if (dbpr==sbpr && size==sbpr) { 83 size *= h; 84 h = 1; 85 } 86 do { 87 memcpy(d, s, size); 88 d += dbpr; 89 s += sbpr; 90 } while (--h > 0); 91 } 92 } 93 94 if (src_bits) 95 src->unlock(); 96 97 if (dst_bits) 98 dst->unlock(); 99 100 return err; 101 } 102 103 // ============================================================================ 104 // SurfaceControl 105 // ============================================================================ 106 107 SurfaceControl::SurfaceControl( 108 const sp<SurfaceComposerClient>& client, 109 const sp<ISurface>& surface, 110 const ISurfaceFlingerClient::surface_data_t& data, 111 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) 112 : mClient(client), mSurface(surface), 113 mToken(data.token), mIdentity(data.identity), 114 mWidth(data.width), mHeight(data.height), mFormat(data.format), 115 mFlags(flags) 116 { 117 } 118 119 SurfaceControl::~SurfaceControl() 120 { 121 destroy(); 122 } 123 124 void SurfaceControl::destroy() 125 { 126 if (isValid()) { 127 mClient->destroySurface(mToken); 128 } 129 130 // clear all references and trigger an IPC now, to make sure things 131 // happen without delay, since these resources are quite heavy. 132 mClient.clear(); 133 mSurface.clear(); 134 IPCThreadState::self()->flushCommands(); 135 } 136 137 void SurfaceControl::clear() 138 { 139 // here, the window manager tells us explicitly that we should destroy 140 // the surface's resource. Soon after this call, it will also release 141 // its last reference (which will call the dtor); however, it is possible 142 // that a client living in the same process still holds references which 143 // would delay the call to the dtor -- that is why we need this explicit 144 // "clear()" call. 145 destroy(); 146 } 147 148 bool SurfaceControl::isSameSurface( 149 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) 150 { 151 if (lhs == 0 || rhs == 0) 152 return false; 153 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); 154 } 155 156 status_t SurfaceControl::setLayer(int32_t layer) { 157 const sp<SurfaceComposerClient>& client(mClient); 158 status_t err = validate(); 159 if (err < 0) return err; 160 return client->setLayer(mToken, layer); 161 } 162 status_t SurfaceControl::setPosition(int32_t x, int32_t y) { 163 const sp<SurfaceComposerClient>& client(mClient); 164 status_t err = validate(); 165 if (err < 0) return err; 166 return client->setPosition(mToken, x, y); 167 } 168 status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { 169 const sp<SurfaceComposerClient>& client(mClient); 170 status_t err = validate(); 171 if (err < 0) return err; 172 return client->setSize(mToken, w, h); 173 } 174 status_t SurfaceControl::hide() { 175 const sp<SurfaceComposerClient>& client(mClient); 176 status_t err = validate(); 177 if (err < 0) return err; 178 return client->hide(mToken); 179 } 180 status_t SurfaceControl::show(int32_t layer) { 181 const sp<SurfaceComposerClient>& client(mClient); 182 status_t err = validate(); 183 if (err < 0) return err; 184 return client->show(mToken, layer); 185 } 186 status_t SurfaceControl::freeze() { 187 const sp<SurfaceComposerClient>& client(mClient); 188 status_t err = validate(); 189 if (err < 0) return err; 190 return client->freeze(mToken); 191 } 192 status_t SurfaceControl::unfreeze() { 193 const sp<SurfaceComposerClient>& client(mClient); 194 status_t err = validate(); 195 if (err < 0) return err; 196 return client->unfreeze(mToken); 197 } 198 status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { 199 const sp<SurfaceComposerClient>& client(mClient); 200 status_t err = validate(); 201 if (err < 0) return err; 202 return client->setFlags(mToken, flags, mask); 203 } 204 status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { 205 const sp<SurfaceComposerClient>& client(mClient); 206 status_t err = validate(); 207 if (err < 0) return err; 208 return client->setTransparentRegionHint(mToken, transparent); 209 } 210 status_t SurfaceControl::setAlpha(float alpha) { 211 const sp<SurfaceComposerClient>& client(mClient); 212 status_t err = validate(); 213 if (err < 0) return err; 214 return client->setAlpha(mToken, alpha); 215 } 216 status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 217 const sp<SurfaceComposerClient>& client(mClient); 218 status_t err = validate(); 219 if (err < 0) return err; 220 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); 221 } 222 status_t SurfaceControl::setFreezeTint(uint32_t tint) { 223 const sp<SurfaceComposerClient>& client(mClient); 224 status_t err = validate(); 225 if (err < 0) return err; 226 return client->setFreezeTint(mToken, tint); 227 } 228 229 status_t SurfaceControl::validate() const 230 { 231 if (mToken<0 || mClient==0) { 232 LOGE("invalid token (%d, identity=%u) or client (%p)", 233 mToken, mIdentity, mClient.get()); 234 return NO_INIT; 235 } 236 SharedClient const* cblk = mClient->mControl; 237 if (cblk == 0) { 238 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); 239 return NO_INIT; 240 } 241 status_t err = cblk->validate(mToken); 242 if (err != NO_ERROR) { 243 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", 244 mToken, mIdentity, err, strerror(-err)); 245 return err; 246 } 247 uint32_t identity = cblk->getIdentity(mToken); 248 if (mIdentity != identity) { 249 LOGE("using an invalid surface id=%d, identity=%u should be %d", 250 mToken, mIdentity, identity); 251 return NO_INIT; 252 } 253 return NO_ERROR; 254 } 255 256 status_t SurfaceControl::writeSurfaceToParcel( 257 const sp<SurfaceControl>& control, Parcel* parcel) 258 { 259 uint32_t flags = 0; 260 uint32_t format = 0; 261 SurfaceID token = -1; 262 uint32_t identity = 0; 263 uint32_t width = 0; 264 uint32_t height = 0; 265 sp<SurfaceComposerClient> client; 266 sp<ISurface> sur; 267 if (SurfaceControl::isValid(control)) { 268 token = control->mToken; 269 identity = control->mIdentity; 270 client = control->mClient; 271 sur = control->mSurface; 272 width = control->mWidth; 273 height = control->mHeight; 274 format = control->mFormat; 275 flags = control->mFlags; 276 } 277 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL); 278 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); 279 parcel->writeInt32(token); 280 parcel->writeInt32(identity); 281 parcel->writeInt32(width); 282 parcel->writeInt32(height); 283 parcel->writeInt32(format); 284 parcel->writeInt32(flags); 285 return NO_ERROR; 286 } 287 288 sp<Surface> SurfaceControl::getSurface() const 289 { 290 Mutex::Autolock _l(mLock); 291 if (mSurfaceData == 0) { 292 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); 293 } 294 return mSurfaceData; 295 } 296 297 // ============================================================================ 298 // Surface 299 // ============================================================================ 300 301 Surface::Surface(const sp<SurfaceControl>& surface) 302 : mClient(surface->mClient), mSurface(surface->mSurface), 303 mToken(surface->mToken), mIdentity(surface->mIdentity), 304 mFormat(surface->mFormat), mFlags(surface->mFlags), 305 mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL), 306 mWidth(surface->mWidth), mHeight(surface->mHeight) 307 { 308 mSharedBufferClient = new SharedBufferClient( 309 mClient->mControl, mToken, 2, mIdentity); 310 311 init(); 312 } 313 314 Surface::Surface(const Parcel& parcel) 315 : mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL) 316 { 317 sp<IBinder> clientBinder = parcel.readStrongBinder(); 318 mSurface = interface_cast<ISurface>(parcel.readStrongBinder()); 319 mToken = parcel.readInt32(); 320 mIdentity = parcel.readInt32(); 321 mWidth = parcel.readInt32(); 322 mHeight = parcel.readInt32(); 323 mFormat = parcel.readInt32(); 324 mFlags = parcel.readInt32(); 325 326 // FIXME: what does that mean if clientBinder is NULL here? 327 if (clientBinder != NULL) { 328 mClient = SurfaceComposerClient::clientForConnection(clientBinder); 329 330 mSharedBufferClient = new SharedBufferClient( 331 mClient->mControl, mToken, 2, mIdentity); 332 } 333 334 init(); 335 } 336 337 void Surface::init() 338 { 339 android_native_window_t::setSwapInterval = setSwapInterval; 340 android_native_window_t::dequeueBuffer = dequeueBuffer; 341 android_native_window_t::lockBuffer = lockBuffer; 342 android_native_window_t::queueBuffer = queueBuffer; 343 android_native_window_t::query = query; 344 android_native_window_t::perform = perform; 345 mSwapRectangle.makeInvalid(); 346 DisplayInfo dinfo; 347 SurfaceComposerClient::getDisplayInfo(0, &dinfo); 348 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi; 349 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi; 350 // FIXME: set real values here 351 const_cast<int&>(android_native_window_t::minSwapInterval) = 1; 352 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1; 353 const_cast<uint32_t&>(android_native_window_t::flags) = 0; 354 // be default we request a hardware surface 355 mUsage = GRALLOC_USAGE_HW_RENDER; 356 mConnected = 0; 357 mNeedFullUpdate = false; 358 } 359 360 Surface::~Surface() 361 { 362 // this is a client-side operation, the surface is destroyed, unmap 363 // its buffers in this process. 364 for (int i=0 ; i<2 ; i++) { 365 if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) { 366 getBufferMapper().unregisterBuffer(mBuffers[i]->handle); 367 } 368 } 369 370 // clear all references and trigger an IPC now, to make sure things 371 // happen without delay, since these resources are quite heavy. 372 mClient.clear(); 373 mSurface.clear(); 374 delete mSharedBufferClient; 375 IPCThreadState::self()->flushCommands(); 376 } 377 378 sp<SurfaceComposerClient> Surface::getClient() const { 379 return mClient; 380 } 381 382 sp<ISurface> Surface::getISurface() const { 383 return mSurface; 384 } 385 386 bool Surface::isValid() { 387 return mToken>=0 && mClient!=0; 388 } 389 390 status_t Surface::validate() const 391 { 392 sp<SurfaceComposerClient> client(getClient()); 393 if (mToken<0 || mClient==0) { 394 LOGE("invalid token (%d, identity=%u) or client (%p)", 395 mToken, mIdentity, client.get()); 396 return NO_INIT; 397 } 398 SharedClient const* cblk = mClient->mControl; 399 if (cblk == 0) { 400 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); 401 return NO_INIT; 402 } 403 status_t err = cblk->validate(mToken); 404 if (err != NO_ERROR) { 405 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", 406 mToken, mIdentity, err, strerror(-err)); 407 return err; 408 } 409 uint32_t identity = cblk->getIdentity(mToken); 410 if (mIdentity != identity) { 411 LOGE("using an invalid surface id=%d, identity=%u should be %d", 412 mToken, mIdentity, identity); 413 return NO_INIT; 414 } 415 return NO_ERROR; 416 } 417 418 419 bool Surface::isSameSurface( 420 const sp<Surface>& lhs, const sp<Surface>& rhs) 421 { 422 if (lhs == 0 || rhs == 0) 423 return false; 424 425 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); 426 } 427 428 // ---------------------------------------------------------------------------- 429 430 int Surface::setSwapInterval(android_native_window_t* window, int interval) { 431 return 0; 432 } 433 434 int Surface::dequeueBuffer(android_native_window_t* window, 435 android_native_buffer_t** buffer) { 436 Surface* self = getSelf(window); 437 return self->dequeueBuffer(buffer); 438 } 439 440 int Surface::lockBuffer(android_native_window_t* window, 441 android_native_buffer_t* buffer) { 442 Surface* self = getSelf(window); 443 return self->lockBuffer(buffer); 444 } 445 446 int Surface::queueBuffer(android_native_window_t* window, 447 android_native_buffer_t* buffer) { 448 Surface* self = getSelf(window); 449 return self->queueBuffer(buffer); 450 } 451 452 int Surface::query(android_native_window_t* window, 453 int what, int* value) { 454 Surface* self = getSelf(window); 455 return self->query(what, value); 456 } 457 458 int Surface::perform(android_native_window_t* window, 459 int operation, ...) { 460 va_list args; 461 va_start(args, operation); 462 Surface* self = getSelf(window); 463 int res = self->perform(operation, args); 464 va_end(args); 465 return res; 466 } 467 468 // ---------------------------------------------------------------------------- 469 470 status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) { 471 android_native_buffer_t* out; 472 status_t err = dequeueBuffer(&out); 473 if (err == NO_ERROR) { 474 *buffer = GraphicBuffer::getSelf(out); 475 } 476 return err; 477 } 478 479 // ---------------------------------------------------------------------------- 480 481 482 int Surface::dequeueBuffer(android_native_buffer_t** buffer) 483 { 484 sp<SurfaceComposerClient> client(getClient()); 485 status_t err = validate(); 486 if (err != NO_ERROR) 487 return err; 488 489 ssize_t bufIdx = mSharedBufferClient->dequeue(); 490 if (bufIdx < 0) { 491 LOGE("error dequeuing a buffer (%s)", strerror(bufIdx)); 492 return bufIdx; 493 } 494 495 // below we make sure we AT LEAST have the usage flags we want 496 const uint32_t usage(getUsage()); 497 const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); 498 if (backBuffer == 0 || 499 ((uint32_t(backBuffer->usage) & usage) != usage) || 500 mSharedBufferClient->needNewBuffer(bufIdx)) 501 { 502 err = getBufferLocked(bufIdx, usage); 503 LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)", 504 bufIdx, usage, strerror(-err)); 505 if (err == NO_ERROR) { 506 // reset the width/height with the what we get from the buffer 507 mWidth = uint32_t(backBuffer->width); 508 mHeight = uint32_t(backBuffer->height); 509 } 510 } 511 512 // if we still don't have a buffer here, we probably ran out of memory 513 if (!err && backBuffer==0) { 514 err = NO_MEMORY; 515 } 516 517 if (err == NO_ERROR) { 518 mDirtyRegion.set(backBuffer->width, backBuffer->height); 519 *buffer = backBuffer.get(); 520 } else { 521 mSharedBufferClient->undoDequeue(bufIdx); 522 } 523 524 return err; 525 } 526 527 int Surface::lockBuffer(android_native_buffer_t* buffer) 528 { 529 sp<SurfaceComposerClient> client(getClient()); 530 status_t err = validate(); 531 if (err != NO_ERROR) 532 return err; 533 534 int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); 535 err = mSharedBufferClient->lock(bufIdx); 536 LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); 537 return err; 538 } 539 540 int Surface::queueBuffer(android_native_buffer_t* buffer) 541 { 542 sp<SurfaceComposerClient> client(getClient()); 543 status_t err = validate(); 544 if (err != NO_ERROR) 545 return err; 546 547 if (mSwapRectangle.isValid()) { 548 mDirtyRegion.set(mSwapRectangle); 549 } 550 551 int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); 552 mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); 553 err = mSharedBufferClient->queue(bufIdx); 554 LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err)); 555 556 if (err == NO_ERROR) { 557 // FIXME: can we avoid this IPC if we know there is one pending? 558 client->signalServer(); 559 } 560 return err; 561 } 562 563 int Surface::query(int what, int* value) 564 { 565 switch (what) { 566 case NATIVE_WINDOW_WIDTH: 567 *value = int(mWidth); 568 return NO_ERROR; 569 case NATIVE_WINDOW_HEIGHT: 570 *value = int(mHeight); 571 return NO_ERROR; 572 case NATIVE_WINDOW_FORMAT: 573 *value = int(mFormat); 574 return NO_ERROR; 575 } 576 return BAD_VALUE; 577 } 578 579 int Surface::perform(int operation, va_list args) 580 { 581 int res = NO_ERROR; 582 switch (operation) { 583 case NATIVE_WINDOW_SET_USAGE: 584 dispatch_setUsage( args ); 585 break; 586 case NATIVE_WINDOW_CONNECT: 587 res = dispatch_connect( args ); 588 break; 589 case NATIVE_WINDOW_DISCONNECT: 590 res = dispatch_disconnect( args ); 591 break; 592 default: 593 res = NAME_NOT_FOUND; 594 break; 595 } 596 return res; 597 } 598 599 void Surface::dispatch_setUsage(va_list args) { 600 int usage = va_arg(args, int); 601 setUsage( usage ); 602 } 603 int Surface::dispatch_connect(va_list args) { 604 int api = va_arg(args, int); 605 return connect( api ); 606 } 607 int Surface::dispatch_disconnect(va_list args) { 608 int api = va_arg(args, int); 609 return disconnect( api ); 610 } 611 612 613 void Surface::setUsage(uint32_t reqUsage) 614 { 615 Mutex::Autolock _l(mSurfaceLock); 616 mUsage = reqUsage; 617 } 618 619 int Surface::connect(int api) 620 { 621 Mutex::Autolock _l(mSurfaceLock); 622 int err = NO_ERROR; 623 switch (api) { 624 case NATIVE_WINDOW_API_EGL: 625 if (mConnected) { 626 err = -EINVAL; 627 } else { 628 mConnected = api; 629 } 630 break; 631 default: 632 err = -EINVAL; 633 break; 634 } 635 return err; 636 } 637 638 int Surface::disconnect(int api) 639 { 640 Mutex::Autolock _l(mSurfaceLock); 641 int err = NO_ERROR; 642 switch (api) { 643 case NATIVE_WINDOW_API_EGL: 644 if (mConnected == api) { 645 mConnected = 0; 646 } else { 647 err = -EINVAL; 648 } 649 break; 650 default: 651 err = -EINVAL; 652 break; 653 } 654 return err; 655 } 656 657 uint32_t Surface::getUsage() const 658 { 659 Mutex::Autolock _l(mSurfaceLock); 660 return mUsage; 661 } 662 663 int Surface::getConnectedApi() const 664 { 665 Mutex::Autolock _l(mSurfaceLock); 666 return mConnected; 667 } 668 669 670 // ---------------------------------------------------------------------------- 671 672 status_t Surface::lock(SurfaceInfo* info, bool blocking) { 673 return Surface::lock(info, NULL, blocking); 674 } 675 676 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 677 { 678 if (getConnectedApi()) { 679 LOGE("Surface::lock(%p) failed. Already connected to another API", 680 (android_native_window_t*)this); 681 CallStack stack; 682 stack.update(); 683 stack.dump(""); 684 return INVALID_OPERATION; 685 } 686 687 if (mApiLock.tryLock() != NO_ERROR) { 688 LOGE("calling Surface::lock from different threads!"); 689 CallStack stack; 690 stack.update(); 691 stack.dump(""); 692 return WOULD_BLOCK; 693 } 694 695 /* Here we're holding mApiLock */ 696 697 if (mLockedBuffer != 0) { 698 LOGE("Surface::lock failed, already locked"); 699 mApiLock.unlock(); 700 return INVALID_OPERATION; 701 } 702 703 // we're intending to do software rendering from this point 704 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 705 706 sp<GraphicBuffer> backBuffer; 707 status_t err = dequeueBuffer(&backBuffer); 708 LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); 709 if (err == NO_ERROR) { 710 err = lockBuffer(backBuffer.get()); 711 LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", 712 backBuffer->getIndex(), strerror(-err)); 713 if (err == NO_ERROR) { 714 // we handle copy-back here... 715 716 const Rect bounds(backBuffer->width, backBuffer->height); 717 Region scratch(bounds); 718 Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); 719 720 if (mNeedFullUpdate) { 721 // reset newDirtyRegion to bounds when a buffer is reallocated 722 // it would be better if this information was associated with 723 // the buffer and made available to outside of Surface. 724 // This will do for now though. 725 mNeedFullUpdate = false; 726 newDirtyRegion.set(bounds); 727 } else { 728 newDirtyRegion.andSelf(bounds); 729 } 730 731 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); 732 if (frontBuffer !=0 && 733 backBuffer->width == frontBuffer->width && 734 backBuffer->height == frontBuffer->height && 735 !(mFlags & ISurfaceComposer::eDestroyBackbuffer)) 736 { 737 const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); 738 if (!copyback.isEmpty() && frontBuffer!=0) { 739 // copy front to back 740 copyBlt(backBuffer, frontBuffer, copyback); 741 } 742 } 743 744 mDirtyRegion = newDirtyRegion; 745 mOldDirtyRegion = newDirtyRegion; 746 747 void* vaddr; 748 status_t res = backBuffer->lock( 749 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 750 newDirtyRegion.bounds(), &vaddr); 751 752 LOGW_IF(res, "failed locking buffer (handle = %p)", 753 backBuffer->handle); 754 755 mLockedBuffer = backBuffer; 756 other->w = backBuffer->width; 757 other->h = backBuffer->height; 758 other->s = backBuffer->stride; 759 other->usage = backBuffer->usage; 760 other->format = backBuffer->format; 761 other->bits = vaddr; 762 } 763 } 764 mApiLock.unlock(); 765 return err; 766 } 767 768 status_t Surface::unlockAndPost() 769 { 770 if (mLockedBuffer == 0) { 771 LOGE("Surface::unlockAndPost failed, no locked buffer"); 772 return INVALID_OPERATION; 773 } 774 775 status_t err = mLockedBuffer->unlock(); 776 LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); 777 778 err = queueBuffer(mLockedBuffer.get()); 779 LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)", 780 mLockedBuffer->getIndex(), strerror(-err)); 781 782 mPostedBuffer = mLockedBuffer; 783 mLockedBuffer = 0; 784 return err; 785 } 786 787 void Surface::setSwapRectangle(const Rect& r) { 788 Mutex::Autolock _l(mSurfaceLock); 789 mSwapRectangle = r; 790 } 791 792 status_t Surface::getBufferLocked(int index, int usage) 793 { 794 sp<ISurface> s(mSurface); 795 if (s == 0) return NO_INIT; 796 797 status_t err = NO_MEMORY; 798 799 // free the current buffer 800 sp<GraphicBuffer>& currentBuffer(mBuffers[index]); 801 if (currentBuffer != 0) { 802 getBufferMapper().unregisterBuffer(currentBuffer->handle); 803 currentBuffer.clear(); 804 } 805 806 sp<GraphicBuffer> buffer = s->requestBuffer(index, usage); 807 LOGE_IF(buffer==0, 808 "ISurface::getBuffer(%d, %08x) returned NULL", 809 index, usage); 810 if (buffer != 0) { // this should never happen by construction 811 LOGE_IF(buffer->handle == NULL, 812 "Surface (identity=%d) requestBuffer(%d, %08x) returned" 813 "a buffer with a null handle", mIdentity, index, usage); 814 err = mSharedBufferClient->getStatus(); 815 LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err); 816 if (!err && buffer->handle != NULL) { 817 err = getBufferMapper().registerBuffer(buffer->handle); 818 LOGW_IF(err, "registerBuffer(...) failed %d (%s)", 819 err, strerror(-err)); 820 if (err == NO_ERROR) { 821 currentBuffer = buffer; 822 currentBuffer->setIndex(index); 823 mNeedFullUpdate = true; 824 } 825 } else { 826 err = err<0 ? err : NO_MEMORY; 827 } 828 } 829 return err; 830 } 831 832 }; // namespace android 833 834