Surface.cpp revision a0c30e924193da57723fd53b710ce6be24fb26f5
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/Errors.h> 25#include <utils/threads.h> 26#include <utils/CallStack.h> 27#include <utils/Log.h> 28 29#include <binder/IPCThreadState.h> 30#include <binder/IMemory.h> 31 32#include <ui/DisplayInfo.h> 33#include <ui/GraphicBuffer.h> 34#include <ui/GraphicBufferMapper.h> 35#include <ui/Rect.h> 36 37#include <surfaceflinger/Surface.h> 38#include <surfaceflinger/ISurface.h> 39#include <surfaceflinger/ISurfaceComposer.h> 40#include <surfaceflinger/SurfaceComposerClient.h> 41 42#include <private/surfaceflinger/SharedBufferStack.h> 43#include <private/surfaceflinger/LayerState.h> 44 45namespace android { 46 47// ---------------------------------------------------------------------- 48 49static status_t copyBlt( 50 const sp<GraphicBuffer>& dst, 51 const sp<GraphicBuffer>& src, 52 const Region& reg) 53{ 54 // src and dst with, height and format must be identical. no verification 55 // is done here. 56 status_t err; 57 uint8_t const * src_bits = NULL; 58 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); 59 LOGE_IF(err, "error locking src buffer %s", strerror(-err)); 60 61 uint8_t* dst_bits = NULL; 62 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); 63 LOGE_IF(err, "error locking dst buffer %s", strerror(-err)); 64 65 Region::const_iterator head(reg.begin()); 66 Region::const_iterator tail(reg.end()); 67 if (head != tail && src_bits && dst_bits) { 68 const size_t bpp = bytesPerPixel(src->format); 69 const size_t dbpr = dst->stride * bpp; 70 const size_t sbpr = src->stride * bpp; 71 72 while (head != tail) { 73 const Rect& r(*head++); 74 ssize_t h = r.height(); 75 if (h <= 0) continue; 76 size_t size = r.width() * bpp; 77 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; 78 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; 79 if (dbpr==sbpr && size==sbpr) { 80 size *= h; 81 h = 1; 82 } 83 do { 84 memcpy(d, s, size); 85 d += dbpr; 86 s += sbpr; 87 } while (--h > 0); 88 } 89 } 90 91 if (src_bits) 92 src->unlock(); 93 94 if (dst_bits) 95 dst->unlock(); 96 97 return err; 98} 99 100// ============================================================================ 101// SurfaceControl 102// ============================================================================ 103 104SurfaceControl::SurfaceControl( 105 const sp<SurfaceComposerClient>& client, 106 const sp<ISurface>& surface, 107 const ISurfaceComposerClient::surface_data_t& data, 108 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) 109 : mClient(client), mSurface(surface), 110 mToken(data.token), mIdentity(data.identity), 111 mWidth(data.width), mHeight(data.height), mFormat(data.format), 112 mFlags(flags) 113{ 114} 115 116SurfaceControl::~SurfaceControl() 117{ 118 destroy(); 119} 120 121void SurfaceControl::destroy() 122{ 123 if (isValid()) { 124 mClient->destroySurface(mToken); 125 } 126 127 // clear all references and trigger an IPC now, to make sure things 128 // happen without delay, since these resources are quite heavy. 129 mClient.clear(); 130 mSurface.clear(); 131 IPCThreadState::self()->flushCommands(); 132} 133 134void SurfaceControl::clear() 135{ 136 // here, the window manager tells us explicitly that we should destroy 137 // the surface's resource. Soon after this call, it will also release 138 // its last reference (which will call the dtor); however, it is possible 139 // that a client living in the same process still holds references which 140 // would delay the call to the dtor -- that is why we need this explicit 141 // "clear()" call. 142 destroy(); 143} 144 145bool SurfaceControl::isSameSurface( 146 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) 147{ 148 if (lhs == 0 || rhs == 0) 149 return false; 150 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); 151} 152 153status_t SurfaceControl::setLayer(int32_t layer) { 154 status_t err = validate(); 155 if (err < 0) return err; 156 const sp<SurfaceComposerClient>& client(mClient); 157 return client->setLayer(mToken, layer); 158} 159status_t SurfaceControl::setPosition(int32_t x, int32_t y) { 160 status_t err = validate(); 161 if (err < 0) return err; 162 const sp<SurfaceComposerClient>& client(mClient); 163 return client->setPosition(mToken, x, y); 164} 165status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { 166 status_t err = validate(); 167 if (err < 0) return err; 168 const sp<SurfaceComposerClient>& client(mClient); 169 return client->setSize(mToken, w, h); 170} 171status_t SurfaceControl::hide() { 172 status_t err = validate(); 173 if (err < 0) return err; 174 const sp<SurfaceComposerClient>& client(mClient); 175 return client->hide(mToken); 176} 177status_t SurfaceControl::show(int32_t layer) { 178 status_t err = validate(); 179 if (err < 0) return err; 180 const sp<SurfaceComposerClient>& client(mClient); 181 return client->show(mToken, layer); 182} 183status_t SurfaceControl::freeze() { 184 status_t err = validate(); 185 if (err < 0) return err; 186 const sp<SurfaceComposerClient>& client(mClient); 187 return client->freeze(mToken); 188} 189status_t SurfaceControl::unfreeze() { 190 status_t err = validate(); 191 if (err < 0) return err; 192 const sp<SurfaceComposerClient>& client(mClient); 193 return client->unfreeze(mToken); 194} 195status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { 196 status_t err = validate(); 197 if (err < 0) return err; 198 const sp<SurfaceComposerClient>& client(mClient); 199 return client->setFlags(mToken, flags, mask); 200} 201status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { 202 status_t err = validate(); 203 if (err < 0) return err; 204 const sp<SurfaceComposerClient>& client(mClient); 205 return client->setTransparentRegionHint(mToken, transparent); 206} 207status_t SurfaceControl::setAlpha(float alpha) { 208 status_t err = validate(); 209 if (err < 0) return err; 210 const sp<SurfaceComposerClient>& client(mClient); 211 return client->setAlpha(mToken, alpha); 212} 213status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 214 status_t err = validate(); 215 if (err < 0) return err; 216 const sp<SurfaceComposerClient>& client(mClient); 217 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); 218} 219status_t SurfaceControl::setFreezeTint(uint32_t tint) { 220 status_t err = validate(); 221 if (err < 0) return err; 222 const sp<SurfaceComposerClient>& client(mClient); 223 return client->setFreezeTint(mToken, tint); 224} 225 226status_t SurfaceControl::validate() const 227{ 228 if (mToken<0 || mClient==0) { 229 LOGE("invalid token (%d, identity=%u) or client (%p)", 230 mToken, mIdentity, mClient.get()); 231 return NO_INIT; 232 } 233 return NO_ERROR; 234} 235 236status_t SurfaceControl::writeSurfaceToParcel( 237 const sp<SurfaceControl>& control, Parcel* parcel) 238{ 239 uint32_t flags = 0; 240 uint32_t format = 0; 241 uint32_t identity = 0; 242 uint32_t width = 0; 243 uint32_t height = 0; 244 sp<SurfaceComposerClient> client; 245 sp<ISurface> sur; 246 if (SurfaceControl::isValid(control)) { 247 identity = control->mIdentity; 248 client = control->mClient; 249 sur = control->mSurface; 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 277class SurfaceClient : public Singleton<SurfaceClient> 278{ 279 // all these attributes are constants 280 sp<ISurfaceComposer> mComposerService; 281 sp<ISurfaceComposerClient> mClient; 282 status_t mStatus; 283 SharedClient* mControl; 284 sp<IMemoryHeap> mControlMemory; 285 286 SurfaceClient() 287 : Singleton<SurfaceClient>(), mStatus(NO_INIT) 288 { 289 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); 290 mComposerService = sf; 291 mClient = sf->createClientConnection(); 292 if (mClient != NULL) { 293 mControlMemory = mClient->getControlBlock(); 294 if (mControlMemory != NULL) { 295 mControl = static_cast<SharedClient *>( 296 mControlMemory->getBase()); 297 if (mControl) { 298 mStatus = NO_ERROR; 299 } 300 } 301 } 302 } 303 friend class Singleton<SurfaceClient>; 304public: 305 status_t initCheck() const { 306 return mStatus; 307 } 308 SharedClient* getSharedClient() const { 309 return mControl; 310 } 311 ssize_t getTokenForSurface(const sp<ISurface>& sur) const { 312 // TODO: we could cache a few tokens here to avoid an IPC 313 return mClient->getTokenForSurface(sur); 314 } 315 void signalServer() const { 316 mComposerService->signal(); 317 } 318}; 319 320ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient); 321 322// --------------------------------------------------------------------------- 323 324Surface::Surface(const sp<SurfaceControl>& surface) 325 : mBufferMapper(GraphicBufferMapper::get()), 326 mClient(SurfaceClient::getInstance()), 327 mSharedBufferClient(NULL), 328 mInitCheck(NO_INIT), 329 mSurface(surface->mSurface), 330 mIdentity(surface->mIdentity), 331 mFormat(surface->mFormat), mFlags(surface->mFlags), 332 mWidth(surface->mWidth), mHeight(surface->mHeight) 333{ 334 init(); 335} 336 337Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) 338 : mBufferMapper(GraphicBufferMapper::get()), 339 mClient(SurfaceClient::getInstance()), 340 mSharedBufferClient(NULL), 341 mInitCheck(NO_INIT) 342{ 343 mSurface = interface_cast<ISurface>(ref); 344 mIdentity = parcel.readInt32(); 345 mWidth = parcel.readInt32(); 346 mHeight = parcel.readInt32(); 347 mFormat = parcel.readInt32(); 348 mFlags = parcel.readInt32(); 349 init(); 350} 351 352sp<Surface> Surface::readFromParcel( 353 const Parcel& data, const sp<Surface>& other) 354{ 355 sp<Surface> result(other); 356 sp<IBinder> binder(data.readStrongBinder()); 357 if (other==0 || binder != other->mSurface->asBinder()) { 358 result = new Surface(data, binder); 359 } 360 return result; 361} 362 363void Surface::init() 364{ 365 android_native_window_t::setSwapInterval = setSwapInterval; 366 android_native_window_t::dequeueBuffer = dequeueBuffer; 367 android_native_window_t::lockBuffer = lockBuffer; 368 android_native_window_t::queueBuffer = queueBuffer; 369 android_native_window_t::query = query; 370 android_native_window_t::perform = perform; 371 372 DisplayInfo dinfo; 373 SurfaceComposerClient::getDisplayInfo(0, &dinfo); 374 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi; 375 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi; 376 // FIXME: set real values here 377 const_cast<int&>(android_native_window_t::minSwapInterval) = 1; 378 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1; 379 const_cast<uint32_t&>(android_native_window_t::flags) = 0; 380 381 mConnected = 0; 382 mSwapRectangle.makeInvalid(); 383 // two buffers by default 384 mBuffers.setCapacity(2); 385 mBuffers.insertAt(0, 2); 386 387 if (mSurface != 0 && mClient.initCheck() == NO_ERROR) { 388 mToken = mClient.getTokenForSurface(mSurface); 389 if (mToken >= 0) { 390 mSharedBufferClient = new SharedBufferClient( 391 mClient.getSharedClient(), mToken, 2, mIdentity); 392 mInitCheck = mClient.getSharedClient()->validate(mToken); 393 } 394 } 395} 396 397Surface::~Surface() 398{ 399 // this is a client-side operation, the surface is destroyed, unmap 400 // its buffers in this process. 401 size_t size = mBuffers.size(); 402 for (size_t i=0 ; i<size ; i++) { 403 if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) { 404 getBufferMapper().unregisterBuffer(mBuffers[i]->handle); 405 } 406 } 407 408 // clear all references and trigger an IPC now, to make sure things 409 // happen without delay, since these resources are quite heavy. 410 mBuffers.clear(); 411 mSurface.clear(); 412 delete mSharedBufferClient; 413 IPCThreadState::self()->flushCommands(); 414} 415 416bool Surface::isValid() { 417 return mInitCheck == NO_ERROR; 418} 419 420status_t Surface::validate() const 421{ 422 // check that we initialized ourself properly 423 if (mInitCheck != NO_ERROR) { 424 LOGE("invalid token (%d, identity=%u)", mToken, mIdentity); 425 return mInitCheck; 426 } 427 428 // verify the identity of this surface 429 uint32_t identity = mSharedBufferClient->getIdentity(); 430 431 // this is a bit of a (temporary) special case, identity==0 means that 432 // no operation are allowed from the client (eg: dequeue/queue), this 433 // is used with PUSH_BUFFER surfaces for instance 434 if (identity == 0) { 435 LOGE("[Surface] invalid operation (identity=%u)", mIdentity); 436 return INVALID_OPERATION; 437 } 438 439 if (mIdentity != identity) { 440 LOGE("[Surface] using an invalid surface id=%d, " 441 "identity=%u should be %d", 442 mToken, mIdentity, identity); 443 return NO_INIT; 444 } 445 446 // check the surface didn't become invalid 447 status_t err = mSharedBufferClient->getStatus(); 448 if (err != NO_ERROR) { 449 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", 450 mToken, mIdentity, err, strerror(-err)); 451 return err; 452 } 453 454 return NO_ERROR; 455} 456 457sp<ISurface> Surface::getISurface() const { 458 return mSurface; 459} 460 461// ---------------------------------------------------------------------------- 462 463int Surface::setSwapInterval(android_native_window_t* window, int interval) { 464 return 0; 465} 466 467int Surface::dequeueBuffer(android_native_window_t* window, 468 android_native_buffer_t** buffer) { 469 Surface* self = getSelf(window); 470 return self->dequeueBuffer(buffer); 471} 472 473int Surface::lockBuffer(android_native_window_t* window, 474 android_native_buffer_t* buffer) { 475 Surface* self = getSelf(window); 476 return self->lockBuffer(buffer); 477} 478 479int Surface::queueBuffer(android_native_window_t* window, 480 android_native_buffer_t* buffer) { 481 Surface* self = getSelf(window); 482 return self->queueBuffer(buffer); 483} 484 485int Surface::query(android_native_window_t* window, 486 int what, int* value) { 487 Surface* self = getSelf(window); 488 return self->query(what, value); 489} 490 491int Surface::perform(android_native_window_t* window, 492 int operation, ...) { 493 va_list args; 494 va_start(args, operation); 495 Surface* self = getSelf(window); 496 int res = self->perform(operation, args); 497 va_end(args); 498 return res; 499} 500 501// ---------------------------------------------------------------------------- 502 503bool Surface::needNewBuffer(int bufIdx, 504 uint32_t *pWidth, uint32_t *pHeight, 505 uint32_t *pFormat, uint32_t *pUsage) const 506{ 507 Mutex::Autolock _l(mSurfaceLock); 508 509 // Always call needNewBuffer(), since it clears the needed buffers flags 510 bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx); 511 bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]); 512 bool newNeewBuffer = needNewBuffer || !validBuffer; 513 if (newNeewBuffer) { 514 mBufferInfo.get(pWidth, pHeight, pFormat, pUsage); 515 } 516 return newNeewBuffer; 517} 518 519int Surface::dequeueBuffer(android_native_buffer_t** buffer) 520{ 521 status_t err = validate(); 522 if (err != NO_ERROR) 523 return err; 524 525 ssize_t bufIdx = mSharedBufferClient->dequeue(); 526 if (bufIdx < 0) { 527 LOGE("error dequeuing a buffer (%s)", strerror(bufIdx)); 528 return bufIdx; 529 } 530 531 // grow the buffer array if needed 532 const size_t size = mBuffers.size(); 533 const size_t needed = bufIdx+1; 534 if (size < needed) { 535 mBuffers.insertAt(size, needed-size); 536 } 537 538 uint32_t w, h, format, usage; 539 if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) { 540 err = getBufferLocked(bufIdx, w, h, format, usage); 541 LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)", 542 bufIdx, w, h, format, usage, strerror(-err)); 543 if (err == NO_ERROR) { 544 // reset the width/height with the what we get from the buffer 545 const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); 546 mWidth = uint32_t(backBuffer->width); 547 mHeight = uint32_t(backBuffer->height); 548 } 549 } 550 551 // if we still don't have a buffer here, we probably ran out of memory 552 const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); 553 if (!err && backBuffer==0) { 554 err = NO_MEMORY; 555 } 556 557 if (err == NO_ERROR) { 558 mDirtyRegion.set(backBuffer->width, backBuffer->height); 559 *buffer = backBuffer.get(); 560 } else { 561 mSharedBufferClient->undoDequeue(bufIdx); 562 } 563 564 return err; 565} 566 567int Surface::lockBuffer(android_native_buffer_t* buffer) 568{ 569 status_t err = validate(); 570 if (err != NO_ERROR) 571 return err; 572 573 int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); 574 err = mSharedBufferClient->lock(bufIdx); 575 LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); 576 return err; 577} 578 579int Surface::queueBuffer(android_native_buffer_t* buffer) 580{ 581 status_t err = validate(); 582 if (err != NO_ERROR) 583 return err; 584 585 if (mSwapRectangle.isValid()) { 586 mDirtyRegion.set(mSwapRectangle); 587 } 588 589 int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); 590 mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop); 591 mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); 592 err = mSharedBufferClient->queue(bufIdx); 593 LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err)); 594 595 if (err == NO_ERROR) { 596 // TODO: can we avoid this IPC if we know there is one pending? 597 mClient.signalServer(); 598 } 599 return err; 600} 601 602int Surface::query(int what, int* value) 603{ 604 switch (what) { 605 case NATIVE_WINDOW_WIDTH: 606 *value = int(mWidth); 607 return NO_ERROR; 608 case NATIVE_WINDOW_HEIGHT: 609 *value = int(mHeight); 610 return NO_ERROR; 611 case NATIVE_WINDOW_FORMAT: 612 *value = int(mFormat); 613 return NO_ERROR; 614 } 615 return BAD_VALUE; 616} 617 618int Surface::perform(int operation, va_list args) 619{ 620 status_t err = validate(); 621 if (err != NO_ERROR) 622 return err; 623 624 int res = NO_ERROR; 625 switch (operation) { 626 case NATIVE_WINDOW_SET_USAGE: 627 dispatch_setUsage( args ); 628 break; 629 case NATIVE_WINDOW_CONNECT: 630 res = dispatch_connect( args ); 631 break; 632 case NATIVE_WINDOW_DISCONNECT: 633 res = dispatch_disconnect( args ); 634 break; 635 case NATIVE_WINDOW_SET_CROP: 636 res = dispatch_crop( args ); 637 break; 638 case NATIVE_WINDOW_SET_BUFFER_COUNT: 639 res = dispatch_set_buffer_count( args ); 640 break; 641 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 642 res = dispatch_set_buffers_geometry( args ); 643 break; 644 default: 645 res = NAME_NOT_FOUND; 646 break; 647 } 648 return res; 649} 650 651void Surface::dispatch_setUsage(va_list args) { 652 int usage = va_arg(args, int); 653 setUsage( usage ); 654} 655int Surface::dispatch_connect(va_list args) { 656 int api = va_arg(args, int); 657 return connect( api ); 658} 659int Surface::dispatch_disconnect(va_list args) { 660 int api = va_arg(args, int); 661 return disconnect( api ); 662} 663int Surface::dispatch_crop(va_list args) { 664 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); 665 return crop( reinterpret_cast<Rect const*>(rect) ); 666} 667int Surface::dispatch_set_buffer_count(va_list args) { 668 size_t bufferCount = va_arg(args, size_t); 669 return setBufferCount(bufferCount); 670} 671int Surface::dispatch_set_buffers_geometry(va_list args) { 672 int w = va_arg(args, int); 673 int h = va_arg(args, int); 674 int f = va_arg(args, int); 675 return setBuffersGeometry(w, h, f); 676} 677 678void Surface::setUsage(uint32_t reqUsage) 679{ 680 Mutex::Autolock _l(mSurfaceLock); 681 mBufferInfo.set(reqUsage); 682} 683 684int Surface::connect(int api) 685{ 686 Mutex::Autolock _l(mSurfaceLock); 687 int err = NO_ERROR; 688 switch (api) { 689 case NATIVE_WINDOW_API_EGL: 690 if (mConnected) { 691 err = -EINVAL; 692 } else { 693 mConnected = api; 694 } 695 break; 696 default: 697 err = -EINVAL; 698 break; 699 } 700 return err; 701} 702 703int Surface::disconnect(int api) 704{ 705 Mutex::Autolock _l(mSurfaceLock); 706 int err = NO_ERROR; 707 switch (api) { 708 case NATIVE_WINDOW_API_EGL: 709 if (mConnected == api) { 710 mConnected = 0; 711 } else { 712 err = -EINVAL; 713 } 714 break; 715 default: 716 err = -EINVAL; 717 break; 718 } 719 return err; 720} 721 722int Surface::crop(Rect const* rect) 723{ 724 Mutex::Autolock _l(mSurfaceLock); 725 // TODO: validate rect size 726 mNextBufferCrop = *rect; 727 return NO_ERROR; 728} 729 730int Surface::setBufferCount(int bufferCount) 731{ 732 sp<ISurface> s(mSurface); 733 if (s == 0) return NO_INIT; 734 735 class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback { 736 sp<ISurface> surface; 737 virtual status_t operator()(int bufferCount) const { 738 return surface->setBufferCount(bufferCount); 739 } 740 public: 741 SetBufferCountIPC(const sp<ISurface>& surface) : surface(surface) { } 742 } ipc(s); 743 744 status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc); 745 LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s", 746 bufferCount, strerror(-err)); 747 return err; 748} 749 750int Surface::setBuffersGeometry(int w, int h, int format) 751{ 752 if (w<0 || h<0 || format<0) 753 return BAD_VALUE; 754 755 if ((w && !h) || (!w && h)) 756 return BAD_VALUE; 757 758 Mutex::Autolock _l(mSurfaceLock); 759 mBufferInfo.set(w, h, format); 760 return NO_ERROR; 761} 762 763// ---------------------------------------------------------------------------- 764 765int Surface::getConnectedApi() const 766{ 767 Mutex::Autolock _l(mSurfaceLock); 768 return mConnected; 769} 770 771// ---------------------------------------------------------------------------- 772 773status_t Surface::lock(SurfaceInfo* info, bool blocking) { 774 return Surface::lock(info, NULL, blocking); 775} 776 777status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 778{ 779 if (getConnectedApi()) { 780 LOGE("Surface::lock(%p) failed. Already connected to another API", 781 (android_native_window_t*)this); 782 CallStack stack; 783 stack.update(); 784 stack.dump(""); 785 return INVALID_OPERATION; 786 } 787 788 if (mApiLock.tryLock() != NO_ERROR) { 789 LOGE("calling Surface::lock from different threads!"); 790 CallStack stack; 791 stack.update(); 792 stack.dump(""); 793 return WOULD_BLOCK; 794 } 795 796 /* Here we're holding mApiLock */ 797 798 if (mLockedBuffer != 0) { 799 LOGE("Surface::lock failed, already locked"); 800 mApiLock.unlock(); 801 return INVALID_OPERATION; 802 } 803 804 // we're intending to do software rendering from this point 805 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 806 807 android_native_buffer_t* out; 808 status_t err = dequeueBuffer(&out); 809 LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); 810 if (err == NO_ERROR) { 811 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); 812 err = lockBuffer(backBuffer.get()); 813 LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", 814 getBufferIndex(backBuffer), strerror(-err)); 815 if (err == NO_ERROR) { 816 const Rect bounds(backBuffer->width, backBuffer->height); 817 const Region boundsRegion(bounds); 818 Region scratch(boundsRegion); 819 Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); 820 newDirtyRegion &= boundsRegion; 821 822 // figure out if we can copy the frontbuffer back 823 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); 824 const bool canCopyBack = (frontBuffer != 0 && 825 backBuffer->width == frontBuffer->width && 826 backBuffer->height == frontBuffer->height && 827 backBuffer->format == frontBuffer->format && 828 !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); 829 830 // the dirty region we report to surfaceflinger is the one 831 // given by the user (as opposed to the one *we* return to the 832 // user). 833 mDirtyRegion = newDirtyRegion; 834 835 if (canCopyBack) { 836 // copy the area that is invalid and not repainted this round 837 const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); 838 if (!copyback.isEmpty()) 839 copyBlt(backBuffer, frontBuffer, copyback); 840 } else { 841 // if we can't copy-back anything, modify the user's dirty 842 // region to make sure they redraw the whole buffer 843 newDirtyRegion = boundsRegion; 844 } 845 846 // keep track of the are of the buffer that is "clean" 847 // (ie: that will be redrawn) 848 mOldDirtyRegion = newDirtyRegion; 849 850 void* vaddr; 851 status_t res = backBuffer->lock( 852 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 853 newDirtyRegion.bounds(), &vaddr); 854 855 LOGW_IF(res, "failed locking buffer (handle = %p)", 856 backBuffer->handle); 857 858 mLockedBuffer = backBuffer; 859 other->w = backBuffer->width; 860 other->h = backBuffer->height; 861 other->s = backBuffer->stride; 862 other->usage = backBuffer->usage; 863 other->format = backBuffer->format; 864 other->bits = vaddr; 865 } 866 } 867 mApiLock.unlock(); 868 return err; 869} 870 871status_t Surface::unlockAndPost() 872{ 873 if (mLockedBuffer == 0) { 874 LOGE("Surface::unlockAndPost failed, no locked buffer"); 875 return INVALID_OPERATION; 876 } 877 878 status_t err = mLockedBuffer->unlock(); 879 LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); 880 881 err = queueBuffer(mLockedBuffer.get()); 882 LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)", 883 getBufferIndex(mLockedBuffer), strerror(-err)); 884 885 mPostedBuffer = mLockedBuffer; 886 mLockedBuffer = 0; 887 return err; 888} 889 890void Surface::setSwapRectangle(const Rect& r) { 891 Mutex::Autolock _l(mSurfaceLock); 892 mSwapRectangle = r; 893} 894 895int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const 896{ 897 return buffer->getIndex(); 898} 899 900status_t Surface::getBufferLocked(int index, 901 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) 902{ 903 sp<ISurface> s(mSurface); 904 if (s == 0) return NO_INIT; 905 906 status_t err = NO_MEMORY; 907 908 // free the current buffer 909 sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index)); 910 if (currentBuffer != 0) { 911 getBufferMapper().unregisterBuffer(currentBuffer->handle); 912 currentBuffer.clear(); 913 } 914 915 sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage); 916 LOGE_IF(buffer==0, 917 "ISurface::getBuffer(%d, %08x) returned NULL", 918 index, usage); 919 if (buffer != 0) { // this should never happen by construction 920 LOGE_IF(buffer->handle == NULL, 921 "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) " 922 "returned a buffer with a null handle", 923 mIdentity, index, w, h, format, usage); 924 err = mSharedBufferClient->getStatus(); 925 LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err); 926 if (!err && buffer->handle != NULL) { 927 err = getBufferMapper().registerBuffer(buffer->handle); 928 LOGW_IF(err, "registerBuffer(...) failed %d (%s)", 929 err, strerror(-err)); 930 if (err == NO_ERROR) { 931 currentBuffer = buffer; 932 currentBuffer->setIndex(index); 933 } 934 } else { 935 err = err<0 ? err : status_t(NO_MEMORY); 936 } 937 } 938 return err; 939} 940 941// ---------------------------------------------------------------------------- 942Surface::BufferInfo::BufferInfo() 943 : mWidth(0), mHeight(0), mFormat(0), 944 mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0) 945{ 946} 947 948void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) { 949 if ((mWidth != w) || (mHeight != h) || (mFormat != format)) { 950 mWidth = w; 951 mHeight = h; 952 mFormat = format; 953 mDirty |= GEOMETRY; 954 } 955} 956 957void Surface::BufferInfo::set(uint32_t usage) { 958 mUsage = usage; 959} 960 961void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight, 962 uint32_t *pFormat, uint32_t *pUsage) const { 963 *pWidth = mWidth; 964 *pHeight = mHeight; 965 *pFormat = mFormat; 966 *pUsage = mUsage; 967} 968 969bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const { 970 // make sure we AT LEAST have the usage flags we want 971 if (mDirty || buffer==0 || 972 ((buffer->usage & mUsage) != mUsage)) { 973 mDirty = 0; 974 return false; 975 } 976 return true; 977} 978 979// ---------------------------------------------------------------------------- 980}; // namespace android 981 982