summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlin Jerpelea <jerpelea@gmail.com>2013-07-20 12:56:31 +0100
committerOliverG96 <oliverarafo@gmail.com>2013-07-25 19:38:36 +0100
commit35c7cd72f91eedc77ab693ebb94121bdd57cc22c (patch)
treed71afbbf19d5794d5351660ede45e253722c5c5e
parentfa7e3f769d69fd06d7fadb7c48947f074075f2e4 (diff)
downloadandroid_frameworks_native-jellybean.tar.gz
android_frameworks_native-jellybean.tar.bz2
android_frameworks_native-jellybean.zip
native: Add missing changes for multimedia on STE devicesjellybean
Change-Id: Icfa731aa501ea0e79529f5bb85081cd476a33102
-rw-r--r--include/gui/SurfaceTexture.h73
-rw-r--r--include/ui/Region.h26
-rw-r--r--libs/gui/SurfaceTexture.cpp233
-rw-r--r--libs/ui/PixelFormat.cpp12
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp4
-rw-r--r--services/surfaceflinger/Layer.cpp17
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp55
7 files changed, 413 insertions, 7 deletions
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 2635e2f3a..ec73f952c 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -31,6 +31,11 @@
#include <utils/Vector.h>
#include <utils/threads.h>
+#ifdef STE_HARDWARE
+#include <hardware/copybit.h>
+#include <gui/IGraphicBufferAlloc.h>
+#endif
+
#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
namespace android {
@@ -42,6 +47,9 @@ class String8;
class SurfaceTexture : public virtual RefBase,
protected BufferQueue::ConsumerListener {
public:
+#ifdef STE_HARDWARE
+ enum { NUM_BLIT_BUFFER_SLOTS = 2 };
+#endif
struct FrameAvailableListener : public virtual RefBase {
// onFrameAvailable() is called each time an additional frame becomes
// available for consumption. This means that frames that are queued
@@ -91,6 +99,13 @@ public:
// target texture belongs is bound to the calling thread.
status_t updateTexImage();
+#ifdef STE_HARDWARE
+ // convert() performs the deferred texture conversion as scheduled
+ // by updateTexImage(bool deferConversion).
+ // The method returns immediately if no conversion is necessary.
+ status_t convert();
+#endif
+
// setBufferCountServer set the buffer count. If the client has requested
// a buffer count using setBufferCount, the server-buffer count will
// take effect once the client sets the count back to zero.
@@ -248,12 +263,27 @@ private:
virtual ~BufferRejecter() { }
};
friend class Layer;
+#ifndef STE_HARDWARE
status_t updateTexImage(BufferRejecter* rejecter);
+#else
+ // A surface that uses a non-native format requires conversion of
+ // its buffers. This conversion can be deferred until the layer
+ // based on this surface is drawn.
+ status_t updateTexImage(BufferRejecter* rejecter, bool deferConversion);
+#endif
// createImage creates a new EGLImage from a GraphicBuffer.
EGLImageKHR createImage(EGLDisplay dpy,
const sp<GraphicBuffer>& graphicBuffer);
+#ifdef STE_HARDWARE
+ // returns TRUE if buffer needs color format conversion
+ bool conversionIsNeeded(const sp<GraphicBuffer>& graphicBuffer);
+
+ // converts buffer to a suitable color format
+ status_t convert(sp<GraphicBuffer> &srcBuf, sp<GraphicBuffer> &dstBuf);
+#endif
+
// freeBufferLocked frees up the given buffer slot. If the slot has been
// initialized this will release the reference to the GraphicBuffer in that
// slot and destroy the EGLImage in that slot. Otherwise it has no effect.
@@ -349,6 +379,15 @@ private:
// to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
// on a compile-time option) set to a new sync object in updateTexImage.
EGLSyncKHR mFence;
+
+#ifdef STE_HARDWARE
+ // mEglDisplay is the EGLDisplay with which this SurfaceTexture is currently
+ // associated. It is intialized to EGL_NO_DISPLAY and gets set to the
+ // current display when updateTexImage is called for the first time and when
+ // attachToContext is called.
+ EGLDisplay mEglDisplay;
+#endif
+
};
// mEglDisplay is the EGLDisplay with which this SurfaceTexture is currently
@@ -357,6 +396,40 @@ private:
// attachToContext is called.
EGLDisplay mEglDisplay;
+#ifdef STE_HARDWARE
+ // mBlitEngine is the handle to the copybit device which will be used in
+ // case color transform is needed before the EGL image is created.
+ copybit_device_t* mBlitEngine;
+
+ // mBlitSlots contains several buffers which will
+ // be rendered alternately in case color transform is needed (instead
+ // of rendering the buffers in mSlots).
+ EGLSlot mBlitSlots[NUM_BLIT_BUFFER_SLOTS];
+
+ // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
+ // allocate new GraphicBuffer objects.
+ sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
+
+ // mNextBlitSlot is the index of the blitter buffer (in mBlitSlots) which
+ // will be used in the next color transform.
+ int mNextBlitSlot;
+
+ // mConversionSrcSlot designates the slot where source buffer
+ // for the last deferred updateTexImage is located.
+ int mConversionSrcSlot;
+
+ // mConversionBltSlot designates the slot where destination buffer
+ // for the last deferred updateTexImage is located.
+ int mConversionBltSlot;
+
+ // mNeedsConversion indicates that a format conversion is necessary
+ // before the layer based on this surface is drawn.
+ // This flag is set whenever updateTexImage() with deferred conversion
+ // is called. It is cleared once the layer is drawn,
+ // or when updateTexImage() w/o deferred conversion is called.
+ bool mNeedsConversion;
+#endif
+
// mEglContext is the OpenGL ES context with which this SurfaceTexture is
// currently associated. It is initialized to EGL_NO_CONTEXT and gets set
// to the current GL context when updateTexImage is called for the first
diff --git a/include/ui/Region.h b/include/ui/Region.h
index f242f18eb..9f4d32951 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -24,6 +24,10 @@
#include <ui/Rect.h>
+#ifdef STE_HARDWARE
+#include <hardware/copybit.h>
+#endif
+
namespace android {
// ---------------------------------------------------------------------------
@@ -195,6 +199,28 @@ Region& Region::operator -= (const Region& rhs) {
Region& Region::operator += (const Point& pt) {
return translateSelf(pt.x, pt.y);
}
+
+#ifdef STE_HARDWARE
+// ---------------------------------------------------------------------------
+
+struct region_iterator : public copybit_region_t {
+ region_iterator(const Region& region)
+ : b(region.begin()), e(region.end()) {
+ this->next = iterate;
+ }
+private:
+ static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+ region_iterator const* me = static_cast<region_iterator const*>(self);
+ if (me->b != me->e) {
+ *reinterpret_cast<Rect*>(rect) = *me->b++;
+ return 1;
+ }
+ return 0;
+ }
+ mutable Region::const_iterator b;
+ Region::const_iterator const e;
+};
+#endif
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 2eca22821..21f311269 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -120,6 +120,10 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
mUseFenceSync(false),
#endif
mTexTarget(texTarget),
+#ifdef STE_HARDWARE
+ mNextBlitSlot(0),
+ mNeedsConversion(false),
+#endif
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
mAbandoned(false),
@@ -128,6 +132,13 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
{
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
+#ifdef STE_HARDWARE
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+ if (mGraphicBufferAlloc == 0) {
+ ST_LOGE("createGraphicBufferAlloc() failed in SurfaceTexture()");
+ }
+#endif
ST_LOGV("SurfaceTexture");
if (bufferQueue == 0) {
ST_LOGV("Creating a new BufferQueue");
@@ -140,6 +151,21 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
memcpy(mCurrentTransformMatrix, mtxIdentity,
sizeof(mCurrentTransformMatrix));
+#ifdef STE_HARDWARE
+
+ for (int i = 0; i < NUM_BLIT_BUFFER_SLOTS; i++) {
+ mBlitSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+ mBlitSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+ }
+
+ hw_module_t const* module;
+ mBlitEngine = 0;
+ if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+ copybit_open(module, &mBlitEngine);
+ }
+ ALOGE_IF(!mBlitEngine, "\nCannot open copybit mBlitEngine=%p", mBlitEngine);
+#endif
+
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
@@ -163,6 +189,11 @@ SurfaceTexture::~SurfaceTexture() {
ST_LOGV("~SurfaceTexture");
abandon();
+#ifdef STE_HARDWARE
+ if (mBlitEngine) {
+ copybit_close(mBlitEngine);
+ }
+#endif
}
status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
@@ -180,10 +211,19 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
}
status_t SurfaceTexture::updateTexImage() {
+#ifndef STE_HARDWARE
return SurfaceTexture::updateTexImage(NULL);
+#else
+ return SurfaceTexture::updateTexImage(NULL, false);
+#define STE_DEFERDBG 0
+#endif
}
+#ifndef STE_HARDWARE
status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
+#else
+status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter, bool deferConversion) {
+#endif
ATRACE_CALL();
ST_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
@@ -246,6 +286,7 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
return NO_ERROR;
}
+#ifndef STE_HARDWARE
// Update the GL texture object. We may have to do this even when
// item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
// detaching from a context but the buffer has not been re-allocated.
@@ -271,6 +312,102 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
}
}
}
+#else
+ EGLImageKHR image;
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ if (conversionIsNeeded(mEGLSlots[buf].mGraphicBuffer)) {
+ mNeedsConversion = deferConversion;
+ // If color conversion is needed we can't use the graphic buffers
+ // located in mSlots for the textures (wrong color format). Instead
+ // color convert it into a buffer in mBlitSlots and use that instead.
+ image = mBlitSlots[mNextBlitSlot].mEglImage;
+
+ // If there exists an image already, make sure that
+ // the dimensions match the current source buffer.
+ // Otherwise, destroy the buffer and let a new one be allocated.
+ if (image != EGL_NO_IMAGE_KHR &&
+ mEGLSlots[buf].mGraphicBuffer != NULL &&
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer != NULL) {
+ sp<GraphicBuffer> &srcBuf = mEGLSlots[buf].mGraphicBuffer;
+ sp<GraphicBuffer> &bltBuf =
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer;
+ if (srcBuf->getWidth() != bltBuf->getWidth() ||
+ srcBuf->getHeight() != bltBuf->getHeight()) {
+ eglDestroyImageKHR(mBlitSlots[mNextBlitSlot].mEglDisplay,
+ image);
+ mBlitSlots[mNextBlitSlot].mEglImage = EGL_NO_IMAGE_KHR;
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer = NULL;
+ image = EGL_NO_IMAGE_KHR;
+ }
+ }
+ if (image == EGL_NO_IMAGE_KHR) {
+ sp<GraphicBuffer> &srcBuf = mEGLSlots[buf].mGraphicBuffer;
+ status_t res = 0;
+
+ sp<GraphicBuffer> blitBuffer(
+ mGraphicBufferAlloc->createGraphicBuffer(
+ srcBuf->getWidth(), srcBuf->getHeight(),
+ PIXEL_FORMAT_RGBA_8888, srcBuf->getUsage(),
+ &res));
+ if (blitBuffer == 0) {
+ ST_LOGE("updateTexImage: SurfaceComposer::createGraphicBuffer failed");
+ return NO_MEMORY;
+ }
+ if (res != NO_ERROR) {
+ ST_LOGW("updateTexImage: SurfaceComposer::createGraphicBuffer error=%#04x", res);
+ }
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer = blitBuffer;
+
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ image = createImage(dpy, blitBuffer);
+ mBlitSlots[mNextBlitSlot].mEglImage = image;
+ mBlitSlots[mNextBlitSlot].mEglDisplay = dpy;
+ }
+
+ if (deferConversion) {
+ item.mGraphicBuffer = mEGLSlots[buf].mGraphicBuffer;
+ mConversionSrcSlot = buf;
+ mConversionBltSlot = mNextBlitSlot;
+ // At this point item.mGraphicBuffer and image do not point
+ // at matching buffers. This is intentional as this
+ // surface might end up being taken care of by HWComposer,
+ // which needs access to the original buffer.
+ // GL however, is fed an EGLImage that is created from
+ // a conversion buffer. It will have its
+ // content updated once the surface is actually drawn
+ // in Layer::onDraw()
+ } else {
+ if (convert(mEGLSlots[buf].mGraphicBuffer,
+ mBlitSlots[mNextBlitSlot].mGraphicBuffer) != OK) {
+ ALOGE("updateTexImage: convert failed");
+ return UNKNOWN_ERROR;
+ }
+ item.mGraphicBuffer = mBlitSlots[mNextBlitSlot].mGraphicBuffer;
+ }
+ // mBlitSlots contains several buffers (NUM_BLIT_BUFFER_SLOTS),
+ // advance (potentially wrap) the index
+ mNextBlitSlot = (mNextBlitSlot + 1) % NUM_BLIT_BUFFER_SLOTS;
+ } else {
+ mNeedsConversion = false;
+ image = mEGLSlots[buf].mEglImage ;
+ item.mGraphicBuffer = mEGLSlots[buf].mGraphicBuffer;
+ if (image == EGL_NO_IMAGE_KHR) {
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ if (item.mGraphicBuffer == 0) {
+ ST_LOGE("buffer at slot %d is null", buf);
+ return BAD_VALUE;
+ }
+ image = createImage(dpy, item.mGraphicBuffer);
+ mEGLSlots[buf].mEglImage = image;
+ mEglDisplay = dpy;
+ if (image == EGL_NO_IMAGE_KHR) {
+ // NOTE: if dpy was invalid, createImage() is guaranteed to
+ // fail. so we'd end up here.
+ return -EINVAL;
+ }
+ }
+ }
+#endif
if (err == NO_ERROR) {
GLint error;
@@ -278,10 +415,14 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
}
+#ifndef STE_HARDWARE
if(gpuSupportedFormat) {
+#endif
glBindTexture(mTexTarget, mTexName);
glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
+#ifndef STE_HARDWARE
}
+#endif
while ((error = glGetError()) != GL_NO_ERROR) {
ST_LOGE("updateTexImage: error binding external texture image %p "
"(slot %d): %#04x", image, buf, error);
@@ -322,7 +463,11 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
// Update the SurfaceTexture state.
mCurrentTexture = buf;
+#ifndef STE_HARDWARE
mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
+#else
+ mCurrentTextureBuf = item.mGraphicBuffer;
+#endif
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
mCurrentScalingMode = item.mScalingMode;
@@ -758,6 +903,16 @@ void SurfaceTexture::abandon() {
for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
freeBufferLocked(i);
}
+#ifdef STE_HARDWARE
+ for (int i = 0; i < NUM_BLIT_BUFFER_SLOTS; i++) {
+ mBlitSlots[i].mGraphicBuffer = 0;
+ if (mBlitSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mBlitSlots[i].mEglDisplay, mBlitSlots[i].mEglImage);
+ mBlitSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+ mBlitSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+ }
+ }
+#endif
// disconnect from the BufferQueue
mBufferQueue->consumerDisconnect();
@@ -861,6 +1016,84 @@ void SurfaceTexture::dump(String8& result, const char* prefix,
}
}
+#ifdef STE_HARDWARE
+bool SurfaceTexture::conversionIsNeeded(const sp<GraphicBuffer>& graphicBuffer) {
+ int fmt = graphicBuffer->getPixelFormat();
+ return (fmt == PIXEL_FORMAT_YCBCR42XMBN) || (fmt == PIXEL_FORMAT_YCbCr_420_P);
+}
+
+status_t SurfaceTexture::convert() {
+ if (!mNeedsConversion)
+ return NO_ERROR;
+
+ if (mConversionBltSlot < 0 ||
+ mConversionBltSlot >= NUM_BLIT_BUFFER_SLOTS ||
+ mConversionSrcSlot < 0 ||
+ mConversionSrcSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
+ ALOGE_IF(STE_DEFERDBG, "%s: Incorrect setup for deferred "
+ "texture conversion:\n"
+ "mConversionSrcSlot=%d mConversionBltSlot=%d", __FUNCTION__,
+ mConversionSrcSlot, mConversionBltSlot);
+ return BAD_VALUE;
+ }
+
+ if (mEGLSlots[mConversionSrcSlot].mGraphicBuffer == NULL) {
+ ALOGI_IF(STE_DEFERDBG, "%s: NULL source for deferred texture conversion.",
+ __FUNCTION__);
+ return OK;
+ }
+
+ if (mBlitSlots[mConversionBltSlot].mGraphicBuffer == NULL) {
+ ALOGI_IF(STE_DEFERDBG, "%s: NULL destination for deferred "
+ "texture conversion.", __FUNCTION__);
+ return OK;
+ }
+
+ return convert(mEGLSlots[mConversionSrcSlot].mGraphicBuffer,
+ mBlitSlots[mConversionBltSlot].mGraphicBuffer);
+}
+
+status_t SurfaceTexture::convert(sp<GraphicBuffer> &srcBuf, sp<GraphicBuffer> &dstBuf) {
+ copybit_image_t dstImg;
+ dstImg.w = dstBuf->getWidth();
+ dstImg.h = dstBuf->getHeight();
+ dstImg.format = dstBuf->getPixelFormat();
+ dstImg.handle = (native_handle_t*) dstBuf->getNativeBuffer()->handle;
+
+ copybit_image_t srcImg;
+ srcImg.w = srcBuf->getWidth();
+ srcImg.h = srcBuf->getHeight();
+ srcImg.format = srcBuf->getPixelFormat();
+ srcImg.base = NULL;
+ srcImg.handle = (native_handle_t*) srcBuf->getNativeBuffer()->handle;
+
+ copybit_rect_t dstCrop;
+ dstCrop.l = 0;
+ dstCrop.t = 0;
+ dstCrop.r = dstBuf->getWidth();
+ dstCrop.b = dstBuf->getHeight();
+
+ copybit_rect_t srcCrop;
+ srcCrop.l = 0;
+ srcCrop.t = 0;
+ srcCrop.r = srcBuf->getWidth();
+ srcCrop.b = srcBuf->getHeight();
+
+ region_iterator clip(Region(Rect(dstCrop.r, dstCrop.b)));
+ mBlitEngine->set_parameter(mBlitEngine, COPYBIT_TRANSFORM, 0);
+ mBlitEngine->set_parameter(mBlitEngine, COPYBIT_PLANE_ALPHA, 0xFF);
+ mBlitEngine->set_parameter(mBlitEngine, COPYBIT_DITHER, COPYBIT_ENABLE);
+
+ int err = mBlitEngine->stretch(
+ mBlitEngine, &dstImg, &srcImg, &dstCrop, &srcCrop, &clip);
+ if (err != 0) {
+ ALOGE("\nError: Blit stretch operation failed (err:%d)\n", err);
+ return UNKNOWN_ERROR;
+ }
+ return OK;
+}
+#endif
+
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/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index e73dac877..2135cb50c 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -103,26 +103,24 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info)
#ifdef STE_HARDWARE
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_P:
-#endif
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
-#ifdef STE_HARDWARE
+ case HAL_PIXEL_FORMAT_YCrCb_422_P:
case HAL_PIXEL_FORMAT_CbYCrY_422_I:
#endif
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
info->bitsPerPixel = 16;
goto done;
#ifdef STE_HARDWARE
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-#endif
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YV12:
-#ifdef STE_HARDWARE
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED:
case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_YCrCb_420_P:
case HAL_PIXEL_FORMAT_YCbCr_420_I:
case HAL_PIXEL_FORMAT_CbYCrY_420_I:
case HAL_PIXEL_FORMAT_YCBCR42XMBN:
#endif
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YV12:
info->bitsPerPixel = 12;
done:
info->format = format;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 6896feb45..f30644029 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -447,6 +447,10 @@ void DisplayHardware::flip(const Region& dirty) const
if (mHwc->initCheck() == NO_ERROR) {
mHwc->commit();
} else {
+#ifdef STE_HARDWARE
+ // Make sure the swapbuffer call is done in sync
+ mNativeWindow->compositionComplete();
+#endif
eglSwapBuffers(dpy, surface);
}
checkEGLErrors("eglSwapBuffers");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 84a9060d3..520a9fbc0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -332,6 +332,18 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
void Layer::onDraw(const Region& clip) const
{
+#ifdef STE_HARDWARE
+ // Convert the texture to a native format if need be.
+ // convert() returns immediately if no conversion is necessary.
+ if (mSurfaceTexture != NULL) {
+ status_t res = mSurfaceTexture->convert();
+ if (res != NO_ERROR) {
+ ALOGE("Layer::onDraw: texture conversion failed. "
+ "Texture content for this layer will not be initialized.");
+ }
+ }
+#endif
+
ATRACE_CALL();
if (CC_UNLIKELY(mActiveBuffer == 0)) {
@@ -646,7 +658,12 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
+#ifndef STE_HARDWARE
if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
+#else
+ if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) {
+#endif
+
// something happened!
recomputeVisibleRegions = true;
return;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3ca2297f3..17a810eb2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -479,12 +479,16 @@ void SurfaceFlinger::onMessageReceived(int32_t what)
if (CC_LIKELY(hw.canDraw())) {
// repaint the framebuffer (if needed)
handleRepaint();
+#ifndef STE_HARDWARE
// inform the h/w that we're done compositing
hw.compositionComplete();
+#endif
postFramebuffer();
} else {
+#ifdef STE_HARDWARE
// pretend we did the post
hw.compositionComplete();
+#endif
}
} break;
@@ -891,8 +895,10 @@ void SurfaceFlinger::handleRepaint()
// set the frame buffer
const DisplayHardware& hw(graphicPlane(0).displayHardware());
+#ifndef STE_HARDWARE
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
+#endif
uint32_t flags = hw.getFlags();
if (flags & DisplayHardware::SWAP_RECTANGLE) {
@@ -922,8 +928,15 @@ void SurfaceFlinger::handleRepaint()
mDirtyRegion.clear();
}
+#ifdef STE_HARDWARE
+static bool checkDrawingWithGL(hwc_layer_t* const layers, size_t layerCount);
+#endif
+
void SurfaceFlinger::setupHardwareComposer()
{
+#ifdef STE_HARDWARE
+ bool useGL = true;
+#endif
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
hwc_layer_t* const cur(hwc.getLayers());
@@ -953,8 +966,40 @@ void SurfaceFlinger::setupHardwareComposer()
}
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+#ifdef STE_HARDWARE
+ /*
+ * Check if GL will be used
+ */
+ useGL = checkDrawingWithGL(cur, count);
+
+ if (!useGL) {
+ return;
+ }
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ if (CC_UNLIKELY(!mWormholeRegion.isEmpty())) {
+ // should never happen unless the window manager has a bug
+ // draw something...
+ drawWormhole();
+ }
+#endif
}
+#ifdef STE_HARDWARE
+static bool checkDrawingWithGL(hwc_layer_t* const layers, size_t layerCount)
+{
+ bool useGL = false;
+ if (layers) {
+ for (size_t i=0 ; i<layerCount ; i++) {
+ if (layers[i].compositionType == HWC_FRAMEBUFFER) {
+ useGL = true;
+ }
+ }
+ }
+ return useGL;
+}
+#endif
+
void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
@@ -981,6 +1026,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
glClear(GL_COLOR_BUFFER_BIT);
}
} else {
+#ifndef STE_HARDWARE
// screen is already cleared here
if (!mWormholeRegion.isEmpty()) {
// can happen with SurfaceView
@@ -990,6 +1036,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
#endif
drawWormhole();
}
+#endif
}
/*
@@ -2541,7 +2588,9 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
glDeleteRenderbuffersOES(1, &tname);
glDeleteFramebuffersOES(1, &name);
+#ifdef STE_HARDWARE
hw.compositionComplete();
+#endif
// ALOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
@@ -2769,9 +2818,15 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
+#ifndef STE_HARDWARE
ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
"failed (%s), handle=%p",
w, h, strerror(-err), graphicBuffer->handle);
+#else
+ ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d, format=%#x) "
+ "failed (%s), handle=%p",
+ w, h, format, strerror(-err), graphicBuffer->handle);
+#endif
return 0;
}
return graphicBuffer;