SurfaceTexture: Fully refactored from BufferQueue
SurfaceTexture and BufferQueue are separate objects. Change-Id: I230bc0ae6f78d0f9b2b5df902f40ab443ed5a055
This commit is contained in:
parent
fddc28d871
commit
b267579ba8
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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]) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user