diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/gui/SurfaceTexture.cpp | 72 | ||||
-rw-r--r-- | libs/gui/SurfaceTextureClient.cpp | 65 |
2 files changed, 120 insertions, 17 deletions
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index e2346f0..39418f0 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -27,6 +27,8 @@ #include <gui/SurfaceTexture.h> +#include <hardware/hardware.h> + #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/SurfaceComposerClient.h> #include <surfaceflinger/IGraphicBufferAlloc.h> @@ -82,6 +84,7 @@ SurfaceTexture::SurfaceTexture(GLuint tex) : mUseDefaultSize(true), mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT), + mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES), mCurrentTransform(0), mCurrentTimestamp(0), mLastQueued(INVALID_BUFFER_SLOT), @@ -197,6 +200,7 @@ status_t SurfaceTexture::dequeueBuffer(int *buf) { if (buffer == NULL) { return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; } + if ((mUseDefaultSize) && ((uint32_t(buffer->width) != mDefaultWidth) || (uint32_t(buffer->height) != mDefaultHeight))) { @@ -263,9 +267,6 @@ status_t SurfaceTexture::updateTexImage() { LOGV("SurfaceTexture::updateTexImage"); Mutex::Autolock lock(mMutex); - // We always bind the texture even if we don't update its contents. - glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); - // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT, // so this check will fail until a buffer gets queued. if (mCurrentTexture != mLastQueued) { @@ -283,7 +284,15 @@ status_t SurfaceTexture::updateTexImage() { while ((error = glGetError()) != GL_NO_ERROR) { LOGE("GL error cleared before updating SurfaceTexture: %#04x", error); } - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image); + + GLenum target = getTextureTarget( + mSlots[mLastQueued].mGraphicBuffer->format); + if (target != mCurrentTextureTarget) { + glDeleteTextures(1, &mTexName); + } + glBindTexture(target, mTexName); + glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image); + bool failed = false; while ((error = glGetError()) != GL_NO_ERROR) { LOGE("error binding external texture image %p (slot %d): %#04x", @@ -296,14 +305,53 @@ status_t SurfaceTexture::updateTexImage() { // Update the SurfaceTexture state. mCurrentTexture = mLastQueued; + mCurrentTextureTarget = target; mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer; mCurrentCrop = mLastQueuedCrop; mCurrentTransform = mLastQueuedTransform; mCurrentTimestamp = mLastQueuedTimestamp; + } else { + // We always bind the texture even if we don't update its contents. + glBindTexture(mCurrentTextureTarget, mTexName); } return OK; } +bool SurfaceTexture::isExternalFormat(uint32_t format) +{ + switch (format) { + // supported YUV formats + case HAL_PIXEL_FORMAT_YV12: + // Legacy/deprecated YUV formats + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + return true; + } + + // Any OEM format needs to be considered + if (format>=0x100 && format<=0x1FF) + return true; + + return false; +} + +GLenum SurfaceTexture::getTextureTarget(uint32_t format) +{ + GLenum target = GL_TEXTURE_2D; +#if defined(GL_OES_EGL_image_external) + if (isExternalFormat(format)) { + target = GL_TEXTURE_EXTERNAL_OES; + } +#endif + return target; +} + +GLenum SurfaceTexture::getCurrentTextureTarget() const { + Mutex::Autolock lock(mMutex); + return mCurrentTextureTarget; +} + void SurfaceTexture::getTransformMatrix(float mtx[16]) { LOGV("SurfaceTexture::getTransformMatrix"); Mutex::Autolock lock(mMutex); @@ -445,6 +493,22 @@ EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, return image; } +sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const { + Mutex::Autolock lock(mMutex); + return mCurrentTextureBuf; +} + +Rect SurfaceTexture::getCurrentCrop() const { + Mutex::Autolock lock(mMutex); + return mCurrentCrop; +} + +uint32_t SurfaceTexture::getCurrentTransform() const { + Mutex::Autolock lock(mMutex); + return mCurrentTransform; +} + + static void mtxMul(float out[16], const float a[16], const float b[16]) { out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 29fc4d3..f4b2416 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -26,8 +26,10 @@ namespace android { SurfaceTextureClient::SurfaceTextureClient( const sp<ISurfaceTexture>& surfaceTexture): mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0), - mReqHeight(0), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), - mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() { + mReqHeight(0), mReqFormat(0), mReqUsage(0), + mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0), + mQueryWidth(0), mQueryHeight(0), mQueryFormat(0), + mMutex() { // Initialize the ANativeWindow function pointers. ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; @@ -101,9 +103,10 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { } sp<GraphicBuffer>& gbuf(mSlots[buf]); if (err == ISurfaceTexture::BUFFER_NEEDS_REALLOCATION || - gbuf == 0 || gbuf->getWidth() != mReqWidth || - gbuf->getHeight() != mReqHeight || - uint32_t(gbuf->getPixelFormat()) != mReqFormat || + gbuf == 0 || + (mReqWidth && gbuf->getWidth() != mReqWidth) || + (mReqHeight && gbuf->getHeight() != mReqHeight) || + (mReqFormat && uint32_t(gbuf->getPixelFormat()) != mReqFormat) || (gbuf->getUsage() & mReqUsage) != mReqUsage) { gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight, mReqFormat, mReqUsage); @@ -111,6 +114,9 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed"); return NO_MEMORY; } + mQueryWidth = gbuf->width; + mQueryHeight = gbuf->height; + mQueryFormat = gbuf->format; } *buffer = gbuf.get(); return OK; @@ -159,13 +165,13 @@ int SurfaceTextureClient::query(int what, int* value) { Mutex::Autolock lock(mMutex); switch (what) { case NATIVE_WINDOW_WIDTH: + *value = mQueryWidth ? mQueryWidth : mReqWidth; + return NO_ERROR; case NATIVE_WINDOW_HEIGHT: - // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't - // override the size? - *value = 0; + *value = mQueryHeight ? mQueryHeight : mReqHeight; return NO_ERROR; case NATIVE_WINDOW_FORMAT: - *value = DEFAULT_FORMAT; + *value = mQueryFormat ? mQueryFormat : mReqFormat; return NO_ERROR; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: *value = MIN_UNDEQUEUED_BUFFERS; @@ -260,16 +266,49 @@ int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { int SurfaceTextureClient::connect(int api) { LOGV("SurfaceTextureClient::connect"); - // XXX: Implement this! - return INVALID_OPERATION; + Mutex::Autolock lock(mMutex); + int err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + if (mConnectedApi) { + err = -EINVAL; + } else { + mConnectedApi = api; + } + break; + default: + err = -EINVAL; + break; + } + return err; } int SurfaceTextureClient::disconnect(int api) { LOGV("SurfaceTextureClient::disconnect"); - // XXX: Implement this! - return INVALID_OPERATION; + Mutex::Autolock lock(mMutex); + int err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + if (mConnectedApi == api) { + mConnectedApi = 0; + } else { + err = -EINVAL; + } + break; + default: + err = -EINVAL; + break; + } + return err; } +int SurfaceTextureClient::getConnectedApi() const +{ + Mutex::Autolock lock(mMutex); + return mConnectedApi; +} + + int SurfaceTextureClient::setUsage(uint32_t reqUsage) { LOGV("SurfaceTextureClient::setUsage"); |