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