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