SurfaceTexture.cpp revision ed3894c07a67b3e35d07084c4a8b410908bfedc5
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 38namespace android { 39 40// Transform matrices 41static float mtxIdentity[16] = { 42 1, 0, 0, 0, 43 0, 1, 0, 0, 44 0, 0, 1, 0, 45 0, 0, 0, 1, 46}; 47static float mtxFlipH[16] = { 48 -1, 0, 0, 0, 49 0, 1, 0, 0, 50 0, 0, 1, 0, 51 1, 0, 0, 1, 52}; 53static float mtxFlipV[16] = { 54 1, 0, 0, 0, 55 0, -1, 0, 0, 56 0, 0, 1, 0, 57 0, 1, 0, 1, 58}; 59static float mtxRot90[16] = { 60 0, 1, 0, 0, 61 -1, 0, 0, 0, 62 0, 0, 1, 0, 63 1, 0, 0, 1, 64}; 65static float mtxRot180[16] = { 66 -1, 0, 0, 0, 67 0, -1, 0, 0, 68 0, 0, 1, 0, 69 1, 1, 0, 1, 70}; 71static float mtxRot270[16] = { 72 0, -1, 0, 0, 73 1, 0, 0, 0, 74 0, 0, 1, 0, 75 0, 1, 0, 1, 76}; 77 78static void mtxMul(float out[16], const float a[16], const float b[16]); 79 80SurfaceTexture::SurfaceTexture(GLuint tex) : 81 mDefaultWidth(1), 82 mDefaultHeight(1), 83 mPixelFormat(PIXEL_FORMAT_RGBA_8888), 84 mBufferCount(MIN_BUFFER_SLOTS), 85 mCurrentTexture(INVALID_BUFFER_SLOT), 86 mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES), 87 mCurrentTransform(0), 88 mCurrentTimestamp(0), 89 mLastQueued(INVALID_BUFFER_SLOT), 90 mLastQueuedTransform(0), 91 mLastQueuedTimestamp(0), 92 mNextTransform(0), 93 mTexName(tex) { 94 LOGV("SurfaceTexture::SurfaceTexture"); 95 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 96 mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; 97 mSlots[i].mEglDisplay = EGL_NO_DISPLAY; 98 mSlots[i].mOwnedByClient = false; 99 } 100 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 101 mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 102 mNextCrop.makeInvalid(); 103} 104 105SurfaceTexture::~SurfaceTexture() { 106 LOGV("SurfaceTexture::~SurfaceTexture"); 107 freeAllBuffers(); 108} 109 110status_t SurfaceTexture::setBufferCount(int bufferCount) { 111 LOGV("SurfaceTexture::setBufferCount"); 112 113 if (bufferCount < MIN_BUFFER_SLOTS) { 114 return BAD_VALUE; 115 } 116 117 Mutex::Autolock lock(mMutex); 118 freeAllBuffers(); 119 mBufferCount = bufferCount; 120 mCurrentTexture = INVALID_BUFFER_SLOT; 121 mLastQueued = INVALID_BUFFER_SLOT; 122 return OK; 123} 124 125status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) 126{ 127 Mutex::Autolock lock(mMutex); 128 if ((w != mDefaultWidth) || (h != mDefaultHeight)) { 129 mDefaultWidth = w; 130 mDefaultHeight = h; 131 } 132 return OK; 133} 134 135sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) { 136 LOGV("SurfaceTexture::requestBuffer"); 137 Mutex::Autolock lock(mMutex); 138 if (buf < 0 || mBufferCount <= buf) { 139 LOGE("requestBuffer: slot index out of range [0, %d]: %d", 140 mBufferCount, buf); 141 return 0; 142 } 143 return mSlots[buf].mGraphicBuffer; 144} 145 146status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, 147 uint32_t format, uint32_t usage) { 148 LOGV("SurfaceTexture::dequeueBuffer"); 149 150 if ((w && !h) || (!w & h)) { 151 LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); 152 return BAD_VALUE; 153 } 154 155 Mutex::Autolock lock(mMutex); 156 int found = INVALID_BUFFER_SLOT; 157 for (int i = 0; i < mBufferCount; i++) { 158 if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) { 159 mSlots[i].mOwnedByClient = true; 160 found = i; 161 break; 162 } 163 } 164 if (found == INVALID_BUFFER_SLOT) { 165 return -EBUSY; 166 } 167 168 const int buf = found; 169 *outBuf = found; 170 171 const bool useDefaultSize = !w && !h; 172 if (useDefaultSize) { 173 // use the default size 174 w = mDefaultWidth; 175 h = mDefaultHeight; 176 } 177 178 const bool updateFormat = (format != 0); 179 if (!updateFormat) { 180 // keep the current (or default) format 181 format = mPixelFormat; 182 } 183 184 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); 185 if ((buffer == NULL) || 186 (uint32_t(buffer->width) != w) || 187 (uint32_t(buffer->height) != h) || 188 (uint32_t(buffer->format) != format) || 189 ((uint32_t(buffer->usage) & usage) != usage)) 190 { 191 usage |= GraphicBuffer::USAGE_HW_TEXTURE; 192 sp<GraphicBuffer> graphicBuffer( 193 mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage)); 194 if (graphicBuffer == 0) { 195 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 196 return NO_MEMORY; 197 } 198 if (updateFormat) { 199 mPixelFormat = format; 200 } 201 mSlots[buf].mGraphicBuffer = graphicBuffer; 202 if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { 203 eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage); 204 mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; 205 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; 206 } 207 return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 208 } 209 return OK; 210} 211 212status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { 213 LOGV("SurfaceTexture::queueBuffer"); 214 Mutex::Autolock lock(mMutex); 215 if (buf < 0 || mBufferCount <= buf) { 216 LOGE("queueBuffer: slot index out of range [0, %d]: %d", 217 mBufferCount, buf); 218 return -EINVAL; 219 } else if (!mSlots[buf].mOwnedByClient) { 220 LOGE("queueBuffer: slot %d is not owned by the client", buf); 221 return -EINVAL; 222 } else if (mSlots[buf].mGraphicBuffer == 0) { 223 LOGE("queueBuffer: slot %d was enqueued without requesting a buffer", 224 buf); 225 return -EINVAL; 226 } 227 mSlots[buf].mOwnedByClient = false; 228 mLastQueued = buf; 229 mLastQueuedCrop = mNextCrop; 230 mLastQueuedTransform = mNextTransform; 231 mLastQueuedTimestamp = timestamp; 232 if (mFrameAvailableListener != 0) { 233 mFrameAvailableListener->onFrameAvailable(); 234 } 235 return OK; 236} 237 238void SurfaceTexture::cancelBuffer(int buf) { 239 LOGV("SurfaceTexture::cancelBuffer"); 240 Mutex::Autolock lock(mMutex); 241 if (buf < 0 || mBufferCount <= buf) { 242 LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount, 243 buf); 244 return; 245 } else if (!mSlots[buf].mOwnedByClient) { 246 LOGE("cancelBuffer: slot %d is not owned by the client", buf); 247 return; 248 } 249 mSlots[buf].mOwnedByClient = false; 250} 251 252status_t SurfaceTexture::setCrop(const Rect& crop) { 253 LOGV("SurfaceTexture::setCrop"); 254 Mutex::Autolock lock(mMutex); 255 mNextCrop = crop; 256 return OK; 257} 258 259status_t SurfaceTexture::setTransform(uint32_t transform) { 260 LOGV("SurfaceTexture::setTransform"); 261 Mutex::Autolock lock(mMutex); 262 mNextTransform = transform; 263 return OK; 264} 265 266status_t SurfaceTexture::updateTexImage() { 267 LOGV("SurfaceTexture::updateTexImage"); 268 Mutex::Autolock lock(mMutex); 269 270 // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT, 271 // so this check will fail until a buffer gets queued. 272 if (mCurrentTexture != mLastQueued) { 273 // Update the GL texture object. 274 EGLImageKHR image = mSlots[mLastQueued].mEglImage; 275 if (image == EGL_NO_IMAGE_KHR) { 276 EGLDisplay dpy = eglGetCurrentDisplay(); 277 image = createImage(dpy, mSlots[mLastQueued].mGraphicBuffer); 278 mSlots[mLastQueued].mEglImage = image; 279 mSlots[mLastQueued].mEglDisplay = dpy; 280 if (image == EGL_NO_IMAGE_KHR) { 281 // NOTE: if dpy was invalid, createImage() is guaranteed to 282 // fail. so we'd end up here. 283 return -EINVAL; 284 } 285 } 286 287 GLint error; 288 while ((error = glGetError()) != GL_NO_ERROR) { 289 LOGE("GL error cleared before updating SurfaceTexture: %#04x", error); 290 } 291 292 GLenum target = getTextureTarget( 293 mSlots[mLastQueued].mGraphicBuffer->format); 294 if (target != mCurrentTextureTarget) { 295 glDeleteTextures(1, &mTexName); 296 } 297 glBindTexture(target, mTexName); 298 glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image); 299 300 bool failed = false; 301 while ((error = glGetError()) != GL_NO_ERROR) { 302 LOGE("error binding external texture image %p (slot %d): %#04x", 303 image, mLastQueued, error); 304 failed = true; 305 } 306 if (failed) { 307 return -EINVAL; 308 } 309 310 // Update the SurfaceTexture state. 311 mCurrentTexture = mLastQueued; 312 mCurrentTextureTarget = target; 313 mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer; 314 mCurrentCrop = mLastQueuedCrop; 315 mCurrentTransform = mLastQueuedTransform; 316 mCurrentTimestamp = mLastQueuedTimestamp; 317 } else { 318 // We always bind the texture even if we don't update its contents. 319 glBindTexture(mCurrentTextureTarget, mTexName); 320 } 321 return OK; 322} 323 324bool SurfaceTexture::isExternalFormat(uint32_t format) 325{ 326 switch (format) { 327 // supported YUV formats 328 case HAL_PIXEL_FORMAT_YV12: 329 // Legacy/deprecated YUV formats 330 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 331 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 332 case HAL_PIXEL_FORMAT_YCbCr_422_I: 333 return true; 334 } 335 336 // Any OEM format needs to be considered 337 if (format>=0x100 && format<=0x1FF) 338 return true; 339 340 return false; 341} 342 343GLenum SurfaceTexture::getTextureTarget(uint32_t format) 344{ 345 GLenum target = GL_TEXTURE_2D; 346#if defined(GL_OES_EGL_image_external) 347 if (isExternalFormat(format)) { 348 target = GL_TEXTURE_EXTERNAL_OES; 349 } 350#endif 351 return target; 352} 353 354GLenum SurfaceTexture::getCurrentTextureTarget() const { 355 Mutex::Autolock lock(mMutex); 356 return mCurrentTextureTarget; 357} 358 359void SurfaceTexture::getTransformMatrix(float mtx[16]) { 360 LOGV("SurfaceTexture::getTransformMatrix"); 361 Mutex::Autolock lock(mMutex); 362 363 float xform[16]; 364 for (int i = 0; i < 16; i++) { 365 xform[i] = mtxIdentity[i]; 366 } 367 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { 368 float result[16]; 369 mtxMul(result, xform, mtxFlipH); 370 for (int i = 0; i < 16; i++) { 371 xform[i] = result[i]; 372 } 373 } 374 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { 375 float result[16]; 376 mtxMul(result, xform, mtxFlipV); 377 for (int i = 0; i < 16; i++) { 378 xform[i] = result[i]; 379 } 380 } 381 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 382 float result[16]; 383 mtxMul(result, xform, mtxRot90); 384 for (int i = 0; i < 16; i++) { 385 xform[i] = result[i]; 386 } 387 } 388 389 sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer); 390 float tx, ty, sx, sy; 391 if (!mCurrentCrop.isEmpty()) { 392 // In order to prevent bilinear sampling at the of the crop rectangle we 393 // may need to shrink it by 2 texels in each direction. Normally this 394 // would just need to take 1/2 a texel off each end, but because the 395 // chroma channels will likely be subsampled we need to chop off a whole 396 // texel. This will cause artifacts if someone does nearest sampling 397 // with 1:1 pixel:texel ratio, but it's impossible to simultaneously 398 // accomodate the bilinear and nearest sampling uses. 399 // 400 // If nearest sampling turns out to be a desirable usage of these 401 // textures then we could add the ability to switch a SurfaceTexture to 402 // nearest-mode. Preferably, however, the image producers (video 403 // decoder, camera, etc.) would simply not use a crop rectangle (or at 404 // least not tell the framework about it) so that the GPU can do the 405 // correct edge behavior. 406 int xshrink = 0, yshrink = 0; 407 if (mCurrentCrop.left > 0) { 408 tx = float(mCurrentCrop.left + 1) / float(buf->getWidth()); 409 xshrink++; 410 } else { 411 tx = 0.0f; 412 } 413 if (mCurrentCrop.right < int32_t(buf->getWidth())) { 414 xshrink++; 415 } 416 if (mCurrentCrop.bottom < int32_t(buf->getHeight())) { 417 ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) / 418 float(buf->getHeight()); 419 yshrink++; 420 } else { 421 ty = 0.0f; 422 } 423 if (mCurrentCrop.top > 0) { 424 yshrink++; 425 } 426 sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth()); 427 sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight()); 428 } else { 429 tx = 0.0f; 430 ty = 0.0f; 431 sx = 1.0f; 432 sy = 1.0f; 433 } 434 float crop[16] = { 435 sx, 0, 0, 0, 436 0, sy, 0, 0, 437 0, 0, 1, 0, 438 tx, ty, 0, 1, 439 }; 440 441 float mtxBeforeFlipV[16]; 442 mtxMul(mtxBeforeFlipV, crop, xform); 443 444 // SurfaceFlinger expects the top of its window textures to be at a Y 445 // coordinate of 0, so SurfaceTexture must behave the same way. We don't 446 // want to expose this to applications, however, so we must add an 447 // additional vertical flip to the transform after all the other transforms. 448 mtxMul(mtx, mtxFlipV, mtxBeforeFlipV); 449} 450 451nsecs_t SurfaceTexture::getTimestamp() { 452 LOGV("SurfaceTexture::getTimestamp"); 453 Mutex::Autolock lock(mMutex); 454 return mCurrentTimestamp; 455} 456 457void SurfaceTexture::setFrameAvailableListener( 458 const sp<FrameAvailableListener>& l) { 459 LOGV("SurfaceTexture::setFrameAvailableListener"); 460 Mutex::Autolock lock(mMutex); 461 mFrameAvailableListener = l; 462} 463 464sp<IBinder> SurfaceTexture::getAllocator() { 465 LOGV("SurfaceTexture::getAllocator"); 466 return mGraphicBufferAlloc->asBinder(); 467} 468 469void SurfaceTexture::freeAllBuffers() { 470 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 471 mSlots[i].mGraphicBuffer = 0; 472 mSlots[i].mOwnedByClient = false; 473 if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { 474 eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); 475 mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; 476 mSlots[i].mEglDisplay = EGL_NO_DISPLAY; 477 } 478 } 479} 480 481EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, 482 const sp<GraphicBuffer>& graphicBuffer) { 483 EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); 484 EGLint attrs[] = { 485 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 486 EGL_NONE, 487 }; 488 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 489 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); 490 if (image == EGL_NO_IMAGE_KHR) { 491 EGLint error = eglGetError(); 492 LOGE("error creating EGLImage: %#x", error); 493 } 494 return image; 495} 496 497sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const { 498 Mutex::Autolock lock(mMutex); 499 return mCurrentTextureBuf; 500} 501 502Rect SurfaceTexture::getCurrentCrop() const { 503 Mutex::Autolock lock(mMutex); 504 return mCurrentCrop; 505} 506 507uint32_t SurfaceTexture::getCurrentTransform() const { 508 Mutex::Autolock lock(mMutex); 509 return mCurrentTransform; 510} 511 512int SurfaceTexture::query(int what, int* outValue) 513{ 514 Mutex::Autolock lock(mMutex); 515 int value; 516 switch (what) { 517 case NATIVE_WINDOW_WIDTH: 518 value = mDefaultWidth; 519 if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0) 520 value = mCurrentTextureBuf->width; 521 break; 522 case NATIVE_WINDOW_HEIGHT: 523 value = mDefaultHeight; 524 if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0) 525 value = mCurrentTextureBuf->height; 526 break; 527 case NATIVE_WINDOW_FORMAT: 528 value = mPixelFormat; 529 break; 530 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 531 value = mSynchronousMode ? 532 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 533 break; 534 default: 535 return BAD_VALUE; 536 } 537 outValue[0] = value; 538 return NO_ERROR; 539} 540 541static void mtxMul(float out[16], const float a[16], const float b[16]) { 542 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; 543 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; 544 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; 545 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; 546 547 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; 548 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; 549 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; 550 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; 551 552 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; 553 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; 554 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; 555 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; 556 557 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; 558 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; 559 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; 560 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; 561} 562 563}; // namespace android 564