1 /* 2 * Copyright (C) 2010 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 "SurfaceTextureClient" 18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 19 //#define LOG_NDEBUG 0 20 21 #include <android/native_window.h> 22 23 #include <utils/Log.h> 24 #include <utils/Trace.h> 25 26 #include <gui/ISurfaceComposer.h> 27 #include <gui/SurfaceComposerClient.h> 28 #include <gui/SurfaceTexture.h> 29 #include <gui/SurfaceTextureClient.h> 30 31 #include <private/gui/ComposerService.h> 32 33 namespace android { 34 35 SurfaceTextureClient::SurfaceTextureClient( 36 const sp<ISurfaceTexture>& surfaceTexture) 37 { 38 SurfaceTextureClient::init(); 39 SurfaceTextureClient::setISurfaceTexture(surfaceTexture); 40 } 41 42 // see SurfaceTextureClient.h 43 SurfaceTextureClient::SurfaceTextureClient(const 44 sp<SurfaceTexture>& surfaceTexture) 45 { 46 SurfaceTextureClient::init(); 47 SurfaceTextureClient::setISurfaceTexture(surfaceTexture->getBufferQueue()); 48 } 49 50 SurfaceTextureClient::SurfaceTextureClient() { 51 SurfaceTextureClient::init(); 52 } 53 54 SurfaceTextureClient::~SurfaceTextureClient() { 55 if (mConnectedToCpu) { 56 SurfaceTextureClient::disconnect(NATIVE_WINDOW_API_CPU); 57 } 58 } 59 60 void SurfaceTextureClient::init() { 61 // Initialize the ANativeWindow function pointers. 62 ANativeWindow::setSwapInterval = hook_setSwapInterval; 63 ANativeWindow::dequeueBuffer = hook_dequeueBuffer; 64 ANativeWindow::cancelBuffer = hook_cancelBuffer; 65 ANativeWindow::lockBuffer = hook_lockBuffer; 66 ANativeWindow::queueBuffer = hook_queueBuffer; 67 ANativeWindow::query = hook_query; 68 ANativeWindow::perform = hook_perform; 69 70 const_cast<int&>(ANativeWindow::minSwapInterval) = 0; 71 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1; 72 73 mReqWidth = 0; 74 mReqHeight = 0; 75 mReqFormat = 0; 76 mReqUsage = 0; 77 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; 78 mCrop.clear(); 79 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; 80 mTransform = 0; 81 mDefaultWidth = 0; 82 mDefaultHeight = 0; 83 mUserWidth = 0; 84 mUserHeight = 0; 85 mTransformHint = 0; 86 mConsumerRunningBehind = false; 87 mConnectedToCpu = false; 88 } 89 90 void SurfaceTextureClient::setISurfaceTexture( 91 const sp<ISurfaceTexture>& surfaceTexture) 92 { 93 mSurfaceTexture = surfaceTexture; 94 } 95 96 sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const { 97 return mSurfaceTexture; 98 } 99 100 int SurfaceTextureClient::hook_setSwapInterval(ANativeWindow* window, int interval) { 101 SurfaceTextureClient* c = getSelf(window); 102 return c->setSwapInterval(interval); 103 } 104 105 int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window, 106 ANativeWindowBuffer** buffer) { 107 SurfaceTextureClient* c = getSelf(window); 108 return c->dequeueBuffer(buffer); 109 } 110 111 int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window, 112 ANativeWindowBuffer* buffer) { 113 SurfaceTextureClient* c = getSelf(window); 114 return c->cancelBuffer(buffer); 115 } 116 117 int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window, 118 ANativeWindowBuffer* buffer) { 119 SurfaceTextureClient* c = getSelf(window); 120 return c->lockBuffer(buffer); 121 } 122 123 int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window, 124 ANativeWindowBuffer* buffer) { 125 SurfaceTextureClient* c = getSelf(window); 126 return c->queueBuffer(buffer); 127 } 128 129 int SurfaceTextureClient::hook_query(const ANativeWindow* window, 130 int what, int* value) { 131 const SurfaceTextureClient* c = getSelf(window); 132 return c->query(what, value); 133 } 134 135 int SurfaceTextureClient::hook_perform(ANativeWindow* window, int operation, ...) { 136 va_list args; 137 va_start(args, operation); 138 SurfaceTextureClient* c = getSelf(window); 139 return c->perform(operation, args); 140 } 141 142 int SurfaceTextureClient::setSwapInterval(int interval) { 143 ATRACE_CALL(); 144 // EGL specification states: 145 // interval is silently clamped to minimum and maximum implementation 146 // dependent values before being stored. 147 // Although we don't have to, we apply the same logic here. 148 149 if (interval < minSwapInterval) 150 interval = minSwapInterval; 151 152 if (interval > maxSwapInterval) 153 interval = maxSwapInterval; 154 155 status_t res = mSurfaceTexture->setSynchronousMode(interval ? true : false); 156 157 return res; 158 } 159 160 int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { 161 ATRACE_CALL(); 162 ALOGV("SurfaceTextureClient::dequeueBuffer"); 163 Mutex::Autolock lock(mMutex); 164 int buf = -1; 165 int reqW = mReqWidth ? mReqWidth : mUserWidth; 166 int reqH = mReqHeight ? mReqHeight : mUserHeight; 167 status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH, 168 mReqFormat, mReqUsage); 169 if (result < 0) { 170 ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)" 171 "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage, 172 result); 173 return result; 174 } 175 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer); 176 if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) { 177 freeAllBuffers(); 178 } 179 180 if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) { 181 result = mSurfaceTexture->requestBuffer(buf, &gbuf); 182 if (result != NO_ERROR) { 183 ALOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d", 184 result); 185 return result; 186 } 187 } 188 *buffer = gbuf.get(); 189 return OK; 190 } 191 192 int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { 193 ATRACE_CALL(); 194 ALOGV("SurfaceTextureClient::cancelBuffer"); 195 Mutex::Autolock lock(mMutex); 196 int i = getSlotFromBufferLocked(buffer); 197 if (i < 0) { 198 return i; 199 } 200 mSurfaceTexture->cancelBuffer(i); 201 return OK; 202 } 203 204 int SurfaceTextureClient::getSlotFromBufferLocked( 205 android_native_buffer_t* buffer) const { 206 bool dumpedState = false; 207 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 208 if (mSlots[i].buffer != NULL && 209 mSlots[i].buffer->handle == buffer->handle) { 210 return i; 211 } 212 } 213 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); 214 return BAD_VALUE; 215 } 216 217 int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { 218 ALOGV("SurfaceTextureClient::lockBuffer"); 219 Mutex::Autolock lock(mMutex); 220 return OK; 221 } 222 223 int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { 224 ATRACE_CALL(); 225 ALOGV("SurfaceTextureClient::queueBuffer"); 226 Mutex::Autolock lock(mMutex); 227 int64_t timestamp; 228 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { 229 timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 230 ALOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms", 231 timestamp / 1000000.f); 232 } else { 233 timestamp = mTimestamp; 234 } 235 int i = getSlotFromBufferLocked(buffer); 236 if (i < 0) { 237 return i; 238 } 239 240 // Make sure the crop rectangle is entirely inside the buffer. 241 Rect crop; 242 mCrop.intersect(Rect(buffer->width, buffer->height), &crop); 243 244 ISurfaceTexture::QueueBufferOutput output; 245 ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode, 246 mTransform); 247 status_t err = mSurfaceTexture->queueBuffer(i, input, &output); 248 if (err != OK) { 249 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); 250 } 251 uint32_t numPendingBuffers = 0; 252 output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, 253 &numPendingBuffers); 254 255 mConsumerRunningBehind = (numPendingBuffers >= 2); 256 257 return err; 258 } 259 260 int SurfaceTextureClient::query(int what, int* value) const { 261 ATRACE_CALL(); 262 ALOGV("SurfaceTextureClient::query"); 263 { // scope for the lock 264 Mutex::Autolock lock(mMutex); 265 switch (what) { 266 case NATIVE_WINDOW_FORMAT: 267 if (mReqFormat) { 268 *value = mReqFormat; 269 return NO_ERROR; 270 } 271 break; 272 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: { 273 sp<ISurfaceComposer> composer( 274 ComposerService::getComposerService()); 275 if (composer->authenticateSurfaceTexture(mSurfaceTexture)) { 276 *value = 1; 277 } else { 278 *value = 0; 279 } 280 return NO_ERROR; 281 } 282 case NATIVE_WINDOW_CONCRETE_TYPE: 283 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; 284 return NO_ERROR; 285 case NATIVE_WINDOW_DEFAULT_WIDTH: 286 *value = mUserWidth ? mUserWidth : mDefaultWidth; 287 return NO_ERROR; 288 case NATIVE_WINDOW_DEFAULT_HEIGHT: 289 *value = mUserHeight ? mUserHeight : mDefaultHeight; 290 return NO_ERROR; 291 case NATIVE_WINDOW_TRANSFORM_HINT: 292 *value = mTransformHint; 293 return NO_ERROR; 294 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: { 295 status_t err = NO_ERROR; 296 if (!mConsumerRunningBehind) { 297 *value = 0; 298 } else { 299 err = mSurfaceTexture->query(what, value); 300 if (err == NO_ERROR) { 301 mConsumerRunningBehind = *value; 302 } 303 } 304 return err; 305 } 306 } 307 } 308 return mSurfaceTexture->query(what, value); 309 } 310 311 int SurfaceTextureClient::perform(int operation, va_list args) 312 { 313 int res = NO_ERROR; 314 switch (operation) { 315 case NATIVE_WINDOW_CONNECT: 316 // deprecated. must return NO_ERROR. 317 break; 318 case NATIVE_WINDOW_DISCONNECT: 319 // deprecated. must return NO_ERROR. 320 break; 321 case NATIVE_WINDOW_SET_USAGE: 322 res = dispatchSetUsage(args); 323 break; 324 case NATIVE_WINDOW_SET_CROP: 325 res = dispatchSetCrop(args); 326 break; 327 case NATIVE_WINDOW_SET_BUFFER_COUNT: 328 res = dispatchSetBufferCount(args); 329 break; 330 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 331 res = dispatchSetBuffersGeometry(args); 332 break; 333 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: 334 res = dispatchSetBuffersTransform(args); 335 break; 336 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: 337 res = dispatchSetBuffersTimestamp(args); 338 break; 339 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: 340 res = dispatchSetBuffersDimensions(args); 341 break; 342 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS: 343 res = dispatchSetBuffersUserDimensions(args); 344 break; 345 case NATIVE_WINDOW_SET_BUFFERS_FORMAT: 346 res = dispatchSetBuffersFormat(args); 347 break; 348 case NATIVE_WINDOW_LOCK: 349 res = dispatchLock(args); 350 break; 351 case NATIVE_WINDOW_UNLOCK_AND_POST: 352 res = dispatchUnlockAndPost(args); 353 break; 354 case NATIVE_WINDOW_SET_SCALING_MODE: 355 res = dispatchSetScalingMode(args); 356 break; 357 case NATIVE_WINDOW_API_CONNECT: 358 res = dispatchConnect(args); 359 break; 360 case NATIVE_WINDOW_API_DISCONNECT: 361 res = dispatchDisconnect(args); 362 break; 363 default: 364 res = NAME_NOT_FOUND; 365 break; 366 } 367 return res; 368 } 369 370 int SurfaceTextureClient::dispatchConnect(va_list args) { 371 int api = va_arg(args, int); 372 return connect(api); 373 } 374 375 int SurfaceTextureClient::dispatchDisconnect(va_list args) { 376 int api = va_arg(args, int); 377 return disconnect(api); 378 } 379 380 int SurfaceTextureClient::dispatchSetUsage(va_list args) { 381 int usage = va_arg(args, int); 382 return setUsage(usage); 383 } 384 385 int SurfaceTextureClient::dispatchSetCrop(va_list args) { 386 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); 387 return setCrop(reinterpret_cast<Rect const*>(rect)); 388 } 389 390 int SurfaceTextureClient::dispatchSetBufferCount(va_list args) { 391 size_t bufferCount = va_arg(args, size_t); 392 return setBufferCount(bufferCount); 393 } 394 395 int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) { 396 int w = va_arg(args, int); 397 int h = va_arg(args, int); 398 int f = va_arg(args, int); 399 int err = setBuffersDimensions(w, h); 400 if (err != 0) { 401 return err; 402 } 403 return setBuffersFormat(f); 404 } 405 406 int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) { 407 int w = va_arg(args, int); 408 int h = va_arg(args, int); 409 return setBuffersDimensions(w, h); 410 } 411 412 int SurfaceTextureClient::dispatchSetBuffersUserDimensions(va_list args) { 413 int w = va_arg(args, int); 414 int h = va_arg(args, int); 415 return setBuffersUserDimensions(w, h); 416 } 417 418 int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) { 419 int f = va_arg(args, int); 420 return setBuffersFormat(f); 421 } 422 423 int SurfaceTextureClient::dispatchSetScalingMode(va_list args) { 424 int m = va_arg(args, int); 425 return setScalingMode(m); 426 } 427 428 int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { 429 int transform = va_arg(args, int); 430 return setBuffersTransform(transform); 431 } 432 433 int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { 434 int64_t timestamp = va_arg(args, int64_t); 435 return setBuffersTimestamp(timestamp); 436 } 437 438 int SurfaceTextureClient::dispatchLock(va_list args) { 439 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*); 440 ARect* inOutDirtyBounds = va_arg(args, ARect*); 441 return lock(outBuffer, inOutDirtyBounds); 442 } 443 444 int SurfaceTextureClient::dispatchUnlockAndPost(va_list args) { 445 return unlockAndPost(); 446 } 447 448 449 int SurfaceTextureClient::connect(int api) { 450 ATRACE_CALL(); 451 ALOGV("SurfaceTextureClient::connect"); 452 Mutex::Autolock lock(mMutex); 453 ISurfaceTexture::QueueBufferOutput output; 454 int err = mSurfaceTexture->connect(api, &output); 455 if (err == NO_ERROR) { 456 uint32_t numPendingBuffers = 0; 457 output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, 458 &numPendingBuffers); 459 mConsumerRunningBehind = (numPendingBuffers >= 2); 460 } 461 if (!err && api == NATIVE_WINDOW_API_CPU) { 462 mConnectedToCpu = true; 463 } 464 return err; 465 } 466 467 int SurfaceTextureClient::disconnect(int api) { 468 ATRACE_CALL(); 469 ALOGV("SurfaceTextureClient::disconnect"); 470 Mutex::Autolock lock(mMutex); 471 freeAllBuffers(); 472 int err = mSurfaceTexture->disconnect(api); 473 if (!err) { 474 mReqFormat = 0; 475 mReqWidth = 0; 476 mReqHeight = 0; 477 mReqUsage = 0; 478 mCrop.clear(); 479 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; 480 mTransform = 0; 481 if (api == NATIVE_WINDOW_API_CPU) { 482 mConnectedToCpu = false; 483 } 484 } 485 return err; 486 } 487 488 int SurfaceTextureClient::setUsage(uint32_t reqUsage) 489 { 490 ALOGV("SurfaceTextureClient::setUsage"); 491 Mutex::Autolock lock(mMutex); 492 mReqUsage = reqUsage; 493 return OK; 494 } 495 496 int SurfaceTextureClient::setCrop(Rect const* rect) 497 { 498 ATRACE_CALL(); 499 500 Rect realRect; 501 if (rect == NULL || rect->isEmpty()) { 502 realRect.clear(); 503 } else { 504 realRect = *rect; 505 } 506 507 ALOGV("SurfaceTextureClient::setCrop rect=[%d %d %d %d]", 508 realRect.left, realRect.top, realRect.right, realRect.bottom); 509 510 Mutex::Autolock lock(mMutex); 511 mCrop = realRect; 512 return NO_ERROR; 513 } 514 515 int SurfaceTextureClient::setBufferCount(int bufferCount) 516 { 517 ATRACE_CALL(); 518 ALOGV("SurfaceTextureClient::setBufferCount"); 519 Mutex::Autolock lock(mMutex); 520 521 status_t err = mSurfaceTexture->setBufferCount(bufferCount); 522 ALOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s", 523 bufferCount, strerror(-err)); 524 525 if (err == NO_ERROR) { 526 freeAllBuffers(); 527 } 528 529 return err; 530 } 531 532 int SurfaceTextureClient::setBuffersDimensions(int w, int h) 533 { 534 ATRACE_CALL(); 535 ALOGV("SurfaceTextureClient::setBuffersDimensions"); 536 537 if (w<0 || h<0) 538 return BAD_VALUE; 539 540 if ((w && !h) || (!w && h)) 541 return BAD_VALUE; 542 543 Mutex::Autolock lock(mMutex); 544 mReqWidth = w; 545 mReqHeight = h; 546 return NO_ERROR; 547 } 548 549 int SurfaceTextureClient::setBuffersUserDimensions(int w, int h) 550 { 551 ATRACE_CALL(); 552 ALOGV("SurfaceTextureClient::setBuffersUserDimensions"); 553 554 if (w<0 || h<0) 555 return BAD_VALUE; 556 557 if ((w && !h) || (!w && h)) 558 return BAD_VALUE; 559 560 Mutex::Autolock lock(mMutex); 561 mUserWidth = w; 562 mUserHeight = h; 563 return NO_ERROR; 564 } 565 566 int SurfaceTextureClient::setBuffersFormat(int format) 567 { 568 ALOGV("SurfaceTextureClient::setBuffersFormat"); 569 570 if (format<0) 571 return BAD_VALUE; 572 573 Mutex::Autolock lock(mMutex); 574 mReqFormat = format; 575 return NO_ERROR; 576 } 577 578 int SurfaceTextureClient::setScalingMode(int mode) 579 { 580 ATRACE_CALL(); 581 ALOGV("SurfaceTextureClient::setScalingMode(%d)", mode); 582 583 switch (mode) { 584 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 585 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 586 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 587 break; 588 default: 589 ALOGE("unknown scaling mode: %d", mode); 590 return BAD_VALUE; 591 } 592 593 Mutex::Autolock lock(mMutex); 594 mScalingMode = mode; 595 return NO_ERROR; 596 } 597 598 int SurfaceTextureClient::setBuffersTransform(int transform) 599 { 600 ATRACE_CALL(); 601 ALOGV("SurfaceTextureClient::setBuffersTransform"); 602 Mutex::Autolock lock(mMutex); 603 mTransform = transform; 604 return NO_ERROR; 605 } 606 607 int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp) 608 { 609 ALOGV("SurfaceTextureClient::setBuffersTimestamp"); 610 Mutex::Autolock lock(mMutex); 611 mTimestamp = timestamp; 612 return NO_ERROR; 613 } 614 615 void SurfaceTextureClient::freeAllBuffers() { 616 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 617 mSlots[i].buffer = 0; 618 } 619 } 620 621 // ---------------------------------------------------------------------- 622 // the lock/unlock APIs must be used from the same thread 623 624 static status_t copyBlt( 625 const sp<GraphicBuffer>& dst, 626 const sp<GraphicBuffer>& src, 627 const Region& reg) 628 { 629 // src and dst with, height and format must be identical. no verification 630 // is done here. 631 status_t err; 632 uint8_t const * src_bits = NULL; 633 err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); 634 ALOGE_IF(err, "error locking src buffer %s", strerror(-err)); 635 636 uint8_t* dst_bits = NULL; 637 err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); 638 ALOGE_IF(err, "error locking dst buffer %s", strerror(-err)); 639 640 Region::const_iterator head(reg.begin()); 641 Region::const_iterator tail(reg.end()); 642 if (head != tail && src_bits && dst_bits) { 643 const size_t bpp = bytesPerPixel(src->format); 644 const size_t dbpr = dst->stride * bpp; 645 const size_t sbpr = src->stride * bpp; 646 647 while (head != tail) { 648 const Rect& r(*head++); 649 ssize_t h = r.height(); 650 if (h <= 0) continue; 651 size_t size = r.width() * bpp; 652 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; 653 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; 654 if (dbpr==sbpr && size==sbpr) { 655 size *= h; 656 h = 1; 657 } 658 do { 659 memcpy(d, s, size); 660 d += dbpr; 661 s += sbpr; 662 } while (--h > 0); 663 } 664 } 665 666 if (src_bits) 667 src->unlock(); 668 669 if (dst_bits) 670 dst->unlock(); 671 672 return err; 673 } 674 675 // ---------------------------------------------------------------------------- 676 677 status_t SurfaceTextureClient::lock( 678 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) 679 { 680 if (mLockedBuffer != 0) { 681 ALOGE("Surface::lock failed, already locked"); 682 return INVALID_OPERATION; 683 } 684 685 if (!mConnectedToCpu) { 686 int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU); 687 if (err) { 688 return err; 689 } 690 // we're intending to do software rendering from this point 691 setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 692 } 693 694 ANativeWindowBuffer* out; 695 status_t err = dequeueBuffer(&out); 696 ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); 697 if (err == NO_ERROR) { 698 sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); 699 err = lockBuffer(backBuffer.get()); 700 ALOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", 701 backBuffer->handle, strerror(-err)); 702 if (err == NO_ERROR) { 703 const Rect bounds(backBuffer->width, backBuffer->height); 704 705 Region newDirtyRegion; 706 if (inOutDirtyBounds) { 707 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds)); 708 newDirtyRegion.andSelf(bounds); 709 } else { 710 newDirtyRegion.set(bounds); 711 } 712 713 // figure out if we can copy the frontbuffer back 714 const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); 715 const bool canCopyBack = (frontBuffer != 0 && 716 backBuffer->width == frontBuffer->width && 717 backBuffer->height == frontBuffer->height && 718 backBuffer->format == frontBuffer->format); 719 720 if (canCopyBack) { 721 // copy the area that is invalid and not repainted this round 722 const Region copyback(mDirtyRegion.subtract(newDirtyRegion)); 723 if (!copyback.isEmpty()) 724 copyBlt(backBuffer, frontBuffer, copyback); 725 } else { 726 // if we can't copy-back anything, modify the user's dirty 727 // region to make sure they redraw the whole buffer 728 newDirtyRegion.set(bounds); 729 mDirtyRegion.clear(); 730 Mutex::Autolock lock(mMutex); 731 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) { 732 mSlots[i].dirtyRegion.clear(); 733 } 734 } 735 736 737 { // scope for the lock 738 Mutex::Autolock lock(mMutex); 739 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get())); 740 if (backBufferSlot >= 0) { 741 Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion); 742 mDirtyRegion.subtract(dirtyRegion); 743 dirtyRegion = newDirtyRegion; 744 } 745 } 746 747 mDirtyRegion.orSelf(newDirtyRegion); 748 if (inOutDirtyBounds) { 749 *inOutDirtyBounds = newDirtyRegion.getBounds(); 750 } 751 752 void* vaddr; 753 status_t res = backBuffer->lock( 754 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 755 newDirtyRegion.bounds(), &vaddr); 756 757 ALOGW_IF(res, "failed locking buffer (handle = %p)", 758 backBuffer->handle); 759 760 mLockedBuffer = backBuffer; 761 outBuffer->width = backBuffer->width; 762 outBuffer->height = backBuffer->height; 763 outBuffer->stride = backBuffer->stride; 764 outBuffer->format = backBuffer->format; 765 outBuffer->bits = vaddr; 766 } 767 } 768 return err; 769 } 770 771 status_t SurfaceTextureClient::unlockAndPost() 772 { 773 if (mLockedBuffer == 0) { 774 ALOGE("Surface::unlockAndPost failed, no locked buffer"); 775 return INVALID_OPERATION; 776 } 777 778 status_t err = mLockedBuffer->unlock(); 779 ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); 780 781 err = queueBuffer(mLockedBuffer.get()); 782 ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", 783 mLockedBuffer->handle, strerror(-err)); 784 785 mPostedBuffer = mLockedBuffer; 786 mLockedBuffer = 0; 787 return err; 788 } 789 790 }; // namespace android 791