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