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 "SurfaceTexture" 18 //#define LOG_NDEBUG 0 19 20 #define GL_GLEXT_PROTOTYPES 21 #define EGL_EGLEXT_PROTOTYPES 22 23 #include <EGL/egl.h> 24 #include <EGL/eglext.h> 25 #include <GLES2/gl2.h> 26 #include <GLES2/gl2ext.h> 27 28 #include <gui/SurfaceTexture.h> 29 30 #include <hardware/hardware.h> 31 32 #include <surfaceflinger/ISurfaceComposer.h> 33 #include <surfaceflinger/SurfaceComposerClient.h> 34 #include <surfaceflinger/IGraphicBufferAlloc.h> 35 36 #include <utils/Log.h> 37 #include <utils/String8.h> 38 39 40 #define ALLOW_DEQUEUE_CURRENT_BUFFER false 41 42 // Macros for including the SurfaceTexture name in log messages 43 #define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__) 44 #define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__) 45 #define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__) 46 #define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__) 47 #define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__) 48 49 namespace android { 50 51 // Transform matrices 52 static float mtxIdentity[16] = { 53 1, 0, 0, 0, 54 0, 1, 0, 0, 55 0, 0, 1, 0, 56 0, 0, 0, 1, 57 }; 58 static float mtxFlipH[16] = { 59 -1, 0, 0, 0, 60 0, 1, 0, 0, 61 0, 0, 1, 0, 62 1, 0, 0, 1, 63 }; 64 static float mtxFlipV[16] = { 65 1, 0, 0, 0, 66 0, -1, 0, 0, 67 0, 0, 1, 0, 68 0, 1, 0, 1, 69 }; 70 static float mtxRot90[16] = { 71 0, 1, 0, 0, 72 -1, 0, 0, 0, 73 0, 0, 1, 0, 74 1, 0, 0, 1, 75 }; 76 static float mtxRot180[16] = { 77 -1, 0, 0, 0, 78 0, -1, 0, 0, 79 0, 0, 1, 0, 80 1, 1, 0, 1, 81 }; 82 static float mtxRot270[16] = { 83 0, -1, 0, 0, 84 1, 0, 0, 0, 85 0, 0, 1, 0, 86 0, 1, 0, 1, 87 }; 88 89 static void mtxMul(float out[16], const float a[16], const float b[16]); 90 91 // Get an ID that's unique within this process. 92 static int32_t createProcessUniqueId() { 93 static volatile int32_t globalCounter = 0; 94 return android_atomic_inc(&globalCounter); 95 } 96 97 SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, 98 GLenum texTarget) : 99 mDefaultWidth(1), 100 mDefaultHeight(1), 101 mPixelFormat(PIXEL_FORMAT_RGBA_8888), 102 mBufferCount(MIN_ASYNC_BUFFER_SLOTS), 103 mClientBufferCount(0), 104 mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), 105 mCurrentTexture(INVALID_BUFFER_SLOT), 106 mCurrentTransform(0), 107 mCurrentTimestamp(0), 108 mNextTransform(0), 109 mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 110 mTexName(tex), 111 mSynchronousMode(false), 112 mAllowSynchronousMode(allowSynchronousMode), 113 mConnectedApi(NO_CONNECTED_API), 114 mAbandoned(false), 115 mTexTarget(texTarget) { 116 // Choose a name using the PID and a process-unique ID. 117 mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); 118 119 ST_LOGV("SurfaceTexture::SurfaceTexture"); 120 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 121 mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 122 mNextCrop.makeInvalid(); 123 memcpy(mCurrentTransformMatrix, mtxIdentity, 124 sizeof(mCurrentTransformMatrix)); 125 } 126 127 SurfaceTexture::~SurfaceTexture() { 128 ST_LOGV("SurfaceTexture::~SurfaceTexture"); 129 freeAllBuffersLocked(); 130 } 131 132 status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) { 133 if (bufferCount > NUM_BUFFER_SLOTS) 134 return BAD_VALUE; 135 136 // special-case, nothing to do 137 if (bufferCount == mBufferCount) 138 return OK; 139 140 if (!mClientBufferCount && 141 bufferCount >= mBufferCount) { 142 // easy, we just have more buffers 143 mBufferCount = bufferCount; 144 mServerBufferCount = bufferCount; 145 mDequeueCondition.signal(); 146 } else { 147 // we're here because we're either 148 // - reducing the number of available buffers 149 // - or there is a client-buffer-count in effect 150 151 // less than 2 buffers is never allowed 152 if (bufferCount < 2) 153 return BAD_VALUE; 154 155 // when there is non client-buffer-count in effect, the client is not 156 // allowed to dequeue more than one buffer at a time, 157 // so the next time they dequeue a buffer, we know that they don't 158 // own one. the actual resizing will happen during the next 159 // dequeueBuffer. 160 161 mServerBufferCount = bufferCount; 162 } 163 return OK; 164 } 165 166 status_t SurfaceTexture::setBufferCountServer(int bufferCount) { 167 Mutex::Autolock lock(mMutex); 168 return setBufferCountServerLocked(bufferCount); 169 } 170 171 status_t SurfaceTexture::setBufferCount(int bufferCount) { 172 ST_LOGV("SurfaceTexture::setBufferCount"); 173 Mutex::Autolock lock(mMutex); 174 175 if (mAbandoned) { 176 ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!"); 177 return NO_INIT; 178 } 179 if (bufferCount > NUM_BUFFER_SLOTS) { 180 ST_LOGE("setBufferCount: bufferCount larger than slots available"); 181 return BAD_VALUE; 182 } 183 184 // Error out if the user has dequeued buffers 185 for (int i=0 ; i<mBufferCount ; i++) { 186 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 187 ST_LOGE("setBufferCount: client owns some buffers"); 188 return -EINVAL; 189 } 190 } 191 192 const int minBufferSlots = mSynchronousMode ? 193 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 194 if (bufferCount == 0) { 195 mClientBufferCount = 0; 196 bufferCount = (mServerBufferCount >= minBufferSlots) ? 197 mServerBufferCount : minBufferSlots; 198 return setBufferCountServerLocked(bufferCount); 199 } 200 201 if (bufferCount < minBufferSlots) { 202 ST_LOGE("setBufferCount: requested buffer count (%d) is less than " 203 "minimum (%d)", bufferCount, minBufferSlots); 204 return BAD_VALUE; 205 } 206 207 // here we're guaranteed that the client doesn't have dequeued buffers 208 // and will release all of its buffer references. 209 freeAllBuffersLocked(); 210 mBufferCount = bufferCount; 211 mClientBufferCount = bufferCount; 212 mCurrentTexture = INVALID_BUFFER_SLOT; 213 mQueue.clear(); 214 mDequeueCondition.signal(); 215 return OK; 216 } 217 218 status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) 219 { 220 if (!w || !h) { 221 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", 222 w, h); 223 return BAD_VALUE; 224 } 225 226 Mutex::Autolock lock(mMutex); 227 mDefaultWidth = w; 228 mDefaultHeight = h; 229 return OK; 230 } 231 232 status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 233 ST_LOGV("SurfaceTexture::requestBuffer"); 234 Mutex::Autolock lock(mMutex); 235 if (mAbandoned) { 236 ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!"); 237 return NO_INIT; 238 } 239 if (slot < 0 || mBufferCount <= slot) { 240 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", 241 mBufferCount, slot); 242 return BAD_VALUE; 243 } 244 mSlots[slot].mRequestBufferCalled = true; 245 *buf = mSlots[slot].mGraphicBuffer; 246 return NO_ERROR; 247 } 248 249 status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, 250 uint32_t format, uint32_t usage) { 251 ST_LOGV("SurfaceTexture::dequeueBuffer"); 252 253 if ((w && !h) || (!w && h)) { 254 ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); 255 return BAD_VALUE; 256 } 257 258 Mutex::Autolock lock(mMutex); 259 260 status_t returnFlags(OK); 261 262 int found, foundSync; 263 int dequeuedCount = 0; 264 bool tryAgain = true; 265 while (tryAgain) { 266 if (mAbandoned) { 267 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); 268 return NO_INIT; 269 } 270 271 // We need to wait for the FIFO to drain if the number of buffer 272 // needs to change. 273 // 274 // The condition "number of buffers needs to change" is true if 275 // - the client doesn't care about how many buffers there are 276 // - AND the actual number of buffer is different from what was 277 // set in the last setBufferCountServer() 278 // - OR - 279 // setBufferCountServer() was set to a value incompatible with 280 // the synchronization mode (for instance because the sync mode 281 // changed since) 282 // 283 // As long as this condition is true AND the FIFO is not empty, we 284 // wait on mDequeueCondition. 285 286 const int minBufferCountNeeded = mSynchronousMode ? 287 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 288 289 const bool numberOfBuffersNeedsToChange = !mClientBufferCount && 290 ((mServerBufferCount != mBufferCount) || 291 (mServerBufferCount < minBufferCountNeeded)); 292 293 if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) { 294 // wait for the FIFO to drain 295 mDequeueCondition.wait(mMutex); 296 // NOTE: we continue here because we need to reevaluate our 297 // whole state (eg: we could be abandoned or disconnected) 298 continue; 299 } 300 301 if (numberOfBuffersNeedsToChange) { 302 // here we're guaranteed that mQueue is empty 303 freeAllBuffersLocked(); 304 mBufferCount = mServerBufferCount; 305 if (mBufferCount < minBufferCountNeeded) 306 mBufferCount = minBufferCountNeeded; 307 mCurrentTexture = INVALID_BUFFER_SLOT; 308 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; 309 } 310 311 // look for a free buffer to give to the client 312 found = INVALID_BUFFER_SLOT; 313 foundSync = INVALID_BUFFER_SLOT; 314 dequeuedCount = 0; 315 for (int i = 0; i < mBufferCount; i++) { 316 const int state = mSlots[i].mBufferState; 317 if (state == BufferSlot::DEQUEUED) { 318 dequeuedCount++; 319 } 320 321 // if buffer is FREE it CANNOT be current 322 LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i), 323 "dequeueBuffer: buffer %d is both FREE and current!", i); 324 325 if (ALLOW_DEQUEUE_CURRENT_BUFFER) { 326 if (state == BufferSlot::FREE || i == mCurrentTexture) { 327 foundSync = i; 328 if (i != mCurrentTexture) { 329 found = i; 330 break; 331 } 332 } 333 } else { 334 if (state == BufferSlot::FREE) { 335 foundSync = i; 336 found = i; 337 break; 338 } 339 } 340 } 341 342 // clients are not allowed to dequeue more than one buffer 343 // if they didn't set a buffer count. 344 if (!mClientBufferCount && dequeuedCount) { 345 return -EINVAL; 346 } 347 348 // See whether a buffer has been queued since the last setBufferCount so 349 // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. 350 bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT; 351 if (bufferHasBeenQueued) { 352 // make sure the client is not trying to dequeue more buffers 353 // than allowed. 354 const int avail = mBufferCount - (dequeuedCount+1); 355 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { 356 ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded " 357 "(dequeued=%d)", 358 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), 359 dequeuedCount); 360 return -EBUSY; 361 } 362 } 363 364 // we're in synchronous mode and didn't find a buffer, we need to wait 365 // for some buffers to be consumed 366 tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); 367 if (tryAgain) { 368 mDequeueCondition.wait(mMutex); 369 } 370 } 371 372 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { 373 // foundSync guaranteed to be != INVALID_BUFFER_SLOT 374 found = foundSync; 375 } 376 377 if (found == INVALID_BUFFER_SLOT) { 378 return -EBUSY; 379 } 380 381 const int buf = found; 382 *outBuf = found; 383 384 const bool useDefaultSize = !w && !h; 385 if (useDefaultSize) { 386 // use the default size 387 w = mDefaultWidth; 388 h = mDefaultHeight; 389 } 390 391 const bool updateFormat = (format != 0); 392 if (!updateFormat) { 393 // keep the current (or default) format 394 format = mPixelFormat; 395 } 396 397 // buffer is now in DEQUEUED (but can also be current at the same time, 398 // if we're in synchronous mode) 399 mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 400 401 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 402 if ((buffer == NULL) || 403 (uint32_t(buffer->width) != w) || 404 (uint32_t(buffer->height) != h) || 405 (uint32_t(buffer->format) != format) || 406 ((uint32_t(buffer->usage) & usage) != usage)) 407 { 408 usage |= GraphicBuffer::USAGE_HW_TEXTURE; 409 status_t error; 410 sp<GraphicBuffer> graphicBuffer( 411 mGraphicBufferAlloc->createGraphicBuffer( 412 w, h, format, usage, &error)); 413 if (graphicBuffer == 0) { 414 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer " 415 "failed"); 416 return error; 417 } 418 if (updateFormat) { 419 mPixelFormat = format; 420 } 421 mSlots[buf].mGraphicBuffer = graphicBuffer; 422 mSlots[buf].mRequestBufferCalled = false; 423 if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { 424 eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage); 425 mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; 426 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; 427 } 428 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 429 } 430 return returnFlags; 431 } 432 433 status_t SurfaceTexture::setSynchronousMode(bool enabled) { 434 Mutex::Autolock lock(mMutex); 435 436 if (mAbandoned) { 437 ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); 438 return NO_INIT; 439 } 440 441 status_t err = OK; 442 if (!mAllowSynchronousMode && enabled) 443 return err; 444 445 if (!enabled) { 446 // going to asynchronous mode, drain the queue 447 err = drainQueueLocked(); 448 if (err != NO_ERROR) 449 return err; 450 } 451 452 if (mSynchronousMode != enabled) { 453 // - if we're going to asynchronous mode, the queue is guaranteed to be 454 // empty here 455 // - if the client set the number of buffers, we're guaranteed that 456 // we have at least 3 (because we don't allow less) 457 mSynchronousMode = enabled; 458 mDequeueCondition.signal(); 459 } 460 return err; 461 } 462 463 status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, 464 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 465 ST_LOGV("SurfaceTexture::queueBuffer"); 466 467 sp<FrameAvailableListener> listener; 468 469 { // scope for the lock 470 Mutex::Autolock lock(mMutex); 471 if (mAbandoned) { 472 ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); 473 return NO_INIT; 474 } 475 if (buf < 0 || buf >= mBufferCount) { 476 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", 477 mBufferCount, buf); 478 return -EINVAL; 479 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 480 ST_LOGE("queueBuffer: slot %d is not owned by the client " 481 "(state=%d)", buf, mSlots[buf].mBufferState); 482 return -EINVAL; 483 } else if (buf == mCurrentTexture) { 484 ST_LOGE("queueBuffer: slot %d is current!", buf); 485 return -EINVAL; 486 } else if (!mSlots[buf].mRequestBufferCalled) { 487 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " 488 "buffer", buf); 489 return -EINVAL; 490 } 491 492 if (mSynchronousMode) { 493 // In synchronous mode we queue all buffers in a FIFO. 494 mQueue.push_back(buf); 495 496 // Synchronous mode always signals that an additional frame should 497 // be consumed. 498 listener = mFrameAvailableListener; 499 } else { 500 // In asynchronous mode we only keep the most recent buffer. 501 if (mQueue.empty()) { 502 mQueue.push_back(buf); 503 504 // Asynchronous mode only signals that a frame should be 505 // consumed if no previous frame was pending. If a frame were 506 // pending then the consumer would have already been notified. 507 listener = mFrameAvailableListener; 508 } else { 509 Fifo::iterator front(mQueue.begin()); 510 // buffer currently queued is freed 511 mSlots[*front].mBufferState = BufferSlot::FREE; 512 // and we record the new buffer index in the queued list 513 *front = buf; 514 } 515 } 516 517 mSlots[buf].mBufferState = BufferSlot::QUEUED; 518 mSlots[buf].mCrop = mNextCrop; 519 mSlots[buf].mTransform = mNextTransform; 520 mSlots[buf].mScalingMode = mNextScalingMode; 521 mSlots[buf].mTimestamp = timestamp; 522 mDequeueCondition.signal(); 523 524 *outWidth = mDefaultWidth; 525 *outHeight = mDefaultHeight; 526 *outTransform = 0; 527 } // scope for the lock 528 529 // call back without lock held 530 if (listener != 0) { 531 listener->onFrameAvailable(); 532 } 533 return OK; 534 } 535 536 void SurfaceTexture::cancelBuffer(int buf) { 537 ST_LOGV("SurfaceTexture::cancelBuffer"); 538 Mutex::Autolock lock(mMutex); 539 540 if (mAbandoned) { 541 ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); 542 return; 543 } 544 545 if (buf < 0 || buf >= mBufferCount) { 546 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 547 mBufferCount, buf); 548 return; 549 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 550 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 551 buf, mSlots[buf].mBufferState); 552 return; 553 } 554 mSlots[buf].mBufferState = BufferSlot::FREE; 555 mDequeueCondition.signal(); 556 } 557 558 status_t SurfaceTexture::setCrop(const Rect& crop) { 559 ST_LOGV("SurfaceTexture::setCrop"); 560 Mutex::Autolock lock(mMutex); 561 if (mAbandoned) { 562 ST_LOGE("setCrop: SurfaceTexture has been abandoned!"); 563 return NO_INIT; 564 } 565 mNextCrop = crop; 566 return OK; 567 } 568 569 status_t SurfaceTexture::setTransform(uint32_t transform) { 570 ST_LOGV("SurfaceTexture::setTransform"); 571 Mutex::Autolock lock(mMutex); 572 if (mAbandoned) { 573 ST_LOGE("setTransform: SurfaceTexture has been abandoned!"); 574 return NO_INIT; 575 } 576 mNextTransform = transform; 577 return OK; 578 } 579 580 status_t SurfaceTexture::connect(int api, 581 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 582 ST_LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); 583 Mutex::Autolock lock(mMutex); 584 585 if (mAbandoned) { 586 ST_LOGE("connect: SurfaceTexture has been abandoned!"); 587 return NO_INIT; 588 } 589 590 int err = NO_ERROR; 591 switch (api) { 592 case NATIVE_WINDOW_API_EGL: 593 case NATIVE_WINDOW_API_CPU: 594 case NATIVE_WINDOW_API_MEDIA: 595 case NATIVE_WINDOW_API_CAMERA: 596 if (mConnectedApi != NO_CONNECTED_API) { 597 ST_LOGE("connect: already connected (cur=%d, req=%d)", 598 mConnectedApi, api); 599 err = -EINVAL; 600 } else { 601 mConnectedApi = api; 602 *outWidth = mDefaultWidth; 603 *outHeight = mDefaultHeight; 604 *outTransform = 0; 605 } 606 break; 607 default: 608 err = -EINVAL; 609 break; 610 } 611 return err; 612 } 613 614 status_t SurfaceTexture::disconnect(int api) { 615 ST_LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); 616 Mutex::Autolock lock(mMutex); 617 618 if (mAbandoned) { 619 ST_LOGE("disconnect: SurfaceTexture has been abandoned!"); 620 return NO_INIT; 621 } 622 623 int err = NO_ERROR; 624 switch (api) { 625 case NATIVE_WINDOW_API_EGL: 626 case NATIVE_WINDOW_API_CPU: 627 case NATIVE_WINDOW_API_MEDIA: 628 case NATIVE_WINDOW_API_CAMERA: 629 if (mConnectedApi == api) { 630 drainQueueAndFreeBuffersLocked(); 631 mConnectedApi = NO_CONNECTED_API; 632 mNextCrop.makeInvalid(); 633 mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; 634 mNextTransform = 0; 635 mDequeueCondition.signal(); 636 } else { 637 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", 638 mConnectedApi, api); 639 err = -EINVAL; 640 } 641 break; 642 default: 643 err = -EINVAL; 644 break; 645 } 646 return err; 647 } 648 649 status_t SurfaceTexture::setScalingMode(int mode) { 650 ST_LOGV("SurfaceTexture::setScalingMode(%d)", mode); 651 652 switch (mode) { 653 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 654 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 655 break; 656 default: 657 return BAD_VALUE; 658 } 659 660 Mutex::Autolock lock(mMutex); 661 mNextScalingMode = mode; 662 return OK; 663 } 664 665 status_t SurfaceTexture::updateTexImage() { 666 ST_LOGV("SurfaceTexture::updateTexImage"); 667 Mutex::Autolock lock(mMutex); 668 669 if (mAbandoned) { 670 ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); 671 return NO_INIT; 672 } 673 674 // In asynchronous mode the list is guaranteed to be one buffer 675 // deep, while in synchronous mode we use the oldest buffer. 676 if (!mQueue.empty()) { 677 Fifo::iterator front(mQueue.begin()); 678 int buf = *front; 679 680 // Update the GL texture object. 681 EGLImageKHR image = mSlots[buf].mEglImage; 682 if (image == EGL_NO_IMAGE_KHR) { 683 EGLDisplay dpy = eglGetCurrentDisplay(); 684 if (mSlots[buf].mGraphicBuffer == 0) { 685 ST_LOGE("buffer at slot %d is null", buf); 686 return BAD_VALUE; 687 } 688 image = createImage(dpy, mSlots[buf].mGraphicBuffer); 689 mSlots[buf].mEglImage = image; 690 mSlots[buf].mEglDisplay = dpy; 691 if (image == EGL_NO_IMAGE_KHR) { 692 // NOTE: if dpy was invalid, createImage() is guaranteed to 693 // fail. so we'd end up here. 694 return -EINVAL; 695 } 696 } 697 698 GLint error; 699 while ((error = glGetError()) != GL_NO_ERROR) { 700 ST_LOGW("updateTexImage: clearing GL error: %#04x", error); 701 } 702 703 glBindTexture(mTexTarget, mTexName); 704 glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); 705 706 bool failed = false; 707 while ((error = glGetError()) != GL_NO_ERROR) { 708 ST_LOGE("error binding external texture image %p (slot %d): %#04x", 709 image, buf, error); 710 failed = true; 711 } 712 if (failed) { 713 return -EINVAL; 714 } 715 716 if (mCurrentTexture != INVALID_BUFFER_SLOT) { 717 // The current buffer becomes FREE if it was still in the queued 718 // state. If it has already been given to the client 719 // (synchronous mode), then it stays in DEQUEUED state. 720 if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) 721 mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE; 722 } 723 724 // Update the SurfaceTexture state. 725 mCurrentTexture = buf; 726 mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; 727 mCurrentCrop = mSlots[buf].mCrop; 728 mCurrentTransform = mSlots[buf].mTransform; 729 mCurrentScalingMode = mSlots[buf].mScalingMode; 730 mCurrentTimestamp = mSlots[buf].mTimestamp; 731 computeCurrentTransformMatrix(); 732 733 // Now that we've passed the point at which failures can happen, 734 // it's safe to remove the buffer from the front of the queue. 735 mQueue.erase(front); 736 mDequeueCondition.signal(); 737 } else { 738 // We always bind the texture even if we don't update its contents. 739 glBindTexture(mTexTarget, mTexName); 740 } 741 742 return OK; 743 } 744 745 bool SurfaceTexture::isExternalFormat(uint32_t format) 746 { 747 switch (format) { 748 // supported YUV formats 749 case HAL_PIXEL_FORMAT_YV12: 750 // Legacy/deprecated YUV formats 751 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 752 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 753 case HAL_PIXEL_FORMAT_YCbCr_422_I: 754 return true; 755 } 756 757 // Any OEM format needs to be considered 758 if (format>=0x100 && format<=0x1FF) 759 return true; 760 761 return false; 762 } 763 764 GLenum SurfaceTexture::getCurrentTextureTarget() const { 765 return mTexTarget; 766 } 767 768 void SurfaceTexture::getTransformMatrix(float mtx[16]) { 769 Mutex::Autolock lock(mMutex); 770 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix)); 771 } 772 773 void SurfaceTexture::computeCurrentTransformMatrix() { 774 ST_LOGV("SurfaceTexture::computeCurrentTransformMatrix"); 775 776 float xform[16]; 777 for (int i = 0; i < 16; i++) { 778 xform[i] = mtxIdentity[i]; 779 } 780 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { 781 float result[16]; 782 mtxMul(result, xform, mtxFlipH); 783 for (int i = 0; i < 16; i++) { 784 xform[i] = result[i]; 785 } 786 } 787 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { 788 float result[16]; 789 mtxMul(result, xform, mtxFlipV); 790 for (int i = 0; i < 16; i++) { 791 xform[i] = result[i]; 792 } 793 } 794 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 795 float result[16]; 796 mtxMul(result, xform, mtxRot90); 797 for (int i = 0; i < 16; i++) { 798 xform[i] = result[i]; 799 } 800 } 801 802 sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer); 803 float tx, ty, sx, sy; 804 if (!mCurrentCrop.isEmpty()) { 805 // In order to prevent bilinear sampling at the of the crop rectangle we 806 // may need to shrink it by 2 texels in each direction. Normally this 807 // would just need to take 1/2 a texel off each end, but because the 808 // chroma channels will likely be subsampled we need to chop off a whole 809 // texel. This will cause artifacts if someone does nearest sampling 810 // with 1:1 pixel:texel ratio, but it's impossible to simultaneously 811 // accomodate the bilinear and nearest sampling uses. 812 // 813 // If nearest sampling turns out to be a desirable usage of these 814 // textures then we could add the ability to switch a SurfaceTexture to 815 // nearest-mode. Preferably, however, the image producers (video 816 // decoder, camera, etc.) would simply not use a crop rectangle (or at 817 // least not tell the framework about it) so that the GPU can do the 818 // correct edge behavior. 819 int xshrink = 0, yshrink = 0; 820 if (mCurrentCrop.left > 0) { 821 tx = float(mCurrentCrop.left + 1) / float(buf->getWidth()); 822 xshrink++; 823 } else { 824 tx = 0.0f; 825 } 826 if (mCurrentCrop.right < int32_t(buf->getWidth())) { 827 xshrink++; 828 } 829 if (mCurrentCrop.bottom < int32_t(buf->getHeight())) { 830 ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) / 831 float(buf->getHeight()); 832 yshrink++; 833 } else { 834 ty = 0.0f; 835 } 836 if (mCurrentCrop.top > 0) { 837 yshrink++; 838 } 839 sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth()); 840 sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight()); 841 } else { 842 tx = 0.0f; 843 ty = 0.0f; 844 sx = 1.0f; 845 sy = 1.0f; 846 } 847 float crop[16] = { 848 sx, 0, 0, 0, 849 0, sy, 0, 0, 850 0, 0, 1, 0, 851 tx, ty, 0, 1, 852 }; 853 854 float mtxBeforeFlipV[16]; 855 mtxMul(mtxBeforeFlipV, crop, xform); 856 857 // SurfaceFlinger expects the top of its window textures to be at a Y 858 // coordinate of 0, so SurfaceTexture must behave the same way. We don't 859 // want to expose this to applications, however, so we must add an 860 // additional vertical flip to the transform after all the other transforms. 861 mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV); 862 } 863 864 nsecs_t SurfaceTexture::getTimestamp() { 865 ST_LOGV("SurfaceTexture::getTimestamp"); 866 Mutex::Autolock lock(mMutex); 867 return mCurrentTimestamp; 868 } 869 870 void SurfaceTexture::setFrameAvailableListener( 871 const sp<FrameAvailableListener>& listener) { 872 ST_LOGV("SurfaceTexture::setFrameAvailableListener"); 873 Mutex::Autolock lock(mMutex); 874 mFrameAvailableListener = listener; 875 } 876 877 void SurfaceTexture::freeBufferLocked(int i) { 878 mSlots[i].mGraphicBuffer = 0; 879 mSlots[i].mBufferState = BufferSlot::FREE; 880 if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { 881 eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); 882 mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; 883 mSlots[i].mEglDisplay = EGL_NO_DISPLAY; 884 } 885 } 886 887 void SurfaceTexture::freeAllBuffersLocked() { 888 LOGW_IF(!mQueue.isEmpty(), 889 "freeAllBuffersLocked called but mQueue is not empty"); 890 mCurrentTexture = INVALID_BUFFER_SLOT; 891 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 892 freeBufferLocked(i); 893 } 894 } 895 896 void SurfaceTexture::freeAllBuffersExceptHeadLocked() { 897 LOGW_IF(!mQueue.isEmpty(), 898 "freeAllBuffersExceptCurrentLocked called but mQueue is not empty"); 899 int head = -1; 900 if (!mQueue.empty()) { 901 Fifo::iterator front(mQueue.begin()); 902 head = *front; 903 } 904 mCurrentTexture = INVALID_BUFFER_SLOT; 905 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 906 if (i != head) { 907 freeBufferLocked(i); 908 } 909 } 910 } 911 912 status_t SurfaceTexture::drainQueueLocked() { 913 while (mSynchronousMode && !mQueue.isEmpty()) { 914 mDequeueCondition.wait(mMutex); 915 if (mAbandoned) { 916 ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); 917 return NO_INIT; 918 } 919 if (mConnectedApi == NO_CONNECTED_API) { 920 ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!"); 921 return NO_INIT; 922 } 923 } 924 return NO_ERROR; 925 } 926 927 status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() { 928 status_t err = drainQueueLocked(); 929 if (err == NO_ERROR) { 930 if (mSynchronousMode) { 931 freeAllBuffersLocked(); 932 } else { 933 freeAllBuffersExceptHeadLocked(); 934 } 935 } 936 return err; 937 } 938 939 EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, 940 const sp<GraphicBuffer>& graphicBuffer) { 941 EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); 942 EGLint attrs[] = { 943 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 944 EGL_NONE, 945 }; 946 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 947 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); 948 if (image == EGL_NO_IMAGE_KHR) { 949 EGLint error = eglGetError(); 950 ST_LOGE("error creating EGLImage: %#x", error); 951 } 952 return image; 953 } 954 955 sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const { 956 Mutex::Autolock lock(mMutex); 957 return mCurrentTextureBuf; 958 } 959 960 Rect SurfaceTexture::getCurrentCrop() const { 961 Mutex::Autolock lock(mMutex); 962 return mCurrentCrop; 963 } 964 965 uint32_t SurfaceTexture::getCurrentTransform() const { 966 Mutex::Autolock lock(mMutex); 967 return mCurrentTransform; 968 } 969 970 uint32_t SurfaceTexture::getCurrentScalingMode() const { 971 Mutex::Autolock lock(mMutex); 972 return mCurrentScalingMode; 973 } 974 975 int SurfaceTexture::query(int what, int* outValue) 976 { 977 Mutex::Autolock lock(mMutex); 978 979 if (mAbandoned) { 980 ST_LOGE("query: SurfaceTexture has been abandoned!"); 981 return NO_INIT; 982 } 983 984 int value; 985 switch (what) { 986 case NATIVE_WINDOW_WIDTH: 987 value = mDefaultWidth; 988 break; 989 case NATIVE_WINDOW_HEIGHT: 990 value = mDefaultHeight; 991 break; 992 case NATIVE_WINDOW_FORMAT: 993 value = mPixelFormat; 994 break; 995 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 996 value = mSynchronousMode ? 997 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 998 break; 999 default: 1000 return BAD_VALUE; 1001 } 1002 outValue[0] = value; 1003 return NO_ERROR; 1004 } 1005 1006 void SurfaceTexture::abandon() { 1007 Mutex::Autolock lock(mMutex); 1008 mQueue.clear(); 1009 mAbandoned = true; 1010 mCurrentTextureBuf.clear(); 1011 freeAllBuffersLocked(); 1012 mDequeueCondition.signal(); 1013 } 1014 1015 void SurfaceTexture::setName(const String8& name) { 1016 mName = name; 1017 } 1018 1019 void SurfaceTexture::dump(String8& result) const 1020 { 1021 char buffer[1024]; 1022 dump(result, "", buffer, 1024); 1023 } 1024 1025 void SurfaceTexture::dump(String8& result, const char* prefix, 1026 char* buffer, size_t SIZE) const 1027 { 1028 Mutex::Autolock _l(mMutex); 1029 snprintf(buffer, SIZE, 1030 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 1031 "mPixelFormat=%d, mTexName=%d\n", 1032 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, 1033 mDefaultHeight, mPixelFormat, mTexName); 1034 result.append(buffer); 1035 1036 String8 fifo; 1037 int fifoSize = 0; 1038 Fifo::const_iterator i(mQueue.begin()); 1039 while (i != mQueue.end()) { 1040 snprintf(buffer, SIZE, "%02d ", *i++); 1041 fifoSize++; 1042 fifo.append(buffer); 1043 } 1044 1045 snprintf(buffer, SIZE, 1046 "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n" 1047 "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n" 1048 , 1049 prefix, mCurrentCrop.left, 1050 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, 1051 mCurrentTransform, mCurrentTexture, 1052 prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, 1053 mNextCrop.bottom, mNextTransform, fifoSize, fifo.string() 1054 ); 1055 result.append(buffer); 1056 1057 struct { 1058 const char * operator()(int state) const { 1059 switch (state) { 1060 case BufferSlot::DEQUEUED: return "DEQUEUED"; 1061 case BufferSlot::QUEUED: return "QUEUED"; 1062 case BufferSlot::FREE: return "FREE"; 1063 default: return "Unknown"; 1064 } 1065 } 1066 } stateName; 1067 1068 for (int i=0 ; i<mBufferCount ; i++) { 1069 const BufferSlot& slot(mSlots[i]); 1070 snprintf(buffer, SIZE, 1071 "%s%s[%02d] " 1072 "state=%-8s, crop=[%d,%d,%d,%d], " 1073 "transform=0x%02x, timestamp=%lld", 1074 prefix, (i==mCurrentTexture)?">":" ", i, 1075 stateName(slot.mBufferState), 1076 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, 1077 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp 1078 ); 1079 result.append(buffer); 1080 1081 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); 1082 if (buf != NULL) { 1083 snprintf(buffer, SIZE, 1084 ", %p [%4ux%4u:%4u,%3X]", 1085 buf->handle, buf->width, buf->height, buf->stride, 1086 buf->format); 1087 result.append(buffer); 1088 } 1089 result.append("\n"); 1090 } 1091 } 1092 1093 static void mtxMul(float out[16], const float a[16], const float b[16]) { 1094 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; 1095 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; 1096 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; 1097 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; 1098 1099 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; 1100 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; 1101 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; 1102 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; 1103 1104 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; 1105 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; 1106 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; 1107 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; 1108 1109 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; 1110 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; 1111 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; 1112 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; 1113 } 1114 1115 }; // namespace android 1116