SurfaceTexture.cpp revision 44e9e0d825aef362a3413dfd63812962f5de1b1a
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 // See whether a buffer has been queued since the last setBufferCount so 289 // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. 290 bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT; 291 if (bufferHasBeenQueued) { 292 // make sure the client is not trying to dequeue more buffers 293 // than allowed. 294 const int avail = mBufferCount - (dequeuedCount+1); 295 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { 296 LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", 297 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), 298 dequeuedCount); 299 return -EBUSY; 300 } 301 } 302 303 // we're in synchronous mode and didn't find a buffer, we need to wait 304 // for for some buffers to be consumed 305 tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); 306 if (tryAgain) { 307 mDequeueCondition.wait(mMutex); 308 } 309 } 310 311 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { 312 // foundSync guaranteed to be != INVALID_BUFFER_SLOT 313 found = foundSync; 314 } 315 316 if (found == INVALID_BUFFER_SLOT) { 317 return -EBUSY; 318 } 319 320 const int buf = found; 321 *outBuf = found; 322 323 const bool useDefaultSize = !w && !h; 324 if (useDefaultSize) { 325 // use the default size 326 w = mDefaultWidth; 327 h = mDefaultHeight; 328 } 329 330 const bool updateFormat = (format != 0); 331 if (!updateFormat) { 332 // keep the current (or default) format 333 format = mPixelFormat; 334 } 335 336 // buffer is now in DEQUEUED (but can also be current at the same time, 337 // if we're in synchronous mode) 338 mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 339 340 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 341 if ((buffer == NULL) || 342 (uint32_t(buffer->width) != w) || 343 (uint32_t(buffer->height) != h) || 344 (uint32_t(buffer->format) != format) || 345 ((uint32_t(buffer->usage) & usage) != usage)) 346 { 347 usage |= GraphicBuffer::USAGE_HW_TEXTURE; 348 sp<GraphicBuffer> graphicBuffer( 349 mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage)); 350 if (graphicBuffer == 0) { 351 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 352 return NO_MEMORY; 353 } 354 if (updateFormat) { 355 mPixelFormat = format; 356 } 357 mSlots[buf].mGraphicBuffer = graphicBuffer; 358 mSlots[buf].mRequestBufferCalled = false; 359 if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { 360 eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage); 361 mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; 362 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; 363 } 364 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 365 } 366 return returnFlags; 367} 368 369status_t SurfaceTexture::setSynchronousMode(bool enabled) { 370 Mutex::Autolock lock(mMutex); 371 372 status_t err = OK; 373 if (!enabled) { 374 // going to asynchronous mode, drain the queue 375 while (mSynchronousMode != enabled && !mQueue.isEmpty()) { 376 mDequeueCondition.wait(mMutex); 377 } 378 } 379 380 if (mSynchronousMode != enabled) { 381 // - if we're going to asynchronous mode, the queue is guaranteed to be 382 // empty here 383 // - if the client set the number of buffers, we're guaranteed that 384 // we have at least 3 (because we don't allow less) 385 mSynchronousMode = enabled; 386 mDequeueCondition.signal(); 387 } 388 return err; 389} 390 391status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { 392 LOGV("SurfaceTexture::queueBuffer"); 393 394 sp<FrameAvailableListener> listener; 395 396 { // scope for the lock 397 Mutex::Autolock lock(mMutex); 398 if (buf < 0 || buf >= mBufferCount) { 399 LOGE("queueBuffer: slot index out of range [0, %d]: %d", 400 mBufferCount, buf); 401 return -EINVAL; 402 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 403 LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", 404 buf, mSlots[buf].mBufferState); 405 return -EINVAL; 406 } else if (buf == mCurrentTexture) { 407 LOGE("queueBuffer: slot %d is current!", buf); 408 return -EINVAL; 409 } else if (!mSlots[buf].mRequestBufferCalled) { 410 LOGE("queueBuffer: slot %d was enqueued without requesting a " 411 "buffer", buf); 412 return -EINVAL; 413 } 414 415 if (mQueue.empty()) { 416 listener = mFrameAvailableListener; 417 } 418 419 if (mSynchronousMode) { 420 // in synchronous mode we queue all buffers in a FIFO 421 mQueue.push_back(buf); 422 } else { 423 // in asynchronous mode we only keep the most recent buffer 424 if (mQueue.empty()) { 425 mQueue.push_back(buf); 426 } else { 427 Fifo::iterator front(mQueue.begin()); 428 // buffer currently queued is freed 429 mSlots[*front].mBufferState = BufferSlot::FREE; 430 // and we record the new buffer index in the queued list 431 *front = buf; 432 } 433 } 434 435 mSlots[buf].mBufferState = BufferSlot::QUEUED; 436 mSlots[buf].mCrop = mNextCrop; 437 mSlots[buf].mTransform = mNextTransform; 438 mSlots[buf].mTimestamp = timestamp; 439 mDequeueCondition.signal(); 440 } // scope for the lock 441 442 // call back without lock held 443 if (listener != 0) { 444 listener->onFrameAvailable(); 445 } 446 return OK; 447} 448 449void SurfaceTexture::cancelBuffer(int buf) { 450 LOGV("SurfaceTexture::cancelBuffer"); 451 Mutex::Autolock lock(mMutex); 452 if (buf < 0 || buf >= mBufferCount) { 453 LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 454 mBufferCount, buf); 455 return; 456 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 457 LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 458 buf, mSlots[buf].mBufferState); 459 return; 460 } 461 mSlots[buf].mBufferState = BufferSlot::FREE; 462 mDequeueCondition.signal(); 463} 464 465status_t SurfaceTexture::setCrop(const Rect& crop) { 466 LOGV("SurfaceTexture::setCrop"); 467 Mutex::Autolock lock(mMutex); 468 mNextCrop = crop; 469 return OK; 470} 471 472status_t SurfaceTexture::setTransform(uint32_t transform) { 473 LOGV("SurfaceTexture::setTransform"); 474 Mutex::Autolock lock(mMutex); 475 mNextTransform = transform; 476 return OK; 477} 478 479status_t SurfaceTexture::updateTexImage() { 480 LOGV("SurfaceTexture::updateTexImage"); 481 482 Mutex::Autolock lock(mMutex); 483 484 int buf = mCurrentTexture; 485 if (!mQueue.empty()) { 486 // in asynchronous mode the list is guaranteed to be one buffer deep, 487 // while in synchronous mode we use the oldest buffer 488 Fifo::iterator front(mQueue.begin()); 489 buf = *front; 490 mQueue.erase(front); 491 if (mQueue.isEmpty()) { 492 mDequeueCondition.signal(); 493 } 494 } 495 496 // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT, 497 // so this check will fail until a buffer gets queued. 498 if (mCurrentTexture != buf) { 499 // Update the GL texture object. 500 EGLImageKHR image = mSlots[buf].mEglImage; 501 if (image == EGL_NO_IMAGE_KHR) { 502 EGLDisplay dpy = eglGetCurrentDisplay(); 503 image = createImage(dpy, mSlots[buf].mGraphicBuffer); 504 mSlots[buf].mEglImage = image; 505 mSlots[buf].mEglDisplay = dpy; 506 if (image == EGL_NO_IMAGE_KHR) { 507 // NOTE: if dpy was invalid, createImage() is guaranteed to 508 // fail. so we'd end up here. 509 return -EINVAL; 510 } 511 } 512 513 GLint error; 514 while ((error = glGetError()) != GL_NO_ERROR) { 515 LOGW("updateTexImage: clearing GL error: %#04x", error); 516 } 517 518 GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format); 519 if (target != mCurrentTextureTarget) { 520 glDeleteTextures(1, &mTexName); 521 } 522 glBindTexture(target, mTexName); 523 glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image); 524 525 bool failed = false; 526 while ((error = glGetError()) != GL_NO_ERROR) { 527 LOGE("error binding external texture image %p (slot %d): %#04x", 528 image, buf, error); 529 failed = true; 530 } 531 if (failed) { 532 return -EINVAL; 533 } 534 535 if (mCurrentTexture != INVALID_BUFFER_SLOT) { 536 // the current buffer becomes FREE if it was still in the queued 537 // state. If it has already been given to the client 538 // (synchronous mode), then it stays in DEQUEUED state. 539 if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) 540 mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE; 541 } 542 543 // Update the SurfaceTexture state. 544 mCurrentTexture = buf; 545 mCurrentTextureTarget = target; 546 mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; 547 mCurrentCrop = mSlots[buf].mCrop; 548 mCurrentTransform = mSlots[buf].mTransform; 549 mCurrentTimestamp = mSlots[buf].mTimestamp; 550 mDequeueCondition.signal(); 551 } else { 552 // We always bind the texture even if we don't update its contents. 553 glBindTexture(mCurrentTextureTarget, mTexName); 554 } 555 return OK; 556} 557 558size_t SurfaceTexture::getQueuedCount() const { 559 Mutex::Autolock lock(mMutex); 560 return mQueue.size(); 561} 562 563bool SurfaceTexture::isExternalFormat(uint32_t format) 564{ 565 switch (format) { 566 // supported YUV formats 567 case HAL_PIXEL_FORMAT_YV12: 568 // Legacy/deprecated YUV formats 569 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 570 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 571 case HAL_PIXEL_FORMAT_YCbCr_422_I: 572 return true; 573 } 574 575 // Any OEM format needs to be considered 576 if (format>=0x100 && format<=0x1FF) 577 return true; 578 579 return false; 580} 581 582GLenum SurfaceTexture::getTextureTarget(uint32_t format) 583{ 584 GLenum target = GL_TEXTURE_2D; 585#if defined(GL_OES_EGL_image_external) 586 if (isExternalFormat(format)) { 587 target = GL_TEXTURE_EXTERNAL_OES; 588 } 589#endif 590 return target; 591} 592 593GLenum SurfaceTexture::getCurrentTextureTarget() const { 594 Mutex::Autolock lock(mMutex); 595 return mCurrentTextureTarget; 596} 597 598void SurfaceTexture::getTransformMatrix(float mtx[16]) { 599 LOGV("SurfaceTexture::getTransformMatrix"); 600 Mutex::Autolock lock(mMutex); 601 602 float xform[16]; 603 for (int i = 0; i < 16; i++) { 604 xform[i] = mtxIdentity[i]; 605 } 606 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { 607 float result[16]; 608 mtxMul(result, xform, mtxFlipH); 609 for (int i = 0; i < 16; i++) { 610 xform[i] = result[i]; 611 } 612 } 613 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { 614 float result[16]; 615 mtxMul(result, xform, mtxFlipV); 616 for (int i = 0; i < 16; i++) { 617 xform[i] = result[i]; 618 } 619 } 620 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 621 float result[16]; 622 mtxMul(result, xform, mtxRot90); 623 for (int i = 0; i < 16; i++) { 624 xform[i] = result[i]; 625 } 626 } 627 628 sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer); 629 float tx, ty, sx, sy; 630 if (!mCurrentCrop.isEmpty()) { 631 // In order to prevent bilinear sampling at the of the crop rectangle we 632 // may need to shrink it by 2 texels in each direction. Normally this 633 // would just need to take 1/2 a texel off each end, but because the 634 // chroma channels will likely be subsampled we need to chop off a whole 635 // texel. This will cause artifacts if someone does nearest sampling 636 // with 1:1 pixel:texel ratio, but it's impossible to simultaneously 637 // accomodate the bilinear and nearest sampling uses. 638 // 639 // If nearest sampling turns out to be a desirable usage of these 640 // textures then we could add the ability to switch a SurfaceTexture to 641 // nearest-mode. Preferably, however, the image producers (video 642 // decoder, camera, etc.) would simply not use a crop rectangle (or at 643 // least not tell the framework about it) so that the GPU can do the 644 // correct edge behavior. 645 int xshrink = 0, yshrink = 0; 646 if (mCurrentCrop.left > 0) { 647 tx = float(mCurrentCrop.left + 1) / float(buf->getWidth()); 648 xshrink++; 649 } else { 650 tx = 0.0f; 651 } 652 if (mCurrentCrop.right < int32_t(buf->getWidth())) { 653 xshrink++; 654 } 655 if (mCurrentCrop.bottom < int32_t(buf->getHeight())) { 656 ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) / 657 float(buf->getHeight()); 658 yshrink++; 659 } else { 660 ty = 0.0f; 661 } 662 if (mCurrentCrop.top > 0) { 663 yshrink++; 664 } 665 sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth()); 666 sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight()); 667 } else { 668 tx = 0.0f; 669 ty = 0.0f; 670 sx = 1.0f; 671 sy = 1.0f; 672 } 673 float crop[16] = { 674 sx, 0, 0, 0, 675 0, sy, 0, 0, 676 0, 0, 1, 0, 677 tx, ty, 0, 1, 678 }; 679 680 float mtxBeforeFlipV[16]; 681 mtxMul(mtxBeforeFlipV, crop, xform); 682 683 // SurfaceFlinger expects the top of its window textures to be at a Y 684 // coordinate of 0, so SurfaceTexture must behave the same way. We don't 685 // want to expose this to applications, however, so we must add an 686 // additional vertical flip to the transform after all the other transforms. 687 mtxMul(mtx, mtxFlipV, mtxBeforeFlipV); 688} 689 690nsecs_t SurfaceTexture::getTimestamp() { 691 LOGV("SurfaceTexture::getTimestamp"); 692 Mutex::Autolock lock(mMutex); 693 return mCurrentTimestamp; 694} 695 696void SurfaceTexture::setFrameAvailableListener( 697 const sp<FrameAvailableListener>& l) { 698 LOGV("SurfaceTexture::setFrameAvailableListener"); 699 Mutex::Autolock lock(mMutex); 700 mFrameAvailableListener = l; 701} 702 703sp<IBinder> SurfaceTexture::getAllocator() { 704 LOGV("SurfaceTexture::getAllocator"); 705 return mGraphicBufferAlloc->asBinder(); 706} 707 708void SurfaceTexture::freeAllBuffers() { 709 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 710 mSlots[i].mGraphicBuffer = 0; 711 mSlots[i].mBufferState = BufferSlot::FREE; 712 if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { 713 eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); 714 mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; 715 mSlots[i].mEglDisplay = EGL_NO_DISPLAY; 716 } 717 } 718} 719 720EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, 721 const sp<GraphicBuffer>& graphicBuffer) { 722 EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); 723 EGLint attrs[] = { 724 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 725 EGL_NONE, 726 }; 727 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 728 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); 729 if (image == EGL_NO_IMAGE_KHR) { 730 EGLint error = eglGetError(); 731 LOGE("error creating EGLImage: %#x", error); 732 } 733 return image; 734} 735 736sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const { 737 Mutex::Autolock lock(mMutex); 738 return mCurrentTextureBuf; 739} 740 741Rect SurfaceTexture::getCurrentCrop() const { 742 Mutex::Autolock lock(mMutex); 743 return mCurrentCrop; 744} 745 746uint32_t SurfaceTexture::getCurrentTransform() const { 747 Mutex::Autolock lock(mMutex); 748 return mCurrentTransform; 749} 750 751int SurfaceTexture::query(int what, int* outValue) 752{ 753 Mutex::Autolock lock(mMutex); 754 int value; 755 switch (what) { 756 case NATIVE_WINDOW_WIDTH: 757 value = mDefaultWidth; 758 if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0) 759 value = mCurrentTextureBuf->width; 760 break; 761 case NATIVE_WINDOW_HEIGHT: 762 value = mDefaultHeight; 763 if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0) 764 value = mCurrentTextureBuf->height; 765 break; 766 case NATIVE_WINDOW_FORMAT: 767 value = mPixelFormat; 768 break; 769 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 770 value = mSynchronousMode ? 771 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 772 break; 773 default: 774 return BAD_VALUE; 775 } 776 outValue[0] = value; 777 return NO_ERROR; 778} 779 780void SurfaceTexture::dump(String8& result) const 781{ 782 char buffer[1024]; 783 dump(result, "", buffer, 1024); 784} 785 786void SurfaceTexture::dump(String8& result, const char* prefix, 787 char* buffer, size_t SIZE) const 788{ 789 Mutex::Autolock _l(mMutex); 790 snprintf(buffer, SIZE, 791 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 792 "mPixelFormat=%d, mTexName=%d\n", 793 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, 794 mPixelFormat, mTexName); 795 result.append(buffer); 796 797 String8 fifo; 798 int fifoSize = 0; 799 Fifo::const_iterator i(mQueue.begin()); 800 while (i != mQueue.end()) { 801 snprintf(buffer, SIZE, "%02d ", *i++); 802 fifoSize++; 803 fifo.append(buffer); 804 } 805 806 snprintf(buffer, SIZE, 807 "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n" 808 "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n" 809 , 810 prefix, mCurrentCrop.left, 811 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, 812 mCurrentTransform, mCurrentTexture, mCurrentTextureTarget, 813 prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom, 814 mCurrentTransform, fifoSize, fifo.string() 815 ); 816 result.append(buffer); 817 818 struct { 819 const char * operator()(int state) const { 820 switch (state) { 821 case BufferSlot::DEQUEUED: return "DEQUEUED"; 822 case BufferSlot::QUEUED: return "QUEUED"; 823 case BufferSlot::FREE: return "FREE"; 824 default: return "Unknown"; 825 } 826 } 827 } stateName; 828 829 for (int i=0 ; i<mBufferCount ; i++) { 830 const BufferSlot& slot(mSlots[i]); 831 snprintf(buffer, SIZE, 832 "%s%s[%02d] state=%-8s, crop=[%d,%d,%d,%d], transform=0x%02x, " 833 "timestamp=%lld\n", 834 prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState), 835 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom, 836 slot.mTransform, slot.mTimestamp 837 ); 838 result.append(buffer); 839 } 840} 841 842static void mtxMul(float out[16], const float a[16], const float b[16]) { 843 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; 844 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; 845 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; 846 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; 847 848 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; 849 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; 850 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; 851 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; 852 853 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; 854 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; 855 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; 856 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; 857 858 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; 859 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; 860 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; 861 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; 862} 863 864}; // namespace android 865