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