SurfaceTexture: add the abandon method.
This change adds the 'abandon' method to the SurfaceTexture C++ class. This method may be used to put the SurfaceTexture in an abandoned state, causing all ISurfaceTexture methods to fail. Change-Id: Ibd261f7b73f44e2bec36a8508bf92113cfb7cf95
This commit is contained in:
parent
6e50219aee
commit
7b305fffc3
@ -51,7 +51,7 @@ protected:
|
|||||||
// the given slot index, and the client is expected to mirror the
|
// the given slot index, and the client is expected to mirror the
|
||||||
// slot->buffer mapping so that it's not necessary to transfer a
|
// slot->buffer mapping so that it's not necessary to transfer a
|
||||||
// GraphicBuffer for every dequeue operation.
|
// GraphicBuffer for every dequeue operation.
|
||||||
virtual sp<GraphicBuffer> requestBuffer(int slot) = 0;
|
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
|
||||||
|
|
||||||
// setBufferCount sets the number of buffer slots available. Calling this
|
// setBufferCount sets the number of buffer slots available. Calling this
|
||||||
// will also cause all buffer slots to be emptied. The caller should empty
|
// will also cause all buffer slots to be emptied. The caller should empty
|
||||||
|
@ -69,7 +69,7 @@ public:
|
|||||||
// SurfaceTexture object (i.e. they are not owned by the client).
|
// SurfaceTexture object (i.e. they are not owned by the client).
|
||||||
virtual status_t setBufferCount(int bufferCount);
|
virtual status_t setBufferCount(int bufferCount);
|
||||||
|
|
||||||
virtual sp<GraphicBuffer> requestBuffer(int buf);
|
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
|
||||||
|
|
||||||
// dequeueBuffer gets the next buffer slot index for the client to use. If a
|
// dequeueBuffer gets the next buffer slot index for the client to use. If a
|
||||||
// buffer slot is available then that slot index is written to the location
|
// buffer slot is available then that slot index is written to the location
|
||||||
@ -190,6 +190,17 @@ public:
|
|||||||
// getCurrentScalingMode returns the scaling mode of the current buffer
|
// getCurrentScalingMode returns the scaling mode of the current buffer
|
||||||
uint32_t getCurrentScalingMode() const;
|
uint32_t getCurrentScalingMode() const;
|
||||||
|
|
||||||
|
// abandon frees all the buffers and puts the SurfaceTexture into the
|
||||||
|
// 'abandoned' state. Once put in this state the SurfaceTexture can never
|
||||||
|
// leave it. When in the 'abandoned' state, all methods of the
|
||||||
|
// ISurfaceTexture interface will fail with the NO_INIT error.
|
||||||
|
//
|
||||||
|
// Note that while calling this method causes all the buffers to be freed
|
||||||
|
// from the perspective of the the SurfaceTexture, if there are additional
|
||||||
|
// references on the buffers (e.g. if a buffer is referenced by a client or
|
||||||
|
// by OpenGL ES as a texture) then those buffer will remain allocated.
|
||||||
|
void abandon();
|
||||||
|
|
||||||
// dump our state in a String
|
// dump our state in a String
|
||||||
void dump(String8& result) const;
|
void dump(String8& result) const;
|
||||||
void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
|
void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
|
||||||
@ -411,6 +422,13 @@ private:
|
|||||||
typedef Vector<int> Fifo;
|
typedef Vector<int> Fifo;
|
||||||
Fifo mQueue;
|
Fifo mQueue;
|
||||||
|
|
||||||
|
// mAbandoned indicates that the SurfaceTexture will no longer be used to
|
||||||
|
// consume images buffers pushed to it using the ISurfaceTexture interface.
|
||||||
|
// It is initialized to false, and set to true in the abandon method. A
|
||||||
|
// SurfaceTexture that has been abandoned will return the NO_INIT error from
|
||||||
|
// all ISurfaceTexture methods capable of returning an error.
|
||||||
|
bool mAbandoned;
|
||||||
|
|
||||||
// mMutex is the mutex used to prevent concurrent access to the member
|
// mMutex is the mutex used to prevent concurrent access to the member
|
||||||
// variables of SurfaceTexture objects. It must be locked whenever the
|
// variables of SurfaceTexture objects. It must be locked whenever the
|
||||||
// member variables are accessed.
|
// member variables are accessed.
|
||||||
|
@ -54,18 +54,18 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
|
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
|
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
|
||||||
data.writeInt32(bufferIdx);
|
data.writeInt32(bufferIdx);
|
||||||
remote()->transact(REQUEST_BUFFER, data, &reply);
|
remote()->transact(REQUEST_BUFFER, data, &reply);
|
||||||
sp<GraphicBuffer> buffer;
|
|
||||||
bool nonNull = reply.readInt32();
|
bool nonNull = reply.readInt32();
|
||||||
if (nonNull) {
|
if (nonNull) {
|
||||||
buffer = new GraphicBuffer();
|
*buf = new GraphicBuffer();
|
||||||
reply.read(*buffer);
|
reply.read(**buf);
|
||||||
}
|
}
|
||||||
return buffer;
|
status_t result = reply.readInt32();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t setBufferCount(int bufferCount)
|
virtual status_t setBufferCount(int bufferCount)
|
||||||
@ -192,11 +192,13 @@ status_t BnSurfaceTexture::onTransact(
|
|||||||
case REQUEST_BUFFER: {
|
case REQUEST_BUFFER: {
|
||||||
CHECK_INTERFACE(ISurfaceTexture, data, reply);
|
CHECK_INTERFACE(ISurfaceTexture, data, reply);
|
||||||
int bufferIdx = data.readInt32();
|
int bufferIdx = data.readInt32();
|
||||||
sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
|
sp<GraphicBuffer> buffer;
|
||||||
|
int result = requestBuffer(bufferIdx, &buffer);
|
||||||
reply->writeInt32(buffer != 0);
|
reply->writeInt32(buffer != 0);
|
||||||
if (buffer != 0) {
|
if (buffer != 0) {
|
||||||
reply->write(*buffer);
|
reply->write(*buffer);
|
||||||
}
|
}
|
||||||
|
reply->writeInt32(result);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
case SET_BUFFER_COUNT: {
|
case SET_BUFFER_COUNT: {
|
||||||
|
@ -94,7 +94,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
|
|||||||
mTexName(tex),
|
mTexName(tex),
|
||||||
mSynchronousMode(false),
|
mSynchronousMode(false),
|
||||||
mAllowSynchronousMode(allowSynchronousMode),
|
mAllowSynchronousMode(allowSynchronousMode),
|
||||||
mConnectedApi(NO_CONNECTED_API) {
|
mConnectedApi(NO_CONNECTED_API),
|
||||||
|
mAbandoned(false) {
|
||||||
LOGV("SurfaceTexture::SurfaceTexture");
|
LOGV("SurfaceTexture::SurfaceTexture");
|
||||||
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
||||||
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
|
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
|
||||||
@ -150,6 +151,11 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) {
|
|||||||
LOGV("SurfaceTexture::setBufferCount");
|
LOGV("SurfaceTexture::setBufferCount");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("setBufferCount: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
if (bufferCount > NUM_BUFFER_SLOTS) {
|
if (bufferCount > NUM_BUFFER_SLOTS) {
|
||||||
LOGE("setBufferCount: bufferCount larger than slots available");
|
LOGE("setBufferCount: bufferCount larger than slots available");
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -199,22 +205,32 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
|
status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
|
||||||
LOGV("SurfaceTexture::requestBuffer");
|
LOGV("SurfaceTexture::requestBuffer");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
if (buf < 0 || mBufferCount <= buf) {
|
if (mAbandoned) {
|
||||||
LOGE("requestBuffer: slot index out of range [0, %d]: %d",
|
LOGE("requestBuffer: SurfaceTexture has been abandoned!");
|
||||||
mBufferCount, buf);
|
return NO_INIT;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
mSlots[buf].mRequestBufferCalled = true;
|
if (slot < 0 || mBufferCount <= slot) {
|
||||||
return mSlots[buf].mGraphicBuffer;
|
LOGE("requestBuffer: slot index out of range [0, %d]: %d",
|
||||||
|
mBufferCount, slot);
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
mSlots[slot].mRequestBufferCalled = true;
|
||||||
|
*buf = mSlots[slot].mGraphicBuffer;
|
||||||
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
||||||
uint32_t format, uint32_t usage) {
|
uint32_t format, uint32_t usage) {
|
||||||
LOGV("SurfaceTexture::dequeueBuffer");
|
LOGV("SurfaceTexture::dequeueBuffer");
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
if ((w && !h) || (!w && h)) {
|
if ((w && !h) || (!w && h)) {
|
||||||
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
|
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -252,6 +268,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
|||||||
// wait for the FIFO to drain
|
// wait for the FIFO to drain
|
||||||
while (!mQueue.isEmpty()) {
|
while (!mQueue.isEmpty()) {
|
||||||
mDequeueCondition.wait(mMutex);
|
mDequeueCondition.wait(mMutex);
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("dequeueBuffer: SurfaceTexture was abandoned while "
|
||||||
|
"blocked!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
minBufferCountNeeded = mSynchronousMode ?
|
minBufferCountNeeded = mSynchronousMode ?
|
||||||
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
|
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
|
||||||
@ -380,6 +401,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
|||||||
status_t SurfaceTexture::setSynchronousMode(bool enabled) {
|
status_t SurfaceTexture::setSynchronousMode(bool enabled) {
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
status_t err = OK;
|
status_t err = OK;
|
||||||
if (!mAllowSynchronousMode && enabled)
|
if (!mAllowSynchronousMode && enabled)
|
||||||
return err;
|
return err;
|
||||||
@ -410,6 +436,10 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
|
|||||||
|
|
||||||
{ // scope for the lock
|
{ // scope for the lock
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("queueBuffer: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
if (buf < 0 || buf >= mBufferCount) {
|
if (buf < 0 || buf >= mBufferCount) {
|
||||||
LOGE("queueBuffer: slot index out of range [0, %d]: %d",
|
LOGE("queueBuffer: slot index out of range [0, %d]: %d",
|
||||||
mBufferCount, buf);
|
mBufferCount, buf);
|
||||||
@ -475,6 +505,12 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
|
|||||||
void SurfaceTexture::cancelBuffer(int buf) {
|
void SurfaceTexture::cancelBuffer(int buf) {
|
||||||
LOGV("SurfaceTexture::cancelBuffer");
|
LOGV("SurfaceTexture::cancelBuffer");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (buf < 0 || buf >= mBufferCount) {
|
if (buf < 0 || buf >= mBufferCount) {
|
||||||
LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
||||||
mBufferCount, buf);
|
mBufferCount, buf);
|
||||||
@ -491,6 +527,10 @@ void SurfaceTexture::cancelBuffer(int buf) {
|
|||||||
status_t SurfaceTexture::setCrop(const Rect& crop) {
|
status_t SurfaceTexture::setCrop(const Rect& crop) {
|
||||||
LOGV("SurfaceTexture::setCrop");
|
LOGV("SurfaceTexture::setCrop");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("setCrop: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
mNextCrop = crop;
|
mNextCrop = crop;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -498,6 +538,10 @@ status_t SurfaceTexture::setCrop(const Rect& crop) {
|
|||||||
status_t SurfaceTexture::setTransform(uint32_t transform) {
|
status_t SurfaceTexture::setTransform(uint32_t transform) {
|
||||||
LOGV("SurfaceTexture::setTransform");
|
LOGV("SurfaceTexture::setTransform");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("setTransform: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
mNextTransform = transform;
|
mNextTransform = transform;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -505,6 +549,12 @@ status_t SurfaceTexture::setTransform(uint32_t transform) {
|
|||||||
status_t SurfaceTexture::connect(int api) {
|
status_t SurfaceTexture::connect(int api) {
|
||||||
LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
|
LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("connect: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
int err = NO_ERROR;
|
int err = NO_ERROR;
|
||||||
switch (api) {
|
switch (api) {
|
||||||
case NATIVE_WINDOW_API_EGL:
|
case NATIVE_WINDOW_API_EGL:
|
||||||
@ -529,6 +579,12 @@ status_t SurfaceTexture::connect(int api) {
|
|||||||
status_t SurfaceTexture::disconnect(int api) {
|
status_t SurfaceTexture::disconnect(int api) {
|
||||||
LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
|
LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("connect: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
int err = NO_ERROR;
|
int err = NO_ERROR;
|
||||||
switch (api) {
|
switch (api) {
|
||||||
case NATIVE_WINDOW_API_EGL:
|
case NATIVE_WINDOW_API_EGL:
|
||||||
@ -837,6 +893,12 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {
|
|||||||
int SurfaceTexture::query(int what, int* outValue)
|
int SurfaceTexture::query(int what, int* outValue)
|
||||||
{
|
{
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("query: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
int value;
|
int value;
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case NATIVE_WINDOW_WIDTH:
|
case NATIVE_WINDOW_WIDTH:
|
||||||
@ -863,6 +925,13 @@ int SurfaceTexture::query(int what, int* outValue)
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceTexture::abandon() {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
|
freeAllBuffers();
|
||||||
|
mAbandoned = true;
|
||||||
|
mDequeueCondition.signal();
|
||||||
|
}
|
||||||
|
|
||||||
void SurfaceTexture::dump(String8& result) const
|
void SurfaceTexture::dump(String8& result) const
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
@ -148,10 +148,11 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
|
if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
|
||||||
gbuf = mSurfaceTexture->requestBuffer(buf);
|
result = mSurfaceTexture->requestBuffer(buf, &gbuf);
|
||||||
if (gbuf == 0) {
|
if (result != NO_ERROR) {
|
||||||
LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
|
LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d",
|
||||||
return NO_MEMORY;
|
result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
mQueryWidth = gbuf->width;
|
mQueryWidth = gbuf->width;
|
||||||
mQueryHeight = gbuf->height;
|
mQueryHeight = gbuf->height;
|
||||||
|
@ -1018,6 +1018,83 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
|
|||||||
EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
|
EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
|
||||||
|
class ProducerThread : public Thread {
|
||||||
|
public:
|
||||||
|
ProducerThread(const sp<ANativeWindow>& anw):
|
||||||
|
mANW(anw),
|
||||||
|
mDequeueError(NO_ERROR) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~ProducerThread() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool threadLoop() {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
|
ANativeWindowBuffer* anb;
|
||||||
|
|
||||||
|
// Frame 1
|
||||||
|
if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (anb == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mANW->queueBuffer(mANW.get(), anb)
|
||||||
|
!= NO_ERROR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame 2
|
||||||
|
if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (anb == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mANW->queueBuffer(mANW.get(), anb)
|
||||||
|
!= NO_ERROR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame 3 - error expected
|
||||||
|
mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t getDequeueError() {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
|
return mDequeueError;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
sp<ANativeWindow> mANW;
|
||||||
|
status_t mDequeueError;
|
||||||
|
Mutex mMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
sp<FrameWaiter> fw(new FrameWaiter);
|
||||||
|
mST->setFrameAvailableListener(fw);
|
||||||
|
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
||||||
|
ASSERT_EQ(OK, mST->setBufferCountServer(2));
|
||||||
|
|
||||||
|
sp<Thread> pt(new ProducerThread(mANW));
|
||||||
|
pt->run();
|
||||||
|
|
||||||
|
fw->waitForFrame();
|
||||||
|
fw->waitForFrame();
|
||||||
|
|
||||||
|
// Sleep for 100ms to allow the producer thread's dequeueBuffer call to
|
||||||
|
// block waiting for a buffer to become available.
|
||||||
|
usleep(100000);
|
||||||
|
|
||||||
|
mST->abandon();
|
||||||
|
|
||||||
|
pt->requestExitAndWait();
|
||||||
|
ASSERT_EQ(NO_INIT,
|
||||||
|
reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This test is for testing GL -> GL texture streaming via SurfaceTexture. It
|
* This test is for testing GL -> GL texture streaming via SurfaceTexture. It
|
||||||
* contains functionality to create a producer thread that will perform GL
|
* contains functionality to create a producer thread that will perform GL
|
||||||
|
Loading…
Reference in New Issue
Block a user