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:
@@ -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
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|||||||
Reference in New Issue
Block a user