Surface.cpp revision 579b3f88d03d06b897b778bd11818f5104677d1d
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 sp<ISurface> sur; 240 uint32_t identity = 0; 241 uint32_t width = 0; 242 uint32_t height = 0; 243 uint32_t format = 0; 244 uint32_t flags = 0; 245 if (SurfaceControl::isValid(control)) { 246 sur = control->mSurface; 247 identity = control->mIdentity; 248 width = control->mWidth; 249 height = control->mHeight; 250 format = control->mFormat; 251 flags = control->mFlags; 252 } 253 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); 254 parcel->writeInt32(identity); 255 parcel->writeInt32(width); 256 parcel->writeInt32(height); 257 parcel->writeInt32(format); 258 parcel->writeInt32(flags); 259 return NO_ERROR; 260} 261 262sp<Surface> SurfaceControl::getSurface() const 263{ 264 Mutex::Autolock _l(mLock); 265 if (mSurfaceData == 0) { 266 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); 267 } 268 return mSurfaceData; 269} 270 271// ============================================================================ 272// Surface 273// ============================================================================ 274 275class SurfaceClient : public Singleton<SurfaceClient> 276{ 277 // all these attributes are constants 278 sp<ISurfaceComposer> mComposerService; 279 sp<ISurfaceComposerClient> mClient; 280 status_t mStatus; 281 SharedClient* mControl; 282 sp<IMemoryHeap> mControlMemory; 283 284 SurfaceClient() 285 : Singleton<SurfaceClient>(), mStatus(NO_INIT) 286 { 287 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); 288 mComposerService = sf; 289 mClient = sf->createClientConnection(); 290 if (mClient != NULL) { 291 mControlMemory = mClient->getControlBlock(); 292 if (mControlMemory != NULL) { 293 mControl = static_cast<SharedClient *>( 294 mControlMemory->getBase()); 295 if (mControl) { 296 mStatus = NO_ERROR; 297 } 298 } 299 } 300 } 301 friend class Singleton<SurfaceClient>; 302public: 303 status_t initCheck() const { 304 return mStatus; 305 } 306 SharedClient* getSharedClient() const { 307 return mControl; 308 } 309 ssize_t getTokenForSurface(const sp<ISurface>& sur) const { 310 // TODO: we could cache a few tokens here to avoid an IPC 311 return mClient->getTokenForSurface(sur); 312 } 313 void signalServer() const { 314 mComposerService->signal(); 315 } 316}; 317 318ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient); 319 320// --------------------------------------------------------------------------- 321 322Surface::Surface(const sp<SurfaceControl>& surface) 323 : mBufferMapper(GraphicBufferMapper::get()), 324 mClient(SurfaceClient::getInstance()), 325 mSharedBufferClient(NULL), 326 mInitCheck(NO_INIT), 327 mSurface(surface->mSurface), 328 mIdentity(surface->mIdentity), 329 mFormat(surface->mFormat), mFlags(surface->mFlags), 330 mWidth(surface->mWidth), mHeight(surface->mHeight) 331{ 332 init(); 333} 334 335Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) 336 : mBufferMapper(GraphicBufferMapper::get()), 337 mClient(SurfaceClient::getInstance()), 338 mSharedBufferClient(NULL), 339 mInitCheck(NO_INIT) 340{ 341 mSurface = interface_cast<ISurface>(ref); 342 mIdentity = parcel.readInt32(); 343 mWidth = parcel.readInt32(); 344 mHeight = parcel.readInt32(); 345 mFormat = parcel.readInt32(); 346 mFlags = parcel.readInt32(); 347 init(); 348} 349 350status_t Surface::writeToParcel( 351 const sp<Surface>& surface, Parcel* parcel) 352{ 353 sp<ISurface> sur; 354 uint32_t identity = 0; 355 uint32_t width = 0; 356 uint32_t height = 0; 357 uint32_t format = 0; 358 uint32_t flags = 0; 359 if (Surface::isValid(surface)) { 360 sur = surface->mSurface; 361 identity = surface->mIdentity; 362 width = surface->mWidth; 363 height = surface->mHeight; 364 format = surface->mFormat; 365 flags = surface->mFlags; 366 } 367 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); 368 parcel->writeInt32(identity); 369 parcel->writeInt32(width); 370 parcel->writeInt32(height); 371 parcel->writeInt32(format); 372 parcel->writeInt32(flags); 373 return NO_ERROR; 374 375} 376 377sp<Surface> Surface::readFromParcel( 378 const Parcel& data, const sp<Surface>& other) 379{ 380 sp<Surface> result(other); 381 sp<IBinder> binder(data.readStrongBinder()); 382 if (other==0 || binder != other->mSurface->asBinder()) { 383 result = new Surface(data, binder); 384 } 385 return result; 386} 387 388void Surface::init() 389{ 390 android_native_window_t::setSwapInterval = setSwapInterval; 391 android_native_window_t::dequeueBuffer = dequeueBuffer; 392 android_native_window_t::lockBuffer = lockBuffer; 393 android_native_window_t::queueBuffer = queueBuffer; 394 android_native_window_t::query = query; 395 android_native_window_t::perform = perform; 396 397 DisplayInfo dinfo; 398 SurfaceComposerClient::getDisplayInfo(0, &dinfo); 399 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi; 400 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi; 401 // FIXME: set real values here 402 const_cast<int&>(android_native_window_t::minSwapInterval) = 1; 403 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1; 404 const_cast<uint32_t&>(android_native_window_t::flags) = 0; 405 406 mConnected = 0; 407 mSwapRectangle.makeInvalid(); 408 // two buffers by default 409 mBuffers.setCapacity(2); 410 mBuffers.insertAt(0, 2); 411 412 if (mSurface != 0 && mClient.initCheck() == NO_ERROR) { 413 int32_t token = mClient.getTokenForSurface(mSurface); 414 if (token >= 0) { 415 mSharedBufferClient = new SharedBufferClient( 416 mClient.getSharedClient(), token, 2, mIdentity); 417 mInitCheck = mClient.getSharedClient()->validate(token); 418 } 419 } 420} 421 422Surface::~Surface() 423{ 424 // this is a client-side operation, the surface is destroyed, unmap 425 // its buffers in this process. 426 size_t size = mBuffers.size(); 427 for (size_t i=0 ; i<size ; i++) { 428 if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) { 429 getBufferMapper().unregisterBuffer(mBuffers[i]->handle); 430 } 431 } 432 433 // clear all references and trigger an IPC now, to make sure things 434 // happen without delay, since these resources are quite heavy. 435 mBuffers.clear(); 436 mSurface.clear(); 437 delete mSharedBufferClient; 438 IPCThreadState::self()->flushCommands(); 439} 440 441bool Surface::isValid() { 442 return mInitCheck == NO_ERROR; 443} 444 445status_t Surface::validate() const 446{ 447 // check that we initialized ourself properly 448 if (mInitCheck != NO_ERROR) { 449 LOGE("invalid token (identity=%u)", mIdentity); 450 return mInitCheck; 451 } 452 453 // verify the identity of this surface 454 uint32_t identity = mSharedBufferClient->getIdentity(); 455 456 // this is a bit of a (temporary) special case, identity==0 means that 457 // no operation are allowed from the client (eg: dequeue/queue), this 458 // is used with PUSH_BUFFER surfaces for instance 459 if (identity == 0) { 460 LOGE("[Surface] invalid operation (identity=%u)", mIdentity); 461 return INVALID_OPERATION; 462 } 463 464 if (mIdentity != identity) { 465 LOGE("[Surface] using an invalid surface, " 466 "identity=%u should be %d", 467 mIdentity, identity); 468 return NO_INIT; 469 } 470 471 // check the surface didn't become invalid 472 status_t err = mSharedBufferClient->getStatus(); 473 if (err != NO_ERROR) { 474 LOGE("surface (identity=%u) is invalid, err=%d (%s)", 475 mIdentity, err, strerror(-err)); 476 return err; 477 } 478 479 return NO_ERROR; 480} 481 482sp<ISurface> Surface::getISurface() const { 483 return mSurface; 484} 485 486// ---------------------------------------------------------------------------- 487 488int Surface::setSwapInterval(android_native_window_t* window, int interval) { 489 return 0; 490} 491 492int Surface::dequeueBuffer(android_native_window_t* window, 493 android_native_buffer_t** buffer) { 494 Surface* self = getSelf(window); 495 return self->dequeueBuffer(buffer); 496} 497 498int Surface::lockBuffer(android_native_window_t* window, 499 android_native_buffer_t* buffer) { 500 Surface* self = getSelf(window); 501 return self->lockBuffer(buffer); 502} 503 504int Surface::queueBuffer(android_native_window_t* window, 505 android_native_buffer_t* buffer) { 506 Surface* self = getSelf(window); 507 return self->queueBuffer(buffer); 508} 509 510int Surface::query(android_native_window_t* window, 511 int what, int* value) { 512 Surface* self = getSelf(window); 513 return self->query(what, value); 514} 515 516int Surface::perform(android_native_window_t* window, 517 int operation, ...) { 518 va_list args; 519 va_start(args, operation); 520 Surface* self = getSelf(window); 521 int res = self->perform(operation, args); 522 va_end(args); 523 return res; 524} 525 526// ---------------------------------------------------------------------------- 527 528bool Surface::needNewBuffer(int bufIdx, 529 uint32_t *pWidth, uint32_t *pHeight, 530 uint32_t *pFormat, uint32_t *pUsage) const 531{ 532 Mutex::Autolock _l(mSurfaceLock); 533 534 // Always call needNewBuffer(), since it clears the needed buffers flags 535 bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx); 536 bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]); 537 bool newNeewBuffer = needNewBuffer || !validBuffer; 538 if (newNeewBuffer) { 539 mBufferInfo.get(pWidth, pHeight, pFormat, pUsage); 540 } 541 return newNeewBuffer; 542} 543 544int Surface::dequeueBuffer(android_native_buffer_t** buffer) 545{ 546 status_t err = validate(); 547 if (err != NO_ERROR) 548 return err; 549 550 ssize_t bufIdx = mSharedBufferClient->dequeue(); 551 if (bufIdx < 0) { 552 LOGE("error dequeuing a buffer (%s)", strerror(bufIdx)); 553 return bufIdx; 554 } 555 556 // grow the buffer array if needed 557 const size_t size = mBuffers.size(); 558 const size_t needed = bufIdx+1; 559 if (size < needed) { 560 mBuffers.insertAt(size, needed-size); 561 } 562 563 uint32_t w, h, format, usage; 564 if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) { 565 err = getBufferLocked(bufIdx, w, h, format, usage); 566 LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)", 567 bufIdx, w, h, format, usage, strerror(-err)); 568 if (err == NO_ERROR) { 569 // reset the width/height with the what we get from the buffer 570 const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); 571 mWidth = uint32_t(backBuffer->width); 572 mHeight = uint32_t(backBuffer->height); 573 } 574 } 575 576 // if we still don't have a buffer here, we probably ran out of memory 577 const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); 578 if (!err && backBuffer==0) { 579 err = NO_MEMORY; 580 } 581 582 if (err == NO_ERROR) { 583 mDirtyRegion.set(backBuffer->width, backBuffer->height); 584 *buffer = backBuffer.get(); 585 } else { 586 mSharedBufferClient->undoDequeue(bufIdx); 587 } 588 589 return err; 590} 591 592int Surface::lockBuffer(android_native_buffer_t* buffer) 593{ 594 status_t err = validate(); 595 if (err != NO_ERROR) 596 return err; 597 598 int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); 599 err = mSharedBufferClient->lock(bufIdx); 600 LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); 601 return err; 602} 603 604int Surface::queueBuffer(android_native_buffer_t* buffer) 605{ 606 status_t err = validate(); 607 if (err != NO_ERROR) 608 return err; 609 610 if (mSwapRectangle.isValid()) { 611 mDirtyRegion.set(mSwapRectangle); 612 } 613 614 int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); 615 mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop); 616 mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); 617 err = mSharedBufferClient->queue(bufIdx); 618 LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err)); 619 620 if (err == NO_ERROR) { 621 // TODO: can we avoid this IPC if we know there is one pending? 622 mClient.signalServer(); 623 } 624 return err; 625} 626 627int Surface::query(int what, int* value) 628{ 629 switch (what) { 630 case NATIVE_WINDOW_WIDTH: 631 *value = int(mWidth); 632 return NO_ERROR; 633 case NATIVE_WINDOW_HEIGHT: 634 *value = int(mHeight); 635 return NO_ERROR; 636 case NATIVE_WINDOW_FORMAT: 637 *value = int(mFormat); 638 return NO_ERROR; 639 } 640 return BAD_VALUE; 641} 642 643int Surface::perform(int operation, va_list args) 644{ 645 status_t err = validate(); 646 if (err != NO_ERROR) 647 return err; 648 649 int res = NO_ERROR; 650 switch (operation) { 651 case NATIVE_WINDOW_SET_USAGE: 652 dispatch_setUsage( args ); 653 break; 654 case NATIVE_WINDOW_CONNECT: 655 res = dispatch_connect( args ); 656 break; 657 case NATIVE_WINDOW_DISCONNECT: 658 res = dispatch_disconnect( args ); 659 break; 660 case NATIVE_WINDOW_SET_CROP: 661 res = dispatch_crop( args ); 662 break; 663 case NATIVE_WINDOW_SET_BUFFER_COUNT: 664 res = dispatch_set_buffer_count( args ); 665 break; 666 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 667 res = dispatch_set_buffers_geometry( args ); 668 break; 669 default: 670 res = NAME_NOT_FOUND; 671 break; 672 } 673 return res; 674} 675 676void Surface::dispatch_setUsage(va_list args) { 677 int usage = va_arg(args, int); 678 setUsage( usage ); 679} 680int Surface::dispatch_connect(va_list args) { 681 int api = va_arg(args, int); 682 return connect( api ); 683} 684int Surface::dispatch_disconnect(va_list args) { 685 int api = va_arg(args, int); 686 return disconnect( api ); 687} 688int Surface::dispatch_crop(va_list args) { 689 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); 690 return crop( reinterpret_cast<Rect const*>(rect) ); 691} 692int Surface::dispatch_set_buffer_count(va_list args) { 693 size_t bufferCount = va_arg(args, size_t); 694 return setBufferCount(bufferCount); 695} 696int Surface::dispatch_set_buffers_geometry(va_list args) { 697 int w = va_arg(args, int); 698 int h = va_arg(args, int); 699 int f = va_arg(args, int); 700 return setBuffersGeometry(w, h, f); 701} 702 703void Surface::setUsage(uint32_t reqUsage) 704{ 705 Mutex::Autolock _l(mSurfaceLock); 706 mBufferInfo.set(reqUsage); 707} 708 709int Surface::connect(int api) 710{ 711 Mutex::Autolock _l(mSurfaceLock); 712 int err = NO_ERROR; 713 switch (api) { 714 case NATIVE_WINDOW_API_EGL: 715 if (mConnected) { 716 err = -EINVAL; 717 } else { 718 mConnected = api; 719 } 720 break; 721 default: 722 err = -EINVAL; 723 break; 724 } 725 return err; 726} 727 728int Surface::disconnect(int api) 729{ 730 Mutex::Autolock _l(mSurfaceLock); 731 int err = NO_ERROR; 732 switch (api) { 733 case NATIVE_WINDOW_API_EGL: 734 if (mConnected == api) { 735 mConnected = 0; 736 } else { 737 err = -EINVAL; 738 } 739 break; 740 default: 741 err = -EINVAL; 742 break; 743 } 744 return err; 745} 746 747int Surface::crop(Rect const* rect) 748{ 749 Mutex::Autolock _l(mSurfaceLock); 750 // TODO: validate rect size 751 mNextBufferCrop = *rect; 752 return NO_ERROR; 753} 754 755int Surface::setBufferCount(int bufferCount) 756{ 757 sp<ISurface> s(mSurface); 758 if (s == 0) return NO_INIT; 759 760 class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback { 761 sp<ISurface> surface; 762 virtual status_t operator()(int bufferCount) const { 763 return surface->setBufferCount(bufferCount); 764 } 765 public: 766 SetBufferCountIPC(const sp<ISurface>& surface) : surface(surface) { } 767 } ipc(s); 768 769 status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc); 770 LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s", 771 bufferCount, strerror(-err)); 772 return err; 773} 774 775int Surface::setBuffersGeometry(int w, int h, int format) 776{ 777 if (w<0 || h<0 || format<0) 778 return BAD_VALUE; 779 780 if ((w && !h) || (!w && h)) 781 return BAD_VALUE; 782 783 Mutex::Autolock _l(mSurfaceLock); 784 mBufferInfo.set(w, h, format); 785 return NO_ERROR; 786} 787 788// ---------------------------------------------------------------------------- 789 790int Surface::getConnectedApi() const 791{ 792 Mutex::Autolock _l(mSurfaceLock); 793 return mConnected; 794} 795 796// ---------------------------------------------------------------------------- 797 798status_t Surface::lock(SurfaceInfo* info, bool blocking) { 799 return Surface::lock(info, NULL, blocking); 800} 801 802status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 803{ 804 if (getConnectedApi()) { 805 LOGE("Surface::lock(%p) failed. Already connected to another API", 806 (android_native_window_t*)this); 807 CallStack stack; 808 stack.update(); 809 stack.dump(""); 810 return INVALID_OPERATION; 811 } 812 813 if (mApiLock.tryLock() != NO_ERROR) { 814 LOGE("calling Surface::lock from different threads!"); 815 CallStack stack; 816 stack.update(); 817 stack.dump(""); 818 return WOULD_BLOCK; 819 } 820 821 /* Here we're holding mApiLock */ 822 823 if (mLockedBuffer != 0) { 824 LOGE("Surface::lock failed, already locked"); 825 mApiLock.unlock(); 826 return INVALID_OPERATION; 827 } 828 829 // we're intending to do software rendering from this point 830 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 831 832 android_native_buffer_t* out; 833 status_t err = dequeueBuffer(&out); 834 LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); 835 if (err == NO_ERROR) { 836 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); 837 err = lockBuffer(backBuffer.get()); 838 LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", 839 getBufferIndex(backBuffer), strerror(-err)); 840 if (err == NO_ERROR) { 841 const Rect bounds(backBuffer->width, backBuffer->height); 842 const Region boundsRegion(bounds); 843 Region scratch(boundsRegion); 844 Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); 845 newDirtyRegion &= boundsRegion; 846 847 // figure out if we can copy the frontbuffer back 848 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); 849 const bool canCopyBack = (frontBuffer != 0 && 850 backBuffer->width == frontBuffer->width && 851 backBuffer->height == frontBuffer->height && 852 backBuffer->format == frontBuffer->format && 853 !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); 854 855 // the dirty region we report to surfaceflinger is the one 856 // given by the user (as opposed to the one *we* return to the 857 // user). 858 mDirtyRegion = newDirtyRegion; 859 860 if (canCopyBack) { 861 // copy the area that is invalid and not repainted this round 862 const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); 863 if (!copyback.isEmpty()) 864 copyBlt(backBuffer, frontBuffer, copyback); 865 } else { 866 // if we can't copy-back anything, modify the user's dirty 867 // region to make sure they redraw the whole buffer 868 newDirtyRegion = boundsRegion; 869 } 870 871 // keep track of the are of the buffer that is "clean" 872 // (ie: that will be redrawn) 873 mOldDirtyRegion = newDirtyRegion; 874 875 void* vaddr; 876 status_t res = backBuffer->lock( 877 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 878 newDirtyRegion.bounds(), &vaddr); 879 880 LOGW_IF(res, "failed locking buffer (handle = %p)", 881 backBuffer->handle); 882 883 mLockedBuffer = backBuffer; 884 other->w = backBuffer->width; 885 other->h = backBuffer->height; 886 other->s = backBuffer->stride; 887 other->usage = backBuffer->usage; 888 other->format = backBuffer->format; 889 other->bits = vaddr; 890 } 891 } 892 mApiLock.unlock(); 893 return err; 894} 895 896status_t Surface::unlockAndPost() 897{ 898 if (mLockedBuffer == 0) { 899 LOGE("Surface::unlockAndPost failed, no locked buffer"); 900 return INVALID_OPERATION; 901 } 902 903 status_t err = mLockedBuffer->unlock(); 904 LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); 905 906 err = queueBuffer(mLockedBuffer.get()); 907 LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)", 908 getBufferIndex(mLockedBuffer), strerror(-err)); 909 910 mPostedBuffer = mLockedBuffer; 911 mLockedBuffer = 0; 912 return err; 913} 914 915void Surface::setSwapRectangle(const Rect& r) { 916 Mutex::Autolock _l(mSurfaceLock); 917 mSwapRectangle = r; 918} 919 920int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const 921{ 922 return buffer->getIndex(); 923} 924 925status_t Surface::getBufferLocked(int index, 926 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) 927{ 928 sp<ISurface> s(mSurface); 929 if (s == 0) return NO_INIT; 930 931 status_t err = NO_MEMORY; 932 933 // free the current buffer 934 sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index)); 935 if (currentBuffer != 0) { 936 getBufferMapper().unregisterBuffer(currentBuffer->handle); 937 currentBuffer.clear(); 938 } 939 940 sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage); 941 LOGE_IF(buffer==0, 942 "ISurface::getBuffer(%d, %08x) returned NULL", 943 index, usage); 944 if (buffer != 0) { // this should never happen by construction 945 LOGE_IF(buffer->handle == NULL, 946 "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) " 947 "returned a buffer with a null handle", 948 mIdentity, index, w, h, format, usage); 949 err = mSharedBufferClient->getStatus(); 950 LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err); 951 if (!err && buffer->handle != NULL) { 952 err = getBufferMapper().registerBuffer(buffer->handle); 953 LOGW_IF(err, "registerBuffer(...) failed %d (%s)", 954 err, strerror(-err)); 955 if (err == NO_ERROR) { 956 currentBuffer = buffer; 957 currentBuffer->setIndex(index); 958 } 959 } else { 960 err = err<0 ? err : status_t(NO_MEMORY); 961 } 962 } 963 return err; 964} 965 966// ---------------------------------------------------------------------------- 967Surface::BufferInfo::BufferInfo() 968 : mWidth(0), mHeight(0), mFormat(0), 969 mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0) 970{ 971} 972 973void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) { 974 if ((mWidth != w) || (mHeight != h) || (mFormat != format)) { 975 mWidth = w; 976 mHeight = h; 977 mFormat = format; 978 mDirty |= GEOMETRY; 979 } 980} 981 982void Surface::BufferInfo::set(uint32_t usage) { 983 mUsage = usage; 984} 985 986void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight, 987 uint32_t *pFormat, uint32_t *pUsage) const { 988 *pWidth = mWidth; 989 *pHeight = mHeight; 990 *pFormat = mFormat; 991 *pUsage = mUsage; 992} 993 994bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const { 995 // make sure we AT LEAST have the usage flags we want 996 if (mDirty || buffer==0 || 997 ((buffer->usage & mUsage) != mUsage)) { 998 mDirty = 0; 999 return false; 1000 } 1001 return true; 1002} 1003 1004// ---------------------------------------------------------------------------- 1005}; // namespace android 1006 1007