SurfaceTexture.cpp revision f1e868f68204bf469a0c162b84af0e651d513ac8
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 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 441 } 442 ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", buf, 443 mSlots[buf].mGraphicBuffer->handle, returnFlags); 444 return returnFlags; 445} 446 447status_t SurfaceTexture::setSynchronousMode(bool enabled) { 448 ST_LOGV("setSynchronousMode: enabled=%d", enabled); 449 Mutex::Autolock lock(mMutex); 450 451 if (mAbandoned) { 452 ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); 453 return NO_INIT; 454 } 455 456 status_t err = OK; 457 if (!mAllowSynchronousMode && enabled) 458 return err; 459 460 if (!enabled) { 461 // going to asynchronous mode, drain the queue 462 err = drainQueueLocked(); 463 if (err != NO_ERROR) 464 return err; 465 } 466 467 if (mSynchronousMode != enabled) { 468 // - if we're going to asynchronous mode, the queue is guaranteed to be 469 // empty here 470 // - if the client set the number of buffers, we're guaranteed that 471 // we have at least 3 (because we don't allow less) 472 mSynchronousMode = enabled; 473 mDequeueCondition.signal(); 474 } 475 return err; 476} 477 478status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, 479 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 480 ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp); 481 482 sp<FrameAvailableListener> listener; 483 484 { // scope for the lock 485 Mutex::Autolock lock(mMutex); 486 if (mAbandoned) { 487 ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); 488 return NO_INIT; 489 } 490 if (buf < 0 || buf >= mBufferCount) { 491 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", 492 mBufferCount, buf); 493 return -EINVAL; 494 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 495 ST_LOGE("queueBuffer: slot %d is not owned by the client " 496 "(state=%d)", buf, mSlots[buf].mBufferState); 497 return -EINVAL; 498 } else if (buf == mCurrentTexture) { 499 ST_LOGE("queueBuffer: slot %d is current!", buf); 500 return -EINVAL; 501 } else if (!mSlots[buf].mRequestBufferCalled) { 502 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " 503 "buffer", buf); 504 return -EINVAL; 505 } 506 507 if (mSynchronousMode) { 508 // In synchronous mode we queue all buffers in a FIFO. 509 mQueue.push_back(buf); 510 511 // Synchronous mode always signals that an additional frame should 512 // be consumed. 513 listener = mFrameAvailableListener; 514 } else { 515 // In asynchronous mode we only keep the most recent buffer. 516 if (mQueue.empty()) { 517 mQueue.push_back(buf); 518 519 // Asynchronous mode only signals that a frame should be 520 // consumed if no previous frame was pending. If a frame were 521 // pending then the consumer would have already been notified. 522 listener = mFrameAvailableListener; 523 } else { 524 Fifo::iterator front(mQueue.begin()); 525 // buffer currently queued is freed 526 mSlots[*front].mBufferState = BufferSlot::FREE; 527 // and we record the new buffer index in the queued list 528 *front = buf; 529 } 530 } 531 532 mSlots[buf].mBufferState = BufferSlot::QUEUED; 533 mSlots[buf].mCrop = mNextCrop; 534 mSlots[buf].mTransform = mNextTransform; 535 mSlots[buf].mScalingMode = mNextScalingMode; 536 mSlots[buf].mTimestamp = timestamp; 537 mFrameCounter++; 538 mSlots[buf].mFrameNumber = mFrameCounter; 539 540 mDequeueCondition.signal(); 541 542 *outWidth = mDefaultWidth; 543 *outHeight = mDefaultHeight; 544 *outTransform = 0; 545 } // scope for the lock 546 547 // call back without lock held 548 if (listener != 0) { 549 listener->onFrameAvailable(); 550 } 551 return OK; 552} 553 554void SurfaceTexture::cancelBuffer(int buf) { 555 ST_LOGV("cancelBuffer: slot=%d", buf); 556 Mutex::Autolock lock(mMutex); 557 558 if (mAbandoned) { 559 ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); 560 return; 561 } 562 563 if (buf < 0 || buf >= mBufferCount) { 564 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 565 mBufferCount, buf); 566 return; 567 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 568 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 569 buf, mSlots[buf].mBufferState); 570 return; 571 } 572 mSlots[buf].mBufferState = BufferSlot::FREE; 573 mSlots[buf].mFrameNumber = 0; 574 mDequeueCondition.signal(); 575} 576 577status_t SurfaceTexture::setCrop(const Rect& crop) { 578 ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right, 579 crop.bottom); 580 581 Mutex::Autolock lock(mMutex); 582 if (mAbandoned) { 583 ST_LOGE("setCrop: SurfaceTexture has been abandoned!"); 584 return NO_INIT; 585 } 586 mNextCrop = crop; 587 return OK; 588} 589 590status_t SurfaceTexture::setTransform(uint32_t transform) { 591 ST_LOGV("setTransform: xform=%#x", transform); 592 Mutex::Autolock lock(mMutex); 593 if (mAbandoned) { 594 ST_LOGE("setTransform: SurfaceTexture has been abandoned!"); 595 return NO_INIT; 596 } 597 mNextTransform = transform; 598 return OK; 599} 600 601status_t SurfaceTexture::connect(int api, 602 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 603 ST_LOGV("connect: api=%d", api); 604 Mutex::Autolock lock(mMutex); 605 606 if (mAbandoned) { 607 ST_LOGE("connect: SurfaceTexture has been abandoned!"); 608 return NO_INIT; 609 } 610 611 int err = NO_ERROR; 612 switch (api) { 613 case NATIVE_WINDOW_API_EGL: 614 case NATIVE_WINDOW_API_CPU: 615 case NATIVE_WINDOW_API_MEDIA: 616 case NATIVE_WINDOW_API_CAMERA: 617 if (mConnectedApi != NO_CONNECTED_API) { 618 ST_LOGE("connect: already connected (cur=%d, req=%d)", 619 mConnectedApi, api); 620 err = -EINVAL; 621 } else { 622 mConnectedApi = api; 623 *outWidth = mDefaultWidth; 624 *outHeight = mDefaultHeight; 625 *outTransform = 0; 626 } 627 break; 628 default: 629 err = -EINVAL; 630 break; 631 } 632 return err; 633} 634 635status_t SurfaceTexture::disconnect(int api) { 636 ST_LOGV("disconnect: api=%d", api); 637 Mutex::Autolock lock(mMutex); 638 639 if (mAbandoned) { 640 ST_LOGE("disconnect: SurfaceTexture has been abandoned!"); 641 return NO_INIT; 642 } 643 644 int err = NO_ERROR; 645 switch (api) { 646 case NATIVE_WINDOW_API_EGL: 647 case NATIVE_WINDOW_API_CPU: 648 case NATIVE_WINDOW_API_MEDIA: 649 case NATIVE_WINDOW_API_CAMERA: 650 if (mConnectedApi == api) { 651 drainQueueAndFreeBuffersLocked(); 652 mConnectedApi = NO_CONNECTED_API; 653 mNextCrop.makeInvalid(); 654 mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; 655 mNextTransform = 0; 656 mDequeueCondition.signal(); 657 } else { 658 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", 659 mConnectedApi, api); 660 err = -EINVAL; 661 } 662 break; 663 default: 664 ST_LOGE("disconnect: unknown API %d", api); 665 err = -EINVAL; 666 break; 667 } 668 return err; 669} 670 671status_t SurfaceTexture::setScalingMode(int mode) { 672 ST_LOGV("setScalingMode: mode=%d", mode); 673 674 switch (mode) { 675 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 676 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 677 break; 678 default: 679 ST_LOGE("unknown scaling mode: %d", mode); 680 return BAD_VALUE; 681 } 682 683 Mutex::Autolock lock(mMutex); 684 mNextScalingMode = mode; 685 return OK; 686} 687 688status_t SurfaceTexture::updateTexImage() { 689 ST_LOGV("updateTexImage"); 690 Mutex::Autolock lock(mMutex); 691 692 if (mAbandoned) { 693 ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); 694 return NO_INIT; 695 } 696 697 // In asynchronous mode the list is guaranteed to be one buffer 698 // deep, while in synchronous mode we use the oldest buffer. 699 if (!mQueue.empty()) { 700 Fifo::iterator front(mQueue.begin()); 701 int buf = *front; 702 703 // Update the GL texture object. 704 EGLImageKHR image = mSlots[buf].mEglImage; 705 if (image == EGL_NO_IMAGE_KHR) { 706 EGLDisplay dpy = eglGetCurrentDisplay(); 707 if (mSlots[buf].mGraphicBuffer == 0) { 708 ST_LOGE("buffer at slot %d is null", buf); 709 return BAD_VALUE; 710 } 711 image = createImage(dpy, mSlots[buf].mGraphicBuffer); 712 mSlots[buf].mEglImage = image; 713 mSlots[buf].mEglDisplay = dpy; 714 if (image == EGL_NO_IMAGE_KHR) { 715 // NOTE: if dpy was invalid, createImage() is guaranteed to 716 // fail. so we'd end up here. 717 return -EINVAL; 718 } 719 } 720 721 GLint error; 722 while ((error = glGetError()) != GL_NO_ERROR) { 723 ST_LOGW("updateTexImage: clearing GL error: %#04x", error); 724 } 725 726 glBindTexture(mTexTarget, mTexName); 727 glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); 728 729 bool failed = false; 730 while ((error = glGetError()) != GL_NO_ERROR) { 731 ST_LOGE("error binding external texture image %p (slot %d): %#04x", 732 image, buf, error); 733 failed = true; 734 } 735 if (failed) { 736 return -EINVAL; 737 } 738 739 ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, 740 mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf, 741 mSlots[buf].mGraphicBuffer->handle); 742 743 if (mCurrentTexture != INVALID_BUFFER_SLOT) { 744 // The current buffer becomes FREE if it was still in the queued 745 // state. If it has already been given to the client 746 // (synchronous mode), then it stays in DEQUEUED state. 747 if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) 748 mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE; 749 } 750 751 // Update the SurfaceTexture state. 752 mCurrentTexture = buf; 753 mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; 754 mCurrentCrop = mSlots[buf].mCrop; 755 mCurrentTransform = mSlots[buf].mTransform; 756 mCurrentScalingMode = mSlots[buf].mScalingMode; 757 mCurrentTimestamp = mSlots[buf].mTimestamp; 758 computeCurrentTransformMatrix(); 759 760 // Now that we've passed the point at which failures can happen, 761 // it's safe to remove the buffer from the front of the queue. 762 mQueue.erase(front); 763 mDequeueCondition.signal(); 764 } else { 765 // We always bind the texture even if we don't update its contents. 766 glBindTexture(mTexTarget, mTexName); 767 } 768 769 return OK; 770} 771 772bool SurfaceTexture::isExternalFormat(uint32_t format) 773{ 774 switch (format) { 775 // supported YUV formats 776 case HAL_PIXEL_FORMAT_YV12: 777 // Legacy/deprecated YUV formats 778 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 779 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 780 case HAL_PIXEL_FORMAT_YCbCr_422_I: 781 return true; 782 } 783 784 // Any OEM format needs to be considered 785 if (format>=0x100 && format<=0x1FF) 786 return true; 787 788 return false; 789} 790 791GLenum SurfaceTexture::getCurrentTextureTarget() const { 792 return mTexTarget; 793} 794 795void SurfaceTexture::getTransformMatrix(float mtx[16]) { 796 Mutex::Autolock lock(mMutex); 797 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix)); 798} 799 800void SurfaceTexture::computeCurrentTransformMatrix() { 801 ST_LOGV("computeCurrentTransformMatrix"); 802 803 float xform[16]; 804 for (int i = 0; i < 16; i++) { 805 xform[i] = mtxIdentity[i]; 806 } 807 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { 808 float result[16]; 809 mtxMul(result, xform, mtxFlipH); 810 for (int i = 0; i < 16; i++) { 811 xform[i] = result[i]; 812 } 813 } 814 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { 815 float result[16]; 816 mtxMul(result, xform, mtxFlipV); 817 for (int i = 0; i < 16; i++) { 818 xform[i] = result[i]; 819 } 820 } 821 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 822 float result[16]; 823 mtxMul(result, xform, mtxRot90); 824 for (int i = 0; i < 16; i++) { 825 xform[i] = result[i]; 826 } 827 } 828 829 sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer); 830 float tx, ty, sx, sy; 831 if (!mCurrentCrop.isEmpty()) { 832 // In order to prevent bilinear sampling at the of the crop rectangle we 833 // may need to shrink it by 2 texels in each direction. Normally this 834 // would just need to take 1/2 a texel off each end, but because the 835 // chroma channels will likely be subsampled we need to chop off a whole 836 // texel. This will cause artifacts if someone does nearest sampling 837 // with 1:1 pixel:texel ratio, but it's impossible to simultaneously 838 // accomodate the bilinear and nearest sampling uses. 839 // 840 // If nearest sampling turns out to be a desirable usage of these 841 // textures then we could add the ability to switch a SurfaceTexture to 842 // nearest-mode. Preferably, however, the image producers (video 843 // decoder, camera, etc.) would simply not use a crop rectangle (or at 844 // least not tell the framework about it) so that the GPU can do the 845 // correct edge behavior. 846 int xshrink = 0, yshrink = 0; 847 if (mCurrentCrop.left > 0) { 848 tx = float(mCurrentCrop.left + 1) / float(buf->getWidth()); 849 xshrink++; 850 } else { 851 tx = 0.0f; 852 } 853 if (mCurrentCrop.right < int32_t(buf->getWidth())) { 854 xshrink++; 855 } 856 if (mCurrentCrop.bottom < int32_t(buf->getHeight())) { 857 ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) / 858 float(buf->getHeight()); 859 yshrink++; 860 } else { 861 ty = 0.0f; 862 } 863 if (mCurrentCrop.top > 0) { 864 yshrink++; 865 } 866 sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth()); 867 sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight()); 868 } else { 869 tx = 0.0f; 870 ty = 0.0f; 871 sx = 1.0f; 872 sy = 1.0f; 873 } 874 float crop[16] = { 875 sx, 0, 0, 0, 876 0, sy, 0, 0, 877 0, 0, 1, 0, 878 tx, ty, 0, 1, 879 }; 880 881 float mtxBeforeFlipV[16]; 882 mtxMul(mtxBeforeFlipV, crop, xform); 883 884 // SurfaceFlinger expects the top of its window textures to be at a Y 885 // coordinate of 0, so SurfaceTexture must behave the same way. We don't 886 // want to expose this to applications, however, so we must add an 887 // additional vertical flip to the transform after all the other transforms. 888 mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV); 889} 890 891nsecs_t SurfaceTexture::getTimestamp() { 892 ST_LOGV("getTimestamp"); 893 Mutex::Autolock lock(mMutex); 894 return mCurrentTimestamp; 895} 896 897void SurfaceTexture::setFrameAvailableListener( 898 const sp<FrameAvailableListener>& listener) { 899 ST_LOGV("setFrameAvailableListener"); 900 Mutex::Autolock lock(mMutex); 901 mFrameAvailableListener = listener; 902} 903 904void SurfaceTexture::freeBufferLocked(int i) { 905 mSlots[i].mGraphicBuffer = 0; 906 mSlots[i].mBufferState = BufferSlot::FREE; 907 mSlots[i].mFrameNumber = 0; 908 if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { 909 eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); 910 mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; 911 mSlots[i].mEglDisplay = EGL_NO_DISPLAY; 912 } 913} 914 915void SurfaceTexture::freeAllBuffersLocked() { 916 LOGW_IF(!mQueue.isEmpty(), 917 "freeAllBuffersLocked called but mQueue is not empty"); 918 mCurrentTexture = INVALID_BUFFER_SLOT; 919 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 920 freeBufferLocked(i); 921 } 922} 923 924void SurfaceTexture::freeAllBuffersExceptHeadLocked() { 925 LOGW_IF(!mQueue.isEmpty(), 926 "freeAllBuffersExceptCurrentLocked called but mQueue is not empty"); 927 int head = -1; 928 if (!mQueue.empty()) { 929 Fifo::iterator front(mQueue.begin()); 930 head = *front; 931 } 932 mCurrentTexture = INVALID_BUFFER_SLOT; 933 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 934 if (i != head) { 935 freeBufferLocked(i); 936 } 937 } 938} 939 940status_t SurfaceTexture::drainQueueLocked() { 941 while (mSynchronousMode && !mQueue.isEmpty()) { 942 mDequeueCondition.wait(mMutex); 943 if (mAbandoned) { 944 ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); 945 return NO_INIT; 946 } 947 if (mConnectedApi == NO_CONNECTED_API) { 948 ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!"); 949 return NO_INIT; 950 } 951 } 952 return NO_ERROR; 953} 954 955status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() { 956 status_t err = drainQueueLocked(); 957 if (err == NO_ERROR) { 958 if (mSynchronousMode) { 959 freeAllBuffersLocked(); 960 } else { 961 freeAllBuffersExceptHeadLocked(); 962 } 963 } 964 return err; 965} 966 967EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, 968 const sp<GraphicBuffer>& graphicBuffer) { 969 EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); 970 EGLint attrs[] = { 971 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 972 EGL_NONE, 973 }; 974 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 975 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); 976 if (image == EGL_NO_IMAGE_KHR) { 977 EGLint error = eglGetError(); 978 ST_LOGE("error creating EGLImage: %#x", error); 979 } 980 return image; 981} 982 983sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const { 984 Mutex::Autolock lock(mMutex); 985 return mCurrentTextureBuf; 986} 987 988Rect SurfaceTexture::getCurrentCrop() const { 989 Mutex::Autolock lock(mMutex); 990 return mCurrentCrop; 991} 992 993uint32_t SurfaceTexture::getCurrentTransform() const { 994 Mutex::Autolock lock(mMutex); 995 return mCurrentTransform; 996} 997 998uint32_t SurfaceTexture::getCurrentScalingMode() const { 999 Mutex::Autolock lock(mMutex); 1000 return mCurrentScalingMode; 1001} 1002 1003int SurfaceTexture::query(int what, int* outValue) 1004{ 1005 Mutex::Autolock lock(mMutex); 1006 1007 if (mAbandoned) { 1008 ST_LOGE("query: SurfaceTexture has been abandoned!"); 1009 return NO_INIT; 1010 } 1011 1012 int value; 1013 switch (what) { 1014 case NATIVE_WINDOW_WIDTH: 1015 value = mDefaultWidth; 1016 break; 1017 case NATIVE_WINDOW_HEIGHT: 1018 value = mDefaultHeight; 1019 break; 1020 case NATIVE_WINDOW_FORMAT: 1021 value = mPixelFormat; 1022 break; 1023 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 1024 value = mSynchronousMode ? 1025 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 1026 break; 1027 default: 1028 return BAD_VALUE; 1029 } 1030 outValue[0] = value; 1031 return NO_ERROR; 1032} 1033 1034void SurfaceTexture::abandon() { 1035 Mutex::Autolock lock(mMutex); 1036 mQueue.clear(); 1037 mAbandoned = true; 1038 mCurrentTextureBuf.clear(); 1039 freeAllBuffersLocked(); 1040 mDequeueCondition.signal(); 1041} 1042 1043void SurfaceTexture::setName(const String8& name) { 1044 mName = name; 1045} 1046 1047void SurfaceTexture::dump(String8& result) const 1048{ 1049 char buffer[1024]; 1050 dump(result, "", buffer, 1024); 1051} 1052 1053void SurfaceTexture::dump(String8& result, const char* prefix, 1054 char* buffer, size_t SIZE) const 1055{ 1056 Mutex::Autolock _l(mMutex); 1057 snprintf(buffer, SIZE, 1058 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 1059 "mPixelFormat=%d, mTexName=%d\n", 1060 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, 1061 mDefaultHeight, mPixelFormat, mTexName); 1062 result.append(buffer); 1063 1064 String8 fifo; 1065 int fifoSize = 0; 1066 Fifo::const_iterator i(mQueue.begin()); 1067 while (i != mQueue.end()) { 1068 snprintf(buffer, SIZE, "%02d ", *i++); 1069 fifoSize++; 1070 fifo.append(buffer); 1071 } 1072 1073 snprintf(buffer, SIZE, 1074 "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n" 1075 "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n" 1076 , 1077 prefix, mCurrentCrop.left, 1078 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, 1079 mCurrentTransform, mCurrentTexture, 1080 prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, 1081 mNextCrop.bottom, mNextTransform, fifoSize, fifo.string() 1082 ); 1083 result.append(buffer); 1084 1085 struct { 1086 const char * operator()(int state) const { 1087 switch (state) { 1088 case BufferSlot::DEQUEUED: return "DEQUEUED"; 1089 case BufferSlot::QUEUED: return "QUEUED"; 1090 case BufferSlot::FREE: return "FREE"; 1091 default: return "Unknown"; 1092 } 1093 } 1094 } stateName; 1095 1096 for (int i=0 ; i<mBufferCount ; i++) { 1097 const BufferSlot& slot(mSlots[i]); 1098 snprintf(buffer, SIZE, 1099 "%s%s[%02d] " 1100 "state=%-8s, crop=[%d,%d,%d,%d], " 1101 "transform=0x%02x, timestamp=%lld", 1102 prefix, (i==mCurrentTexture)?">":" ", i, 1103 stateName(slot.mBufferState), 1104 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, 1105 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp 1106 ); 1107 result.append(buffer); 1108 1109 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); 1110 if (buf != NULL) { 1111 snprintf(buffer, SIZE, 1112 ", %p [%4ux%4u:%4u,%3X]", 1113 buf->handle, buf->width, buf->height, buf->stride, 1114 buf->format); 1115 result.append(buffer); 1116 } 1117 result.append("\n"); 1118 } 1119} 1120 1121static void mtxMul(float out[16], const float a[16], const float b[16]) { 1122 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; 1123 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; 1124 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; 1125 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; 1126 1127 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; 1128 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; 1129 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; 1130 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; 1131 1132 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; 1133 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; 1134 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; 1135 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; 1136 1137 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; 1138 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; 1139 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; 1140 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; 1141} 1142 1143}; // namespace android 1144