Merge change 21401 into eclair

* changes:
  make sure to update a surface's usage bits when it changes, instead of only the first time.
This commit is contained in:
Android (Google) Code Review
2009-08-14 20:07:51 -07:00
2 changed files with 89 additions and 42 deletions

View File

@@ -146,16 +146,16 @@ public:
static bool isValid(const sp<Surface>& surface) { static bool isValid(const sp<Surface>& surface) {
return (surface != 0) && surface->isValid(); return (surface != 0) && surface->isValid();
} }
bool isValid() {
return mToken>=0 && mClient!=0;
}
static bool isSameSurface( static bool isSameSurface(
const sp<Surface>& lhs, const sp<Surface>& rhs); const sp<Surface>& lhs, const sp<Surface>& rhs);
SurfaceID ID() const { return mToken; }
uint32_t getFlags() const { return mFlags; } bool isValid();
SurfaceID ID() const { return mToken; }
uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; } uint32_t getIdentity() const { return mIdentity; }
// the lock/unlock APIs must be used from the same thread
status_t lock(SurfaceInfo* info, bool blocking = true); status_t lock(SurfaceInfo* info, bool blocking = true);
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
status_t unlockAndPost(); status_t unlockAndPost();
@@ -175,14 +175,18 @@ private:
friend class SurfaceComposerClient; friend class SurfaceComposerClient;
friend class SurfaceControl; friend class SurfaceControl;
// camera and camcorder need access to the ISurface binder interface for preview // camera and camcorder need access to the ISurface binder interface for preview
friend class Camera; friend class Camera;
friend class MediaRecorder; friend class MediaRecorder;
// mediaplayer needs access to ISurface for display // mediaplayer needs access to ISurface for display
friend class MediaPlayer; friend class MediaPlayer;
friend class Test;
friend class IOMX; friend class IOMX;
const sp<ISurface>& getISurface() const { return mSurface; } // this is just to be able to write some unit tests
friend class Test;
sp<SurfaceComposerClient> getClient() const;
sp<ISurface> getISurface() const;
status_t getBufferLocked(int index, int usage); status_t getBufferLocked(int index, int usage);
@@ -210,24 +214,38 @@ private:
status_t queueBuffer(const sp<SurfaceBuffer>& buffer); status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
alloc_device_t* mAllocDevice; void setUsage(uint32_t reqUsage);
// constants
sp<SurfaceComposerClient> mClient; sp<SurfaceComposerClient> mClient;
sp<ISurface> mSurface; sp<ISurface> mSurface;
sp<SurfaceBuffer> mBuffers[2];
sp<SurfaceBuffer> mLockedBuffer;
SurfaceID mToken; SurfaceID mToken;
uint32_t mIdentity; uint32_t mIdentity;
uint32_t mWidth;
uint32_t mHeight;
uint32_t mUsage;
PixelFormat mFormat; PixelFormat mFormat;
uint32_t mFlags; uint32_t mFlags;
mutable Region mDirtyRegion;
mutable Region mOldDirtyRegion;
mutable uint8_t mBackbufferIndex;
mutable Mutex mSurfaceLock;
Rect mSwapRectangle;
BufferMapper& mBufferMapper; BufferMapper& mBufferMapper;
// protected by mSurfaceLock
Rect mSwapRectangle;
uint32_t mUsage;
bool mUsageChanged;
// protected by mSurfaceLock. These are also used from lock/unlock
// but in that case, they must be called form the same thread.
sp<SurfaceBuffer> mBuffers[2];
mutable Region mDirtyRegion;
mutable uint8_t mBackbufferIndex;
// must be used from the lock/unlock thread
sp<SurfaceBuffer> mLockedBuffer;
mutable Region mOldDirtyRegion;
// query() must be called from dequeueBuffer() thread
uint32_t mWidth;
uint32_t mHeight;
// Inherently thread-safe
mutable Mutex mSurfaceLock;
}; };
}; // namespace android }; // namespace android

View File

@@ -382,9 +382,9 @@ sp<Surface> SurfaceControl::getSurface() const
Surface::Surface(const sp<SurfaceControl>& surface) Surface::Surface(const sp<SurfaceControl>& surface)
: mClient(surface->mClient), mSurface(surface->mSurface), : mClient(surface->mClient), mSurface(surface->mSurface),
mToken(surface->mToken), mIdentity(surface->mIdentity), mToken(surface->mToken), mIdentity(surface->mIdentity),
mWidth(surface->mWidth), mHeight(surface->mHeight),
mFormat(surface->mFormat), mFlags(surface->mFlags), mFormat(surface->mFormat), mFlags(surface->mFlags),
mBufferMapper(BufferMapper::get()) mBufferMapper(BufferMapper::get()),
mWidth(surface->mWidth), mHeight(surface->mHeight)
{ {
init(); init();
} }
@@ -426,9 +426,9 @@ void Surface::init()
const_cast<uint32_t&>(android_native_window_t::flags) = 0; const_cast<uint32_t&>(android_native_window_t::flags) = 0;
// be default we request a hardware surface // be default we request a hardware surface
mUsage = GRALLOC_USAGE_HW_RENDER; mUsage = GRALLOC_USAGE_HW_RENDER;
mUsageChanged = true;
} }
Surface::~Surface() Surface::~Surface()
{ {
// this is a client-side operation, the surface is destroyed, unmap // this is a client-side operation, the surface is destroyed, unmap
@@ -446,11 +446,24 @@ Surface::~Surface()
IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands();
} }
sp<SurfaceComposerClient> Surface::getClient() const {
return mClient;
}
sp<ISurface> Surface::getISurface() const {
return mSurface;
}
bool Surface::isValid() {
return mToken>=0 && mClient!=0;
}
status_t Surface::validate(per_client_cblk_t const* cblk) const status_t Surface::validate(per_client_cblk_t const* cblk) const
{ {
sp<SurfaceComposerClient> client(getClient());
if (mToken<0 || mClient==0) { if (mToken<0 || mClient==0) {
LOGE("invalid token (%d, identity=%u) or client (%p)", LOGE("invalid token (%d, identity=%u) or client (%p)",
mToken, mIdentity, mClient.get()); mToken, mIdentity, client.get());
return NO_INIT; return NO_INIT;
} }
if (cblk == 0) { if (cblk == 0) {
@@ -477,6 +490,7 @@ bool Surface::isSameSurface(
{ {
if (lhs == 0 || rhs == 0) if (lhs == 0 || rhs == 0)
return false; return false;
return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
} }
@@ -532,10 +546,9 @@ status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
{ {
android_native_buffer_t* out; android_native_buffer_t* out;
status_t err = dequeueBuffer(&out); status_t err = dequeueBuffer(&out);
*buffer = SurfaceBuffer::getSelf(out); if (err == NO_ERROR) {
// reset the width/height with the what we get from the buffer *buffer = SurfaceBuffer::getSelf(out);
mWidth = uint32_t(out->width); }
mHeight = uint32_t(out->height);
return err; return err;
} }
@@ -557,7 +570,8 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
Mutex::Autolock _l(mSurfaceLock); Mutex::Autolock _l(mSurfaceLock);
per_client_cblk_t* const cblk = mClient->mControl; sp<SurfaceComposerClient> client(getClient());
per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk); status_t err = validate(cblk);
if (err != NO_ERROR) if (err != NO_ERROR)
return err; return err;
@@ -572,14 +586,17 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
mBackbufferIndex = backIdx; mBackbufferIndex = backIdx;
layer_cblk_t* const lcblk = &(cblk->layers[index]); layer_cblk_t* const lcblk = &(cblk->layers[index]);
volatile const surface_info_t* const back = lcblk->surface + backIdx; volatile const surface_info_t* const back = lcblk->surface + backIdx;
if (back->flags & surface_info_t::eNeedNewBuffer) { if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
mUsageChanged = false;
err = getBufferLocked(backIdx, mUsage); err = getBufferLocked(backIdx, mUsage);
} }
if (err == NO_ERROR) { if (err == NO_ERROR) {
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]); const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
// reset the width/height with the what we get from the buffer
mWidth = uint32_t(backBuffer->width);
mHeight = uint32_t(backBuffer->height);
mDirtyRegion.set(backBuffer->width, backBuffer->height); mDirtyRegion.set(backBuffer->width, backBuffer->height);
*buffer = backBuffer.get(); *buffer = backBuffer.get();
} }
@@ -591,7 +608,8 @@ int Surface::lockBuffer(android_native_buffer_t* buffer)
{ {
Mutex::Autolock _l(mSurfaceLock); Mutex::Autolock _l(mSurfaceLock);
per_client_cblk_t* const cblk = mClient->mControl; sp<SurfaceComposerClient> client(getClient());
per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk); status_t err = validate(cblk);
if (err != NO_ERROR) if (err != NO_ERROR)
return err; return err;
@@ -604,7 +622,8 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
{ {
Mutex::Autolock _l(mSurfaceLock); Mutex::Autolock _l(mSurfaceLock);
per_client_cblk_t* const cblk = mClient->mControl; sp<SurfaceComposerClient> client(getClient());
per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk); status_t err = validate(cblk);
if (err != NO_ERROR) if (err != NO_ERROR)
return err; return err;
@@ -620,7 +639,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
if (!(newstate & eNextFlipPending)) if (!(newstate & eNextFlipPending))
mClient->signalServer(); client->signalServer();
return NO_ERROR; return NO_ERROR;
} }
@@ -646,7 +665,7 @@ int Surface::perform(int operation, va_list args)
int res = NO_ERROR; int res = NO_ERROR;
switch (operation) { switch (operation) {
case NATIVE_WINDOW_SET_USAGE: case NATIVE_WINDOW_SET_USAGE:
mUsage = va_arg(args, int); setUsage( va_arg(args, int) );
break; break;
default: default:
res = NAME_NOT_FOUND; res = NAME_NOT_FOUND;
@@ -655,6 +674,15 @@ int Surface::perform(int operation, va_list args)
return res; return res;
} }
void Surface::setUsage(uint32_t reqUsage)
{
Mutex::Autolock _l(mSurfaceLock);
if (mUsage != reqUsage) {
mUsageChanged = true;
mUsage = reqUsage;
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
status_t Surface::lock(SurfaceInfo* info, bool blocking) { status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -663,11 +691,9 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) {
status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
{ {
// FIXME: needs some locking here
// we're intending to do software rendering from this point // we're intending to do software rendering from this point
mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
sp<SurfaceBuffer> backBuffer; sp<SurfaceBuffer> backBuffer;
status_t err = dequeueBuffer(&backBuffer); status_t err = dequeueBuffer(&backBuffer);
if (err == NO_ERROR) { if (err == NO_ERROR) {
@@ -679,7 +705,8 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
Region scratch(bounds); Region scratch(bounds);
Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
per_client_cblk_t* const cblk = mClient->mControl; sp<SurfaceComposerClient> client(getClient());
per_client_cblk_t* const cblk = client->mControl;
layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]); layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex; volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
if (back->flags & surface_info_t::eBufferDirty) { if (back->flags & surface_info_t::eBufferDirty) {
@@ -725,8 +752,6 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
status_t Surface::unlockAndPost() status_t Surface::unlockAndPost()
{ {
// FIXME: needs some locking here
if (mLockedBuffer == 0) if (mLockedBuffer == 0)
return BAD_VALUE; return BAD_VALUE;
@@ -753,13 +778,17 @@ void Surface::_send_dirty_region(
} }
void Surface::setSwapRectangle(const Rect& r) { void Surface::setSwapRectangle(const Rect& r) {
Mutex::Autolock _l(mSurfaceLock);
mSwapRectangle = r; mSwapRectangle = r;
} }
status_t Surface::getBufferLocked(int index, int usage) status_t Surface::getBufferLocked(int index, int usage)
{ {
sp<ISurface> s(mSurface);
if (s == 0) return NO_INIT;
status_t err = NO_MEMORY; status_t err = NO_MEMORY;
sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage); sp<SurfaceBuffer> buffer = s->getBuffer(usage);
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL"); LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
if (buffer != 0) { if (buffer != 0) {
sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);