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