am 9f2a91bc: Merge "fix [2873058] Surface::dequeueBuffer blocks on last buffer, i.e. cannot dequeue all allocated buffers at once." into gingerbread
Merge commit '9f2a91bc2b01c2cc60f73a0bae673225fdddec09' into gingerbread-plus-aosp * commit '9f2a91bc2b01c2cc60f73a0bae673225fdddec09': fix [2873058] Surface::dequeueBuffer blocks on last buffer, i.e. cannot dequeue all allocated buffers at once.
This commit is contained in:
@@ -273,7 +273,6 @@ public:
|
||||
void setStatus(status_t status);
|
||||
status_t reallocateAll();
|
||||
status_t reallocateAllExcept(int buffer);
|
||||
status_t assertReallocate(int buffer);
|
||||
int32_t getQueuedCount() const;
|
||||
Region getDirtyRegion(int buffer) const;
|
||||
|
||||
@@ -356,13 +355,6 @@ private:
|
||||
inline StatusUpdate(SharedBufferBase* sbb, status_t status);
|
||||
inline ssize_t operator()();
|
||||
};
|
||||
|
||||
struct ReallocateCondition : public ConditionBase {
|
||||
int buf;
|
||||
inline ReallocateCondition(SharedBufferBase* sbb, int buf);
|
||||
inline bool operator()() const;
|
||||
inline const char* name() const { return "ReallocateCondition"; }
|
||||
};
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
@@ -243,21 +243,6 @@ bool SharedBufferClient::LockCondition::operator()() const {
|
||||
(stack.queued > 0 && stack.inUse != buf));
|
||||
}
|
||||
|
||||
SharedBufferServer::ReallocateCondition::ReallocateCondition(
|
||||
SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) {
|
||||
}
|
||||
bool SharedBufferServer::ReallocateCondition::operator()() const {
|
||||
int32_t head = stack.head;
|
||||
if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX) {
|
||||
// if stack.head is messed up, we cannot allow the server to
|
||||
// crash (since stack.head is mapped on the client side)
|
||||
stack.status = BAD_VALUE;
|
||||
return false;
|
||||
}
|
||||
// TODO: we should also check that buf has been dequeued
|
||||
return (buf != stack.index[head]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
|
||||
@@ -558,21 +543,6 @@ int32_t SharedBufferServer::getQueuedCount() const
|
||||
return stack.queued;
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::assertReallocate(int buf)
|
||||
{
|
||||
/*
|
||||
* NOTE: it's safe to hold mLock for read while waiting for
|
||||
* the ReallocateCondition because that condition is not updated
|
||||
* by the thread that holds mLock for write.
|
||||
*/
|
||||
RWLock::AutoRLock _l(mLock);
|
||||
|
||||
// TODO: need to validate "buf"
|
||||
ReallocateCondition condition(this, buf);
|
||||
status_t err = waitForCondition(condition);
|
||||
return err;
|
||||
}
|
||||
|
||||
Region SharedBufferServer::getDirtyRegion(int buf) const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
|
||||
@@ -294,19 +294,9 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
|
||||
* This is called from the client's Surface::dequeue(). This can happen
|
||||
* at any time, especially while we're in the middle of using the
|
||||
* buffer 'index' as our front buffer.
|
||||
*
|
||||
* Make sure the buffer we're resizing is not the front buffer and has been
|
||||
* dequeued. Once this condition is asserted, we are guaranteed that this
|
||||
* buffer cannot become the front buffer under our feet, since we're called
|
||||
* from Surface::dequeue()
|
||||
*/
|
||||
status_t err = lcblk->assertReallocate(index);
|
||||
LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
|
||||
if (err != NO_ERROR) {
|
||||
// the surface may have died
|
||||
return buffer;
|
||||
}
|
||||
|
||||
status_t err = NO_ERROR;
|
||||
uint32_t w, h, f;
|
||||
{ // scope for the lock
|
||||
Mutex::Autolock _l(mLock);
|
||||
@@ -319,23 +309,17 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
|
||||
w = reqWidth ? reqWidth : mWidth;
|
||||
h = reqHeight ? reqHeight : mHeight;
|
||||
f = reqFormat ? reqFormat : mFormat;
|
||||
buffer = mBufferManager.detachBuffer(index);
|
||||
if (fixedSizeChanged || formatChanged) {
|
||||
lcblk->reallocateAllExcept(index);
|
||||
}
|
||||
}
|
||||
|
||||
// here we have to reallocate a new buffer because the buffer could be
|
||||
// used as the front buffer, or by a client in our process
|
||||
// (eg: status bar), and we can't release the handle under its feet.
|
||||
const uint32_t effectiveUsage = getEffectiveUsage(usage);
|
||||
if (buffer!=0 && buffer->getStrongCount() == 1) {
|
||||
err = buffer->reallocate(w, h, f, effectiveUsage);
|
||||
} else {
|
||||
// here we have to reallocate a new buffer because we could have a
|
||||
// client in our process with a reference to it (eg: status bar),
|
||||
// and we can't release the handle under its feet.
|
||||
buffer.clear();
|
||||
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
|
||||
err = buffer->initCheck();
|
||||
}
|
||||
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
|
||||
err = buffer->initCheck();
|
||||
|
||||
if (err || buffer->handle == 0) {
|
||||
LOGE_IF(err || buffer->handle == 0,
|
||||
|
||||
18
services/surfaceflinger/tests/surface/Android.mk
Normal file
18
services/surfaceflinger/tests/surface/Android.mk
Normal file
@@ -0,0 +1,18 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
surface.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libutils \
|
||||
libbinder \
|
||||
libui \
|
||||
libsurfaceflinger_client
|
||||
|
||||
LOCAL_MODULE:= test-surface
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
54
services/surfaceflinger/tests/surface/surface.cpp
Normal file
54
services/surfaceflinger/tests/surface/surface.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <cutils/memory.h>
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/ProcessState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
|
||||
#include <surfaceflinger/Surface.h>
|
||||
#include <surfaceflinger/ISurface.h>
|
||||
#include <surfaceflinger/SurfaceComposerClient.h>
|
||||
|
||||
#include <ui/Overlay.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// set up the thread-pool
|
||||
sp<ProcessState> proc(ProcessState::self());
|
||||
ProcessState::self()->startThreadPool();
|
||||
|
||||
// create a client to surfaceflinger
|
||||
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
|
||||
|
||||
// create pushbuffer surface
|
||||
sp<SurfaceControl> surfaceControl = client->createSurface(
|
||||
getpid(), 0, 160, 240, PIXEL_FORMAT_RGB_565);
|
||||
client->openTransaction();
|
||||
surfaceControl->setLayer(100000);
|
||||
client->closeTransaction();
|
||||
|
||||
// pretend it went cross-process
|
||||
Parcel parcel;
|
||||
SurfaceControl::writeSurfaceToParcel(surfaceControl, &parcel);
|
||||
parcel.setDataPosition(0);
|
||||
sp<Surface> surface = Surface::readFromParcel(parcel);
|
||||
ANativeWindow* window = surface.get();
|
||||
|
||||
printf("window=%p\n", window);
|
||||
|
||||
int err = native_window_set_buffer_count(window, 8);
|
||||
android_native_buffer_t* buffer;
|
||||
|
||||
for (int i=0 ; i<8 ; i++) {
|
||||
window->dequeueBuffer(window, &buffer);
|
||||
printf("buffer %d: %p\n", i, buffer);
|
||||
}
|
||||
|
||||
printf("test complete. CTRL+C to finish.\n");
|
||||
|
||||
IPCThreadState::self()->joinThreadPool();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user