Surface.cpp revision 1e7fa9e945d98eab76ff92f37c25040429a6c0a0
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 <errno.h> 21#include <sys/types.h> 22#include <sys/stat.h> 23 24#include <utils/CallStack.h> 25#include <utils/Errors.h> 26#include <utils/Log.h> 27#include <utils/threads.h> 28 29#include <binder/IMemory.h> 30#include <binder/IPCThreadState.h> 31 32#include <gui/SurfaceTextureClient.h> 33 34#include <ui/DisplayInfo.h> 35#include <ui/GraphicBuffer.h> 36#include <ui/GraphicBufferMapper.h> 37#include <ui/GraphicLog.h> 38#include <ui/Rect.h> 39 40#include <surfaceflinger/ISurface.h> 41#include <surfaceflinger/ISurfaceComposer.h> 42#include <surfaceflinger/Surface.h> 43#include <surfaceflinger/SurfaceComposerClient.h> 44 45#include <private/surfaceflinger/LayerState.h> 46 47namespace android { 48 49// ---------------------------------------------------------------------- 50 51static status_t copyBlt( 52 const sp<GraphicBuffer>& dst, 53 const sp<GraphicBuffer>& src, 54 const Region& reg) 55{ 56 // src and dst with, height and format must be identical. no verification 57 // is done here. 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 const size_t bpp = bytesPerPixel(src->format); 71 const size_t dbpr = dst->stride * bpp; 72 const size_t sbpr = src->stride * bpp; 73 74 while (head != tail) { 75 const Rect& r(*head++); 76 ssize_t h = r.height(); 77 if (h <= 0) continue; 78 size_t size = r.width() * bpp; 79 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; 80 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; 81 if (dbpr==sbpr && size==sbpr) { 82 size *= h; 83 h = 1; 84 } 85 do { 86 memcpy(d, s, size); 87 d += dbpr; 88 s += sbpr; 89 } while (--h > 0); 90 } 91 } 92 93 if (src_bits) 94 src->unlock(); 95 96 if (dst_bits) 97 dst->unlock(); 98 99 return err; 100} 101 102// ============================================================================ 103// SurfaceControl 104// ============================================================================ 105 106SurfaceControl::SurfaceControl( 107 const sp<SurfaceComposerClient>& client, 108 const sp<ISurface>& surface, 109 const ISurfaceComposerClient::surface_data_t& data, 110 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) 111 : mClient(client), mSurface(surface), 112 mToken(data.token), mIdentity(data.identity), 113 mWidth(data.width), mHeight(data.height), mFormat(data.format), 114 mFlags(flags) 115{ 116} 117 118SurfaceControl::~SurfaceControl() 119{ 120 destroy(); 121} 122 123void SurfaceControl::destroy() 124{ 125 if (isValid()) { 126 mClient->destroySurface(mToken); 127 } 128 129 // clear all references and trigger an IPC now, to make sure things 130 // happen without delay, since these resources are quite heavy. 131 mClient.clear(); 132 mSurface.clear(); 133 IPCThreadState::self()->flushCommands(); 134} 135 136void SurfaceControl::clear() 137{ 138 // here, the window manager tells us explicitly that we should destroy 139 // the surface's resource. Soon after this call, it will also release 140 // its last reference (which will call the dtor); however, it is possible 141 // that a client living in the same process still holds references which 142 // would delay the call to the dtor -- that is why we need this explicit 143 // "clear()" call. 144 destroy(); 145} 146 147bool SurfaceControl::isSameSurface( 148 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) 149{ 150 if (lhs == 0 || rhs == 0) 151 return false; 152 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); 153} 154 155status_t SurfaceControl::setLayer(int32_t layer) { 156 status_t err = validate(); 157 if (err < 0) return err; 158 const sp<SurfaceComposerClient>& client(mClient); 159 return client->setLayer(mToken, layer); 160} 161status_t SurfaceControl::setPosition(int32_t x, int32_t y) { 162 status_t err = validate(); 163 if (err < 0) return err; 164 const sp<SurfaceComposerClient>& client(mClient); 165 return client->setPosition(mToken, x, y); 166} 167status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { 168 status_t err = validate(); 169 if (err < 0) return err; 170 const sp<SurfaceComposerClient>& client(mClient); 171 return client->setSize(mToken, w, h); 172} 173status_t SurfaceControl::hide() { 174 status_t err = validate(); 175 if (err < 0) return err; 176 const sp<SurfaceComposerClient>& client(mClient); 177 return client->hide(mToken); 178} 179status_t SurfaceControl::show(int32_t layer) { 180 status_t err = validate(); 181 if (err < 0) return err; 182 const sp<SurfaceComposerClient>& client(mClient); 183 return client->show(mToken, layer); 184} 185status_t SurfaceControl::freeze() { 186 status_t err = validate(); 187 if (err < 0) return err; 188 const sp<SurfaceComposerClient>& client(mClient); 189 return client->freeze(mToken); 190} 191status_t SurfaceControl::unfreeze() { 192 status_t err = validate(); 193 if (err < 0) return err; 194 const sp<SurfaceComposerClient>& client(mClient); 195 return client->unfreeze(mToken); 196} 197status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { 198 status_t err = validate(); 199 if (err < 0) return err; 200 const sp<SurfaceComposerClient>& client(mClient); 201 return client->setFlags(mToken, flags, mask); 202} 203status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { 204 status_t err = validate(); 205 if (err < 0) return err; 206 const sp<SurfaceComposerClient>& client(mClient); 207 return client->setTransparentRegionHint(mToken, transparent); 208} 209status_t SurfaceControl::setAlpha(float alpha) { 210 status_t err = validate(); 211 if (err < 0) return err; 212 const sp<SurfaceComposerClient>& client(mClient); 213 return client->setAlpha(mToken, alpha); 214} 215status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 216 status_t err = validate(); 217 if (err < 0) return err; 218 const sp<SurfaceComposerClient>& client(mClient); 219 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); 220} 221status_t SurfaceControl::setFreezeTint(uint32_t tint) { 222 status_t err = validate(); 223 if (err < 0) return err; 224 const sp<SurfaceComposerClient>& client(mClient); 225 return client->setFreezeTint(mToken, tint); 226} 227 228status_t SurfaceControl::validate() const 229{ 230 if (mToken<0 || mClient==0) { 231 LOGE("invalid token (%d, identity=%u) or client (%p)", 232 mToken, mIdentity, mClient.get()); 233 return NO_INIT; 234 } 235 return NO_ERROR; 236} 237 238status_t SurfaceControl::writeSurfaceToParcel( 239 const sp<SurfaceControl>& control, Parcel* parcel) 240{ 241 sp<ISurface> sur; 242 uint32_t identity = 0; 243 uint32_t width = 0; 244 uint32_t height = 0; 245 uint32_t format = 0; 246 uint32_t flags = 0; 247 if (SurfaceControl::isValid(control)) { 248 sur = control->mSurface; 249 identity = control->mIdentity; 250 width = control->mWidth; 251 height = control->mHeight; 252 format = control->mFormat; 253 flags = control->mFlags; 254 } 255 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); 256 parcel->writeInt32(identity); 257 parcel->writeInt32(width); 258 parcel->writeInt32(height); 259 parcel->writeInt32(format); 260 parcel->writeInt32(flags); 261 return NO_ERROR; 262} 263 264sp<Surface> SurfaceControl::getSurface() const 265{ 266 Mutex::Autolock _l(mLock); 267 if (mSurfaceData == 0) { 268 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); 269 } 270 return mSurfaceData; 271} 272 273// ============================================================================ 274// Surface 275// ============================================================================ 276 277// --------------------------------------------------------------------------- 278 279Surface::Surface(const sp<SurfaceControl>& surface) 280 : mInitCheck(NO_INIT), 281 mSurface(surface->mSurface), 282 mIdentity(surface->mIdentity), 283 mFormat(surface->mFormat), mFlags(surface->mFlags), 284 mWidth(surface->mWidth), mHeight(surface->mHeight) 285{ 286 init(); 287} 288 289Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) 290 : mInitCheck(NO_INIT) 291{ 292 mSurface = interface_cast<ISurface>(ref); 293 mIdentity = parcel.readInt32(); 294 mWidth = parcel.readInt32(); 295 mHeight = parcel.readInt32(); 296 mFormat = parcel.readInt32(); 297 mFlags = parcel.readInt32(); 298 init(); 299} 300 301status_t Surface::writeToParcel( 302 const sp<Surface>& surface, Parcel* parcel) 303{ 304 sp<ISurface> sur; 305 uint32_t identity = 0; 306 uint32_t width = 0; 307 uint32_t height = 0; 308 uint32_t format = 0; 309 uint32_t flags = 0; 310 if (Surface::isValid(surface)) { 311 sur = surface->mSurface; 312 identity = surface->mIdentity; 313 width = surface->mWidth; 314 height = surface->mHeight; 315 format = surface->mFormat; 316 flags = surface->mFlags; 317 } else if (surface != 0 && surface->mSurface != 0) { 318 LOGW("Parceling invalid surface with non-NULL ISurface as NULL: " 319 "mSurface = %p, mIdentity = %d, mWidth = %d, mHeight = %d, " 320 "mFormat = %d, mFlags = 0x%08x, mInitCheck = %d", 321 surface->mSurface.get(), surface->mIdentity, surface->mWidth, 322 surface->mHeight, surface->mFormat, surface->mFlags, 323 surface->mInitCheck); 324 } 325 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); 326 parcel->writeInt32(identity); 327 parcel->writeInt32(width); 328 parcel->writeInt32(height); 329 parcel->writeInt32(format); 330 parcel->writeInt32(flags); 331 return NO_ERROR; 332 333} 334 335Mutex Surface::sCachedSurfacesLock; 336DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces; 337 338sp<Surface> Surface::readFromParcel(const Parcel& data) { 339 Mutex::Autolock _l(sCachedSurfacesLock); 340 sp<IBinder> binder(data.readStrongBinder()); 341 sp<Surface> surface = sCachedSurfaces.valueFor(binder).promote(); 342 if (surface == 0) { 343 surface = new Surface(data, binder); 344 sCachedSurfaces.add(binder, surface); 345 } 346 if (surface->mSurface == 0) { 347 surface = 0; 348 } 349 cleanCachedSurfacesLocked(); 350 return surface; 351} 352 353// Remove the stale entries from the surface cache. This should only be called 354// with sCachedSurfacesLock held. 355void Surface::cleanCachedSurfacesLocked() { 356 for (int i = sCachedSurfaces.size()-1; i >= 0; --i) { 357 wp<Surface> s(sCachedSurfaces.valueAt(i)); 358 if (s == 0 || s.promote() == 0) { 359 sCachedSurfaces.removeItemsAt(i); 360 } 361 } 362} 363 364void Surface::init() 365{ 366 ANativeWindow::setSwapInterval = setSwapInterval; 367 ANativeWindow::dequeueBuffer = dequeueBuffer; 368 ANativeWindow::cancelBuffer = cancelBuffer; 369 ANativeWindow::lockBuffer = lockBuffer; 370 ANativeWindow::queueBuffer = queueBuffer; 371 ANativeWindow::query = query; 372 ANativeWindow::perform = perform; 373 374 if (mSurface != NULL) { 375 sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture()); 376 LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); 377 if (surfaceTexture != NULL) { 378 mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture); 379 mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER); 380 } 381 382 DisplayInfo dinfo; 383 SurfaceComposerClient::getDisplayInfo(0, &dinfo); 384 const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi; 385 const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi; 386 387 const_cast<int&>(ANativeWindow::minSwapInterval) = 388 mSurfaceTextureClient->minSwapInterval; 389 390 const_cast<int&>(ANativeWindow::maxSwapInterval) = 391 mSurfaceTextureClient->maxSwapInterval; 392 393 const_cast<uint32_t&>(ANativeWindow::flags) = 0; 394 395 if (mSurfaceTextureClient != 0) { 396 mInitCheck = NO_ERROR; 397 } 398 } 399} 400 401Surface::~Surface() 402{ 403 // clear all references and trigger an IPC now, to make sure things 404 // happen without delay, since these resources are quite heavy. 405 mSurfaceTextureClient.clear(); 406 mSurface.clear(); 407 IPCThreadState::self()->flushCommands(); 408} 409 410bool Surface::isValid() { 411 return mInitCheck == NO_ERROR; 412} 413 414status_t Surface::validate(bool inCancelBuffer) const 415{ 416 // check that we initialized ourself properly 417 if (mInitCheck != NO_ERROR) { 418 LOGE("invalid token (identity=%u)", mIdentity); 419 return mInitCheck; 420 } 421 return NO_ERROR; 422} 423 424sp<ISurfaceTexture> Surface::getSurfaceTexture() { 425 return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL; 426} 427 428sp<IBinder> Surface::asBinder() const { 429 return mSurface!=0 ? mSurface->asBinder() : 0; 430} 431 432// ---------------------------------------------------------------------------- 433 434int Surface::setSwapInterval(ANativeWindow* window, int interval) { 435 Surface* self = getSelf(window); 436 return self->setSwapInterval(interval); 437} 438 439int Surface::dequeueBuffer(ANativeWindow* window, 440 ANativeWindowBuffer** buffer) { 441 Surface* self = getSelf(window); 442 return self->dequeueBuffer(buffer); 443} 444 445int Surface::cancelBuffer(ANativeWindow* window, 446 ANativeWindowBuffer* buffer) { 447 Surface* self = getSelf(window); 448 return self->cancelBuffer(buffer); 449} 450 451int Surface::lockBuffer(ANativeWindow* window, 452 ANativeWindowBuffer* buffer) { 453 Surface* self = getSelf(window); 454 return self->lockBuffer(buffer); 455} 456 457int Surface::queueBuffer(ANativeWindow* window, 458 ANativeWindowBuffer* buffer) { 459 Surface* self = getSelf(window); 460 return self->queueBuffer(buffer); 461} 462 463int Surface::query(const ANativeWindow* window, 464 int what, int* value) { 465 const Surface* self = getSelf(window); 466 return self->query(what, value); 467} 468 469int Surface::perform(ANativeWindow* window, 470 int operation, ...) { 471 va_list args; 472 va_start(args, operation); 473 Surface* self = getSelf(window); 474 int res = self->perform(operation, args); 475 va_end(args); 476 return res; 477} 478 479// ---------------------------------------------------------------------------- 480 481int Surface::setSwapInterval(int interval) { 482 return mSurfaceTextureClient->setSwapInterval(interval); 483} 484 485int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) { 486 status_t err = mSurfaceTextureClient->dequeueBuffer(buffer); 487 if (err == NO_ERROR) { 488 mDirtyRegion.set(buffer[0]->width, buffer[0]->height); 489 } 490 return err; 491} 492 493int Surface::cancelBuffer(ANativeWindowBuffer* buffer) { 494 return mSurfaceTextureClient->cancelBuffer(buffer); 495} 496 497int Surface::lockBuffer(ANativeWindowBuffer* buffer) { 498 return mSurfaceTextureClient->lockBuffer(buffer); 499} 500 501int Surface::queueBuffer(ANativeWindowBuffer* buffer) { 502 return mSurfaceTextureClient->queueBuffer(buffer); 503} 504 505int Surface::query(int what, int* value) const { 506 switch (what) { 507 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 508 // TODO: this is not needed anymore 509 *value = 1; 510 return NO_ERROR; 511 case NATIVE_WINDOW_CONCRETE_TYPE: 512 // TODO: this is not needed anymore 513 *value = NATIVE_WINDOW_SURFACE; 514 return NO_ERROR; 515 } 516 return mSurfaceTextureClient->query(what, value); 517} 518 519int Surface::perform(int operation, va_list args) { 520 return mSurfaceTextureClient->perform(operation, args); 521} 522 523// ---------------------------------------------------------------------------- 524 525int Surface::getConnectedApi() const { 526 return mSurfaceTextureClient->getConnectedApi(); 527} 528 529// ---------------------------------------------------------------------------- 530 531status_t Surface::lock(SurfaceInfo* info, bool blocking) { 532 return Surface::lock(info, NULL, blocking); 533} 534 535status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 536{ 537 if (getConnectedApi()) { 538 LOGE("Surface::lock(%p) failed. Already connected to another API", 539 (ANativeWindow*)this); 540 CallStack stack; 541 stack.update(); 542 stack.dump(""); 543 return INVALID_OPERATION; 544 } 545 546 if (mApiLock.tryLock() != NO_ERROR) { 547 LOGE("calling Surface::lock from different threads!"); 548 CallStack stack; 549 stack.update(); 550 stack.dump(""); 551 return WOULD_BLOCK; 552 } 553 554 /* Here we're holding mApiLock */ 555 556 if (mLockedBuffer != 0) { 557 LOGE("Surface::lock failed, already locked"); 558 mApiLock.unlock(); 559 return INVALID_OPERATION; 560 } 561 562 // we're intending to do software rendering from this point 563 mSurfaceTextureClient->setUsage( 564 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 565 566 ANativeWindowBuffer* out; 567 status_t err = mSurfaceTextureClient->dequeueBuffer(&out); 568 LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); 569 if (err == NO_ERROR) { 570 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); 571 err = mSurfaceTextureClient->lockBuffer(backBuffer.get()); 572 LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", 573 backBuffer->handle, strerror(-err)); 574 if (err == NO_ERROR) { 575 const Rect bounds(backBuffer->width, backBuffer->height); 576 const Region boundsRegion(bounds); 577 Region scratch(boundsRegion); 578 Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); 579 newDirtyRegion &= boundsRegion; 580 581 // figure out if we can copy the frontbuffer back 582 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); 583 const bool canCopyBack = (frontBuffer != 0 && 584 backBuffer->width == frontBuffer->width && 585 backBuffer->height == frontBuffer->height && 586 backBuffer->format == frontBuffer->format && 587 !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); 588 589 // the dirty region we report to surfaceflinger is the one 590 // given by the user (as opposed to the one *we* return to the 591 // user). 592 mDirtyRegion = newDirtyRegion; 593 594 if (canCopyBack) { 595 // copy the area that is invalid and not repainted this round 596 const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); 597 if (!copyback.isEmpty()) 598 copyBlt(backBuffer, frontBuffer, copyback); 599 } else { 600 // if we can't copy-back anything, modify the user's dirty 601 // region to make sure they redraw the whole buffer 602 newDirtyRegion = boundsRegion; 603 } 604 605 // keep track of the are of the buffer that is "clean" 606 // (ie: that will be redrawn) 607 mOldDirtyRegion = newDirtyRegion; 608 609 void* vaddr; 610 status_t res = backBuffer->lock( 611 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 612 newDirtyRegion.bounds(), &vaddr); 613 614 LOGW_IF(res, "failed locking buffer (handle = %p)", 615 backBuffer->handle); 616 617 mLockedBuffer = backBuffer; 618 other->w = backBuffer->width; 619 other->h = backBuffer->height; 620 other->s = backBuffer->stride; 621 other->usage = backBuffer->usage; 622 other->format = backBuffer->format; 623 other->bits = vaddr; 624 } 625 } 626 mApiLock.unlock(); 627 return err; 628} 629 630status_t Surface::unlockAndPost() 631{ 632 if (mLockedBuffer == 0) { 633 LOGE("Surface::unlockAndPost failed, no locked buffer"); 634 return INVALID_OPERATION; 635 } 636 637 status_t err = mLockedBuffer->unlock(); 638 LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); 639 640 err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get()); 641 LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", 642 mLockedBuffer->handle, strerror(-err)); 643 644 mPostedBuffer = mLockedBuffer; 645 mLockedBuffer = 0; 646 return err; 647} 648 649// ---------------------------------------------------------------------------- 650}; // namespace android 651