SurfaceTexture: Fully refactored from BufferQueue

SurfaceTexture and BufferQueue are separate objects.

Change-Id: I230bc0ae6f78d0f9b2b5df902f40ab443ed5a055
This commit is contained in:
Daniel Lam 2012-02-23 14:35:13 -08:00
parent fddc28d871
commit b267579ba8
11 changed files with 204 additions and 112 deletions

View File

@ -203,6 +203,16 @@ public:
// when a new frame becomes available. // when a new frame becomes available.
void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
// setDefaultBufferFormat allows the BufferQueue to create
// GraphicBuffers of a defaultFormat if no format is specified
// in dequeueBuffer
status_t setDefaultBufferFormat(uint32_t defaultFormat);
// setConsumerUsageBits will turn on additional usage bits for dequeueBuffer
status_t setConsumerUsageBits(uint32_t usage);
// setTransformHint bakes in rotation to buffers so overlays can be used
status_t setTransformHint(uint32_t hint);
private: private:
// freeBufferLocked frees the resources (both GraphicBuffer and EGLImage) // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
@ -417,7 +427,19 @@ private:
// with the surface Texture. // with the surface Texture.
uint64_t mFrameCounter; uint64_t mFrameCounter;
// mBufferHasBeenQueued is true once a buffer has been queued. It is reset
// by changing the buffer count.
bool mBufferHasBeenQueued; bool mBufferHasBeenQueued;
// mDefaultBufferFormat can be set so it will override
// the buffer format when it isn't specified in dequeueBuffer
uint32_t mDefaultBufferFormat;
// mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
uint32_t mConsumerUsageBits;
// mTransformHint is used to optimize for screen rotations
uint32_t mTransformHint;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -39,8 +39,12 @@ namespace android {
class String8; class String8;
class SurfaceTexture : public BufferQueue { class SurfaceTexture : public virtual RefBase {
public: public:
// This typedef allows external code to continue referencing
// SurfaceTexture::FrameAvailableListener during refactoring
typedef BufferQueue::FrameAvailableListener FrameAvailableListener;
// SurfaceTexture constructs a new SurfaceTexture object. tex indicates the // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
// name of the OpenGL ES texture to which images are to be streamed. This // name of the OpenGL ES texture to which images are to be streamed. This
@ -49,14 +53,15 @@ public:
// enabled. texTarget specifies the OpenGL ES texture target to which the // enabled. texTarget specifies the OpenGL ES texture target to which the
// texture will be bound in updateTexImage. useFenceSync specifies whether // texture will be bound in updateTexImage. useFenceSync specifies whether
// fences should be used to synchronize access to buffers if that behavior // fences should be used to synchronize access to buffers if that behavior
// is enabled at compile-time. // is enabled at compile-time. A custom bufferQueue can be specified
// if behavior for queue/dequeue/connect etc needs to be customized.
// Otherwise a default BufferQueue will be created and used.
SurfaceTexture(GLuint tex, bool allowSynchronousMode = true, SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true); GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
const sp<BufferQueue> &bufferQueue = 0);
virtual ~SurfaceTexture(); virtual ~SurfaceTexture();
// updateTexImage sets the image contents of the target texture to that of // updateTexImage sets the image contents of the target texture to that of
// the most recently queued buffer. // the most recently queued buffer.
// //
@ -152,6 +157,18 @@ public:
// log messages. // log messages.
void setName(const String8& name); void setName(const String8& name);
// These functions call the corresponding BufferQueue implementation
// so the refactoring can proceed smoothly
status_t setDefaultBufferFormat(uint32_t defaultFormat);
status_t setConsumerUsageBits(uint32_t usage);
status_t setTransformHint(uint32_t hint);
virtual status_t setSynchronousMode(bool enabled);
virtual status_t setBufferCount(int bufferCount);
virtual status_t connect(int api,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
sp<BufferQueue> getBufferQueue() const;
// dump our state in a String // dump our state in a String
virtual void dump(String8& result) const; virtual void dump(String8& result) const;
virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
@ -241,7 +258,7 @@ private:
EGLSyncKHR mFence; EGLSyncKHR mFence;
}; };
EGLSlot mEGLSlots[NUM_BUFFER_SLOTS]; EGLSlot mEGLSlots[BufferQueue::NUM_BUFFER_SLOTS];
// mAbandoned indicates that the BufferQueue will no longer be used to // mAbandoned indicates that the BufferQueue will no longer be used to
// consume images buffers pushed to it using the ISurfaceTexture interface. // consume images buffers pushed to it using the ISurfaceTexture interface.
@ -267,6 +284,10 @@ private:
// reset mCurrentTexture to INVALID_BUFFER_SLOT. // reset mCurrentTexture to INVALID_BUFFER_SLOT.
int mCurrentTexture; int mCurrentTexture;
// The SurfaceTexture has-a BufferQueue and is responsible for creating this object
// if none is supplied
sp<BufferQueue> mBufferQueue;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -19,6 +19,7 @@
#include <gui/ISurfaceTexture.h> #include <gui/ISurfaceTexture.h>
#include <gui/SurfaceTexture.h> #include <gui/SurfaceTexture.h>
#include <gui/BufferQueue.h>
#include <ui/ANativeObjectBase.h> #include <ui/ANativeObjectBase.h>
#include <ui/Region.h> #include <ui/Region.h>
@ -34,8 +35,15 @@ class SurfaceTextureClient
: public ANativeObjectBase<ANativeWindow, SurfaceTextureClient, RefBase> : public ANativeObjectBase<ANativeWindow, SurfaceTextureClient, RefBase>
{ {
public: public:
SurfaceTextureClient(const sp<ISurfaceTexture>& surfaceTexture); SurfaceTextureClient(const sp<ISurfaceTexture>& surfaceTexture);
// SurfaceTextureClient is overloaded to assist in refactoring ST and BQ.
// SurfaceTexture is no longer an ISurfaceTexture, so client code
// calling the original constructor will fail. Thus this convenience method
// passes in the surfaceTexture's bufferQueue to the init method.
SurfaceTextureClient(const sp<SurfaceTexture>& surfaceTexture);
sp<ISurfaceTexture> getISurfaceTexture() const; sp<ISurfaceTexture> getISurfaceTexture() const;
protected: protected:
@ -94,8 +102,8 @@ protected:
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
virtual int unlockAndPost(); virtual int unlockAndPost();
enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS }; enum { MIN_UNDEQUEUED_BUFFERS = BufferQueue::MIN_UNDEQUEUED_BUFFERS };
enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS }; enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
private: private:

View File

@ -83,7 +83,10 @@ BufferQueue::BufferQueue( bool allowSynchronousMode ) :
mConnectedApi(NO_CONNECTED_API), mConnectedApi(NO_CONNECTED_API),
mAbandoned(false), mAbandoned(false),
mFrameCounter(0), mFrameCounter(0),
mBufferHasBeenQueued(false) mBufferHasBeenQueued(false),
mDefaultBufferFormat(0),
mConsumerUsageBits(0),
mTransformHint(0)
{ {
// Choose a name using the PID and a process-unique ID. // Choose a name using the PID and a process-unique ID.
mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
@ -128,6 +131,7 @@ status_t BufferQueue::setBufferCountServerLocked(int bufferCount) {
// dequeueBuffer. // dequeueBuffer.
mServerBufferCount = bufferCount; mServerBufferCount = bufferCount;
mDequeueCondition.broadcast();
} }
return OK; return OK;
} }
@ -149,6 +153,24 @@ void BufferQueue::setFrameAvailableListener(
mFrameAvailableListener = listener; mFrameAvailableListener = listener;
} }
status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
Mutex::Autolock lock(mMutex);
mDefaultBufferFormat = defaultFormat;
return OK;
}
status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
Mutex::Autolock lock(mMutex);
mConsumerUsageBits = usage;
return OK;
}
status_t BufferQueue::setTransformHint(uint32_t hint) {
Mutex::Autolock lock(mMutex);
mTransformHint = hint;
return OK;
}
status_t BufferQueue::setBufferCount(int bufferCount) { status_t BufferQueue::setBufferCount(int bufferCount) {
ST_LOGV("setBufferCount: count=%d", bufferCount); ST_LOGV("setBufferCount: count=%d", bufferCount);
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
@ -263,6 +285,12 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
{ // Scope for the lock { // Scope for the lock
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
if (format == 0) {
format = mDefaultBufferFormat;
}
// turn on usage bits the consumer requested
usage |= mConsumerUsageBits;
int found = -1; int found = -1;
int foundSync = -1; int foundSync = -1;
int dequeuedCount = 0; int dequeuedCount = 0;
@ -563,7 +591,7 @@ status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
*outWidth = mDefaultWidth; *outWidth = mDefaultWidth;
*outHeight = mDefaultHeight; *outHeight = mDefaultHeight;
*outTransform = 0; *outTransform = mTransformHint;
ATRACE_INT(mConsumerName.string(), mQueue.size()); ATRACE_INT(mConsumerName.string(), mQueue.size());
} // scope for the lock } // scope for the lock
@ -846,7 +874,8 @@ status_t BufferQueue::acquire(BufferItem *buffer) {
ATRACE_INT(mConsumerName.string(), mQueue.size()); ATRACE_INT(mConsumerName.string(), mQueue.size());
} }
else { else {
return -EINVAL; //should be a better return code // should be a better return code?
return -EINVAL;
} }
return OK; return OK;
@ -880,9 +909,10 @@ status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
status_t BufferQueue::consumerDisconnect() { status_t BufferQueue::consumerDisconnect() {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
// Once the SurfaceTexture disconnects, the BufferQueue
// is considered abandoned
mAbandoned = true; mAbandoned = true;
mQueue.clear();
freeAllBuffersLocked(); freeAllBuffersLocked();
mDequeueCondition.broadcast(); mDequeueCondition.broadcast();
return OK; return OK;

View File

@ -105,8 +105,7 @@ static int32_t createProcessUniqueId() {
} }
SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
GLenum texTarget, bool useFenceSync) : GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
BufferQueue(allowSynchronousMode),
mCurrentTransform(0), mCurrentTransform(0),
mCurrentTimestamp(0), mCurrentTimestamp(0),
mTexName(tex), mTexName(tex),
@ -121,27 +120,37 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
{ {
// Choose a name using the PID and a process-unique ID. // Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
BufferQueue::setConsumerName(mName);
ST_LOGV("SurfaceTexture"); ST_LOGV("SurfaceTexture");
if (bufferQueue == 0) {
ST_LOGV("Creating a new BufferQueue");
mBufferQueue = new BufferQueue(allowSynchronousMode);
}
else {
mBufferQueue = bufferQueue;
}
mBufferQueue->setConsumerName(mName);
memcpy(mCurrentTransformMatrix, mtxIdentity, memcpy(mCurrentTransformMatrix, mtxIdentity,
sizeof(mCurrentTransformMatrix)); sizeof(mCurrentTransformMatrix));
} }
SurfaceTexture::~SurfaceTexture() { SurfaceTexture::~SurfaceTexture() {
ST_LOGV("~SurfaceTexture"); ST_LOGV("~SurfaceTexture");
abandon(); abandon();
} }
status_t SurfaceTexture::setBufferCountServer(int bufferCount) { status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
return BufferQueue::setBufferCountServer(bufferCount); return mBufferQueue->setBufferCountServer(bufferCount);
} }
status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
{ {
return BufferQueue::setDefaultBufferSize(w, h); Mutex::Autolock lock(mMutex);
return mBufferQueue->setDefaultBufferSize(w, h);
} }
status_t SurfaceTexture::updateTexImage() { status_t SurfaceTexture::updateTexImage() {
@ -154,11 +163,11 @@ status_t SurfaceTexture::updateTexImage() {
return NO_INIT; return NO_INIT;
} }
BufferItem item; BufferQueue::BufferItem item;
// In asynchronous mode the list is guaranteed to be one buffer // In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer. // deep, while in synchronous mode we use the oldest buffer.
if (acquire(&item) == NO_ERROR) { if (mBufferQueue->acquire(&item) == NO_ERROR) {
int buf = item.mBuf; int buf = item.mBuf;
// This buffer was newly allocated, so we need to clean up on our side // This buffer was newly allocated, so we need to clean up on our side
if (item.mGraphicBuffer != NULL) { if (item.mGraphicBuffer != NULL) {
@ -205,19 +214,19 @@ status_t SurfaceTexture::updateTexImage() {
failed = true; failed = true;
} }
if (failed) { if (failed) {
releaseBuffer(buf, mEGLSlots[buf].mEglDisplay, mBufferQueue->releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
mEGLSlots[buf].mFence); mEGLSlots[buf].mFence);
return -EINVAL; return -EINVAL;
} }
if (mCurrentTexture != INVALID_BUFFER_SLOT) { if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (mUseFenceSync) { if (mUseFenceSync) {
EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
NULL); NULL);
if (fence == EGL_NO_SYNC_KHR) { if (fence == EGL_NO_SYNC_KHR) {
ALOGE("updateTexImage: error creating fence: %#x", ALOGE("updateTexImage: error creating fence: %#x",
eglGetError()); eglGetError());
releaseBuffer(buf, mEGLSlots[buf].mEglDisplay, mBufferQueue->releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
mEGLSlots[buf].mFence); mEGLSlots[buf].mFence);
return -EINVAL; return -EINVAL;
} }
@ -232,7 +241,7 @@ status_t SurfaceTexture::updateTexImage() {
buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0); buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0);
// release old buffer // release old buffer
releaseBuffer(mCurrentTexture, mBufferQueue->releaseBuffer(mCurrentTexture,
mEGLSlots[mCurrentTexture].mEglDisplay, mEGLSlots[mCurrentTexture].mEglDisplay,
mEGLSlots[mCurrentTexture].mFence); mEGLSlots[mCurrentTexture].mFence);
@ -385,7 +394,7 @@ void SurfaceTexture::setFrameAvailableListener(
const sp<FrameAvailableListener>& listener) { const sp<FrameAvailableListener>& listener) {
ST_LOGV("setFrameAvailableListener"); ST_LOGV("setFrameAvailableListener");
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
BufferQueue::setFrameAvailableListener(listener); mBufferQueue->setFrameAvailableListener(listener);
} }
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
@ -426,7 +435,7 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {
bool SurfaceTexture::isSynchronousMode() const { bool SurfaceTexture::isSynchronousMode() const {
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
return BufferQueue::isSynchronousMode(); return mBufferQueue->isSynchronousMode();
} }
void SurfaceTexture::abandon() { void SurfaceTexture::abandon() {
@ -435,7 +444,7 @@ void SurfaceTexture::abandon() {
mCurrentTextureBuf.clear(); mCurrentTextureBuf.clear();
// destroy all egl buffers // destroy all egl buffers
for (int i =0; i < NUM_BUFFER_SLOTS; i++) { for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
mEGLSlots[i].mGraphicBuffer = 0; mEGLSlots[i].mGraphicBuffer = 0;
if (mEGLSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { if (mEGLSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mEGLSlots[i].mEglDisplay, eglDestroyImageKHR(mEGLSlots[i].mEglDisplay,
@ -446,13 +455,54 @@ void SurfaceTexture::abandon() {
} }
// disconnect from the BufferQueue // disconnect from the BufferQueue
BufferQueue::consumerDisconnect(); mBufferQueue->consumerDisconnect();
} }
void SurfaceTexture::setName(const String8& name) { void SurfaceTexture::setName(const String8& name) {
Mutex::Autolock _l(mMutex); Mutex::Autolock _l(mMutex);
mName = name; mName = name;
BufferQueue::setConsumerName(name); mBufferQueue->setConsumerName(name);
}
status_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
Mutex::Autolock lock(mMutex);
return mBufferQueue->setDefaultBufferFormat(defaultFormat);
}
status_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
Mutex::Autolock lock(mMutex);
return mBufferQueue->setConsumerUsageBits(usage);
}
status_t SurfaceTexture::setTransformHint(uint32_t hint) {
Mutex::Autolock lock(mMutex);
return mBufferQueue->setTransformHint(hint);
}
// Used for refactoring BufferQueue from SurfaceTexture
// Should not be in final interface once users of SurfaceTexture are clean up.
status_t SurfaceTexture::setSynchronousMode(bool enabled) {
Mutex::Autolock lock(mMutex);
return mBufferQueue->setSynchronousMode(enabled);
}
// Used for refactoring, should not be in final interface
sp<BufferQueue> SurfaceTexture::getBufferQueue() const {
Mutex::Autolock lock(mMutex);
return mBufferQueue;
}
// Used for refactoring, should not be in final interface
status_t SurfaceTexture::setBufferCount(int bufferCount) {
Mutex::Autolock lock(mMutex);
return mBufferQueue->setBufferCount(bufferCount);
}
// Used for refactoring, should not be in final interface
status_t SurfaceTexture::connect(int api,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Mutex::Autolock lock(mMutex);
return mBufferQueue->connect(api, outWidth, outHeight, outTransform);
} }
void SurfaceTexture::dump(String8& result) const void SurfaceTexture::dump(String8& result) const
@ -477,7 +527,7 @@ void SurfaceTexture::dump(String8& result, const char* prefix,
result.append(buffer); result.append(buffer);
BufferQueue::dump(result, prefix, buffer, SIZE); mBufferQueue->dump(result, prefix, buffer, SIZE);
} }
static void mtxMul(float out[16], const float a[16], const float b[16]) { static void mtxMul(float out[16], const float a[16], const float b[16]) {

View File

@ -36,6 +36,14 @@ SurfaceTextureClient::SurfaceTextureClient(
SurfaceTextureClient::setISurfaceTexture(surfaceTexture); SurfaceTextureClient::setISurfaceTexture(surfaceTexture);
} }
// see SurfaceTextureClient.h
SurfaceTextureClient::SurfaceTextureClient(const
sp<SurfaceTexture>& surfaceTexture)
{
SurfaceTextureClient::init();
SurfaceTextureClient::setISurfaceTexture(surfaceTexture->getBufferQueue());
}
SurfaceTextureClient::SurfaceTextureClient() { SurfaceTextureClient::SurfaceTextureClient() {
SurfaceTextureClient::init(); SurfaceTextureClient::init();
} }

View File

@ -97,9 +97,19 @@ void Layer::onFirstRef()
} }
} }
}; };
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
// Creates a custom BufferQueue for SurfaceTexture to use
sp<BufferQueue> bq = new SurfaceTextureLayer();
mSurfaceTexture = new SurfaceTexture(mTextureName, true,
GL_TEXTURE_EXTERNAL_OES, false,bq);
mSurfaceTexture->setTransformHint(getTransformHint());
mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this)); mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
mSurfaceTexture->setSynchronousMode(true); mSurfaceTexture->setSynchronousMode(true);
#ifdef USE_TRIPLE_BUFFERING #ifdef USE_TRIPLE_BUFFERING
#warning "using triple buffering" #warning "using triple buffering"
mSurfaceTexture->setBufferCountServer(3); mSurfaceTexture->setBufferCountServer(3);
@ -131,6 +141,14 @@ void Layer::setName(const String8& name) {
mSurfaceTexture->setName(name); mSurfaceTexture->setName(name);
} }
void Layer::validateVisibility(const Transform& globalTransform) {
LayerBase::validateVisibility(globalTransform);
// This optimization allows the SurfaceTexture to bake in
// the rotation so hardware overlays can be used
mSurfaceTexture->setTransformHint(getTransformHint());
}
sp<ISurface> Layer::createSurface() sp<ISurface> Layer::createSurface()
{ {
class BSurface : public BnSurface, public LayerCleaner { class BSurface : public BnSurface, public LayerCleaner {
@ -139,7 +157,7 @@ sp<ISurface> Layer::createSurface()
sp<ISurfaceTexture> res; sp<ISurfaceTexture> res;
sp<const Layer> that( mOwner.promote() ); sp<const Layer> that( mOwner.promote() );
if (that != NULL) { if (that != NULL) {
res = that->mSurfaceTexture; res = that->mSurfaceTexture->getBufferQueue();
} }
return res; return res;
} }
@ -154,7 +172,7 @@ sp<ISurface> Layer::createSurface()
wp<IBinder> Layer::getSurfaceTextureBinder() const wp<IBinder> Layer::getSurfaceTextureBinder() const
{ {
return mSurfaceTexture->asBinder(); return mSurfaceTexture->getBufferQueue()->asBinder();
} }
status_t Layer::setBuffers( uint32_t w, uint32_t h, status_t Layer::setBuffers( uint32_t w, uint32_t h,
@ -193,6 +211,7 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mSurfaceTexture->setDefaultBufferSize(w, h); mSurfaceTexture->setDefaultBufferSize(w, h);
mSurfaceTexture->setDefaultBufferFormat(format); mSurfaceTexture->setDefaultBufferFormat(format);
mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
// we use the red index // we use the red index
int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED); int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);

View File

@ -77,6 +77,7 @@ public:
virtual void onRemoved(); virtual void onRemoved();
virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); } virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
virtual void setName(const String8& name); virtual void setName(const String8& name);
virtual void validateVisibility(const Transform& globalTransform);
// LayerBaseClient interface // LayerBaseClient interface
virtual wp<IBinder> getSurfaceTextureBinder() const; virtual wp<IBinder> getSurfaceTextureBinder() const;
@ -105,7 +106,7 @@ private:
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// constants // constants
sp<SurfaceTextureLayer> mSurfaceTexture; sp<SurfaceTexture> mSurfaceTexture;
GLuint mTextureName; GLuint mTextureName;
// thread-safe // thread-safe

View File

@ -1399,6 +1399,7 @@ status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid)
status_t err = NAME_NOT_FOUND; status_t err = NAME_NOT_FOUND;
Mutex::Autolock _l(mStateLock); Mutex::Autolock _l(mStateLock);
sp<LayerBaseClient> layer = client->getLayerUser(sid); sp<LayerBaseClient> layer = client->getLayerUser(sid);
if (layer != 0) { if (layer != 0) {
err = purgatorizeLayer_l(layer); err = purgatorizeLayer_l(layer);
if (err == NO_ERROR) { if (err == NO_ERROR) {

View File

@ -27,72 +27,18 @@ namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer) SurfaceTextureLayer::SurfaceTextureLayer()
: SurfaceTexture(tex, true, GL_TEXTURE_EXTERNAL_OES, false), mLayer(layer) { : BufferQueue(true) {
} }
SurfaceTextureLayer::~SurfaceTextureLayer() { SurfaceTextureLayer::~SurfaceTextureLayer() {
} }
status_t SurfaceTextureLayer::setDefaultBufferSize(uint32_t w, uint32_t h)
{
//ALOGD("%s, w=%u, h=%u", __PRETTY_FUNCTION__, w, h);
return SurfaceTexture::setDefaultBufferSize(w, h);
}
status_t SurfaceTextureLayer::setDefaultBufferFormat(uint32_t format)
{
mDefaultFormat = format;
return NO_ERROR;
}
status_t SurfaceTextureLayer::setBufferCount(int bufferCount) {
status_t res = SurfaceTexture::setBufferCount(bufferCount);
return res;
}
status_t SurfaceTextureLayer::queueBuffer(int buf, int64_t timestamp,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
status_t res = SurfaceTexture::queueBuffer(buf, timestamp,
outWidth, outHeight, outTransform);
sp<Layer> layer(mLayer.promote());
if (layer != NULL) {
*outTransform = layer->getTransformHint();
}
return res;
}
status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
status_t res(NO_INIT);
sp<Layer> layer(mLayer.promote());
if (layer != NULL) {
if (format == 0)
format = mDefaultFormat;
uint32_t effectiveUsage = layer->getEffectiveUsage(usage);
//ALOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x",
// __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage);
res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage);
}
return res;
}
status_t SurfaceTextureLayer::connect(int api, status_t SurfaceTextureLayer::connect(int api,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
status_t err = SurfaceTexture::connect(api, status_t err = BufferQueue::connect(api,
outWidth, outHeight, outTransform); outWidth, outHeight, outTransform);
if (err == NO_ERROR) { if (err == NO_ERROR) {
sp<Layer> layer(mLayer.promote());
if (layer != NULL) {
uint32_t orientation = layer->getOrientation();
if (orientation & Transform::ROT_INVALID) {
orientation = 0;
}
*outTransform = orientation;
}
switch(api) { switch(api) {
case NATIVE_WINDOW_API_CPU: case NATIVE_WINDOW_API_CPU:
// SurfaceTextureClient supports only 2 buffers for CPU connections // SurfaceTextureClient supports only 2 buffers for CPU connections
@ -110,7 +56,7 @@ status_t SurfaceTextureLayer::connect(int api,
#endif #endif
// fall through to set synchronous mode when not defaulting to // fall through to set synchronous mode when not defaulting to
// async mode. // async mode.
deafult: default:
err = setSynchronousMode(true); err = setSynchronousMode(true);
break; break;
} }

View File

@ -22,35 +22,21 @@
#include <sys/types.h> #include <sys/types.h>
#include <utils/Errors.h> #include <utils/Errors.h>
#include <gui/SurfaceTexture.h> #include <gui/BufferQueue.h>
namespace android { namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class Layer; class Layer;
class SurfaceTextureLayer : public SurfaceTexture // SurfaceTextureLayer is now a BufferQueue since SurfaceTexture has been
// refactored
class SurfaceTextureLayer : public BufferQueue
{ {
wp<Layer> mLayer;
uint32_t mDefaultFormat;
public: public:
SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer); SurfaceTextureLayer();
~SurfaceTextureLayer(); ~SurfaceTextureLayer();
status_t setDefaultBufferSize(uint32_t w, uint32_t h);
status_t setDefaultBufferFormat(uint32_t format);
public:
virtual status_t setBufferCount(int bufferCount);
protected:
virtual status_t queueBuffer(int buf, int64_t timestamp,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
uint32_t format, uint32_t usage);
virtual status_t connect(int api, virtual status_t connect(int api,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
}; };