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