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