added the notion of fixed-size buffers
the new native_window_set_buffers_geometry allows to specify a size and format for all buffers to be dequeued. the buffer will be scalled to the window's size. Change-Id: I2c378b85c88d29cdd827a5f319d5c704d79ba381
This commit is contained in:
parent
a0b3f1d2eb
commit
a138f89c5e
@ -279,7 +279,8 @@ public:
|
||||
ssize_t retireAndLock();
|
||||
status_t unlock(int buffer);
|
||||
void setStatus(status_t status);
|
||||
status_t reallocate();
|
||||
status_t reallocateAll();
|
||||
status_t reallocateAllExcept(int buffer);
|
||||
status_t assertReallocate(int buffer);
|
||||
int32_t getQueuedCount() const;
|
||||
Region getDirtyRegion(int buffer) const;
|
||||
|
@ -53,7 +53,8 @@ protected:
|
||||
public:
|
||||
DECLARE_META_INTERFACE(Surface);
|
||||
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) = 0;
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
|
||||
virtual status_t setBufferCount(int bufferCount) = 0;
|
||||
|
||||
class BufferHeap {
|
||||
|
@ -36,6 +36,7 @@ namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class GraphicBuffer;
|
||||
class GraphicBufferMapper;
|
||||
class IOMX;
|
||||
class Rect;
|
||||
@ -213,12 +214,14 @@ private:
|
||||
int dispatch_disconnect(va_list args);
|
||||
int dispatch_crop(va_list args);
|
||||
int dispatch_set_buffer_count(va_list args);
|
||||
int dispatch_set_buffers_geometry(va_list args);
|
||||
|
||||
void setUsage(uint32_t reqUsage);
|
||||
int connect(int api);
|
||||
int disconnect(int api);
|
||||
int crop(Rect const* rect);
|
||||
int setBufferCount(int bufferCount);
|
||||
int setBuffersGeometry(int w, int h, int format);
|
||||
|
||||
/*
|
||||
* private stuff...
|
||||
@ -231,12 +234,34 @@ private:
|
||||
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
|
||||
inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
|
||||
|
||||
status_t getBufferLocked(int index, int usage);
|
||||
status_t getBufferLocked(int index,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||
int getBufferIndex(const sp<GraphicBuffer>& buffer) const;
|
||||
|
||||
uint32_t getUsage() const;
|
||||
int getConnectedApi() const;
|
||||
int getConnectedApi() const;
|
||||
|
||||
bool needNewBuffer(int bufIdx,
|
||||
uint32_t *pWidth, uint32_t *pHeight,
|
||||
uint32_t *pFormat, uint32_t *pUsage) const;
|
||||
|
||||
class BufferInfo {
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mFormat;
|
||||
uint32_t mUsage;
|
||||
mutable uint32_t mDirty;
|
||||
enum {
|
||||
GEOMETRY = 0x01
|
||||
};
|
||||
public:
|
||||
BufferInfo();
|
||||
void set(uint32_t w, uint32_t h, uint32_t format);
|
||||
void set(uint32_t usage);
|
||||
void get(uint32_t *pWidth, uint32_t *pHeight,
|
||||
uint32_t *pFormat, uint32_t *pUsage) const;
|
||||
bool validateBuffer(const sp<GraphicBuffer>& buffer) const;
|
||||
};
|
||||
|
||||
// constants
|
||||
sp<SurfaceComposerClient> mClient;
|
||||
sp<ISurface> mSurface;
|
||||
@ -249,13 +274,12 @@ private:
|
||||
|
||||
// protected by mSurfaceLock
|
||||
Rect mSwapRectangle;
|
||||
uint32_t mUsage;
|
||||
int mConnected;
|
||||
Rect mNextBufferCrop;
|
||||
BufferInfo mBufferInfo;
|
||||
|
||||
// protected by mSurfaceLock. These are also used from lock/unlock
|
||||
// but in that case, they must be called form the same thread.
|
||||
sp<GraphicBuffer> mBuffers[2];
|
||||
mutable Region mDirtyRegion;
|
||||
|
||||
// must be used from the lock/unlock thread
|
||||
@ -264,6 +288,9 @@ private:
|
||||
mutable Region mOldDirtyRegion;
|
||||
bool mReserved;
|
||||
|
||||
// only used from dequeueBuffer()
|
||||
Vector< sp<GraphicBuffer> > mBuffers;
|
||||
|
||||
// query() must be called from dequeueBuffer() thread
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
|
@ -82,6 +82,7 @@ enum {
|
||||
NATIVE_WINDOW_DISCONNECT,
|
||||
NATIVE_WINDOW_SET_CROP,
|
||||
NATIVE_WINDOW_SET_BUFFER_COUNT,
|
||||
NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
|
||||
};
|
||||
|
||||
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
|
||||
@ -192,6 +193,7 @@ typedef struct android_native_window_t
|
||||
* NATIVE_WINDOW_DISCONNECT
|
||||
* NATIVE_WINDOW_SET_CROP
|
||||
* NATIVE_WINDOW_SET_BUFFER_COUNT
|
||||
* NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
|
||||
*
|
||||
*/
|
||||
|
||||
@ -273,6 +275,25 @@ static inline int native_window_set_buffer_count(
|
||||
return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* native_window_set_buffers_geometry(..., int w, int h, int format)
|
||||
* All buffers dequeued after this call will have the geometry specified.
|
||||
* In particular, all buffers will have a fixed-size, independent form the
|
||||
* native-window size. They will be appropriately scaled to the window-size
|
||||
* upon composition.
|
||||
*
|
||||
* If all parameters are 0, the normal behavior is restored. That is,
|
||||
* dequeued buffers following this call will be sized to the window's size.
|
||||
*
|
||||
*/
|
||||
static inline int native_window_set_buffers_geometry(
|
||||
android_native_window_t* window,
|
||||
int w, int h, int format)
|
||||
{
|
||||
return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
|
||||
w, h, format);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* FIXME: this is legacy for pixmaps */
|
||||
|
@ -55,7 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
|
||||
mNeedsBlending(true),
|
||||
mNeedsDithering(false),
|
||||
mTextureManager(mFlags),
|
||||
mBufferManager(mTextureManager)
|
||||
mBufferManager(mTextureManager),
|
||||
mWidth(0), mHeight(0), mFixedSize(false)
|
||||
{
|
||||
// no OpenGL operation is possible here, since we might not be
|
||||
// in the OpenGL thread.
|
||||
@ -227,10 +228,18 @@ status_t Layer::setBufferCount(int bufferCount)
|
||||
return err;
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
|
||||
sp<GraphicBuffer> Layer::requestBuffer(int index,
|
||||
uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
|
||||
uint32_t usage)
|
||||
{
|
||||
sp<GraphicBuffer> buffer;
|
||||
|
||||
if ((reqWidth | reqHeight | reqFormat) < 0)
|
||||
return buffer;
|
||||
|
||||
if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
|
||||
return buffer;
|
||||
|
||||
// this ensures our client doesn't go away while we're accessing
|
||||
// the shared area.
|
||||
sp<Client> ourClient(client.promote());
|
||||
@ -256,23 +265,33 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint32_t w, h;
|
||||
uint32_t w, h, f;
|
||||
{ // scope for the lock
|
||||
Mutex::Autolock _l(mLock);
|
||||
w = mWidth;
|
||||
h = mHeight;
|
||||
const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
|
||||
const bool formatChanged = mReqFormat != reqFormat;
|
||||
mReqWidth = reqWidth;
|
||||
mReqHeight = reqHeight;
|
||||
mReqFormat = reqFormat;
|
||||
mFixedSize = reqWidth && reqHeight;
|
||||
w = reqWidth ? reqWidth : mWidth;
|
||||
h = reqHeight ? reqHeight : mHeight;
|
||||
f = reqFormat ? reqFormat : mFormat;
|
||||
buffer = mBufferManager.detachBuffer(index);
|
||||
if (fixedSizeChanged || formatChanged) {
|
||||
lcblk->reallocateAllExcept(index);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t effectiveUsage = getEffectiveUsage(usage);
|
||||
if (buffer!=0 && buffer->getStrongCount() == 1) {
|
||||
err = buffer->reallocate(w, h, mFormat, effectiveUsage);
|
||||
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, mFormat, effectiveUsage);
|
||||
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
|
||||
err = buffer->initCheck();
|
||||
}
|
||||
|
||||
@ -288,12 +307,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
|
||||
|
||||
if (err == NO_ERROR && buffer->handle != 0) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
if (mWidth && mHeight) {
|
||||
mBufferManager.attachBuffer(index, buffer);
|
||||
} else {
|
||||
// oops we got killed while we were allocating the buffer
|
||||
buffer.clear();
|
||||
}
|
||||
mBufferManager.attachBuffer(index, buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
@ -330,39 +344,46 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
const Layer::State& front(drawingState());
|
||||
const Layer::State& temp(currentState());
|
||||
|
||||
if ((front.requested_w != temp.requested_w) ||
|
||||
(front.requested_h != temp.requested_h)) {
|
||||
const bool sizeChanged = (front.requested_w != temp.requested_w) ||
|
||||
(front.requested_h != temp.requested_h);
|
||||
|
||||
if (sizeChanged) {
|
||||
// the size changed, we need to ask our client to request a new buffer
|
||||
LOGD_IF(DEBUG_RESIZE,
|
||||
"resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
|
||||
this,
|
||||
int(temp.requested_w), int(temp.requested_h),
|
||||
int(front.requested_w), int(front.requested_h));
|
||||
"resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
|
||||
this,
|
||||
int(temp.requested_w), int(temp.requested_h),
|
||||
int(front.requested_w), int(front.requested_h));
|
||||
|
||||
// we're being resized and there is a freeze display request,
|
||||
// acquire a freeze lock, so that the screen stays put
|
||||
// until we've redrawn at the new size; this is to avoid
|
||||
// glitches upon orientation changes.
|
||||
if (mFlinger->hasFreezeRequest()) {
|
||||
// if the surface is hidden, don't try to acquire the
|
||||
// freeze lock, since hidden surfaces may never redraw
|
||||
if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
|
||||
mFreezeLock = mFlinger->getFreezeLock();
|
||||
if (!isFixedSize()) {
|
||||
// we're being resized and there is a freeze display request,
|
||||
// acquire a freeze lock, so that the screen stays put
|
||||
// until we've redrawn at the new size; this is to avoid
|
||||
// glitches upon orientation changes.
|
||||
if (mFlinger->hasFreezeRequest()) {
|
||||
// if the surface is hidden, don't try to acquire the
|
||||
// freeze lock, since hidden surfaces may never redraw
|
||||
if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
|
||||
mFreezeLock = mFlinger->getFreezeLock();
|
||||
}
|
||||
}
|
||||
|
||||
// this will make sure LayerBase::doTransaction doesn't update
|
||||
// the drawing state's size
|
||||
Layer::State& editDraw(mDrawingState);
|
||||
editDraw.requested_w = temp.requested_w;
|
||||
editDraw.requested_h = temp.requested_h;
|
||||
|
||||
// record the new size, form this point on, when the client request
|
||||
// a buffer, it'll get the new size.
|
||||
setBufferSize(temp.requested_w, temp.requested_h);
|
||||
|
||||
// all buffers need reallocation
|
||||
lcblk->reallocateAll();
|
||||
} else {
|
||||
// record the new size
|
||||
setBufferSize(temp.requested_w, temp.requested_h);
|
||||
}
|
||||
|
||||
// this will make sure LayerBase::doTransaction doesn't update
|
||||
// the drawing state's size
|
||||
Layer::State& editDraw(mDrawingState);
|
||||
editDraw.requested_w = temp.requested_w;
|
||||
editDraw.requested_h = temp.requested_h;
|
||||
|
||||
// record the new size, form this point on, when the client request a
|
||||
// buffer, it'll get the new size.
|
||||
setDrawingSize(temp.requested_w, temp.requested_h);
|
||||
|
||||
// all buffers need reallocation
|
||||
lcblk->reallocate();
|
||||
}
|
||||
|
||||
if (temp.sequence != front.sequence) {
|
||||
@ -376,12 +397,17 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
return LayerBase::doTransaction(flags);
|
||||
}
|
||||
|
||||
void Layer::setDrawingSize(uint32_t w, uint32_t h) {
|
||||
void Layer::setBufferSize(uint32_t w, uint32_t h) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
}
|
||||
|
||||
bool Layer::isFixedSize() const {
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mFixedSize;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// pageflip handling...
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -677,7 +703,8 @@ Layer::SurfaceLayer::~SurfaceLayer()
|
||||
{
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
|
||||
sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
||||
{
|
||||
sp<GraphicBuffer> buffer;
|
||||
sp<Layer> owner(getOwner());
|
||||
@ -687,7 +714,7 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
|
||||
* as it could cause a dead-lock, since it may have to wait
|
||||
* on conditions updated my the main thread.
|
||||
*/
|
||||
buffer = owner->requestBuffer(index, usage);
|
||||
buffer = owner->requestBuffer(index, w, h, format, usage);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
@ -57,7 +57,8 @@ public:
|
||||
status_t setBuffers(uint32_t w, uint32_t h,
|
||||
PixelFormat format, uint32_t flags=0);
|
||||
|
||||
void setDrawingSize(uint32_t w, uint32_t h);
|
||||
void setBufferSize(uint32_t w, uint32_t h);
|
||||
bool isFixedSize() const;
|
||||
|
||||
virtual void onDraw(const Region& clip) const;
|
||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||
@ -88,7 +89,8 @@ private:
|
||||
|
||||
uint32_t getEffectiveUsage(uint32_t usage) const;
|
||||
|
||||
sp<GraphicBuffer> requestBuffer(int index, int usage);
|
||||
sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||
status_t setBufferCount(int bufferCount);
|
||||
|
||||
class SurfaceLayer : public LayerBaseClient::Surface {
|
||||
@ -97,7 +99,8 @@ private:
|
||||
SurfaceID id, const sp<Layer>& owner);
|
||||
~SurfaceLayer();
|
||||
private:
|
||||
virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||
virtual status_t setBufferCount(int bufferCount);
|
||||
sp<Layer> getOwner() const {
|
||||
return static_cast<Layer*>(Surface::getOwner().get());
|
||||
@ -181,6 +184,10 @@ private:
|
||||
mutable Mutex mLock;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mReqWidth;
|
||||
uint32_t mReqHeight;
|
||||
uint32_t mReqFormat;
|
||||
bool mFixedSize;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -616,7 +616,8 @@ status_t LayerBaseClient::Surface::onTransact(
|
||||
return BnSurface::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
|
||||
sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -301,7 +301,8 @@ public:
|
||||
sp<LayerBaseClient> getOwner() const;
|
||||
|
||||
private:
|
||||
virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||
virtual status_t setBufferCount(int bufferCount);
|
||||
|
||||
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
|
||||
|
@ -71,11 +71,15 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage)
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
|
||||
data.writeInt32(bufferIdx);
|
||||
data.writeInt32(w);
|
||||
data.writeInt32(h);
|
||||
data.writeInt32(format);
|
||||
data.writeInt32(usage);
|
||||
remote()->transact(REQUEST_BUFFER, data, &reply);
|
||||
sp<GraphicBuffer> buffer = new GraphicBuffer();
|
||||
@ -150,8 +154,11 @@ status_t BnSurface::onTransact(
|
||||
case REQUEST_BUFFER: {
|
||||
CHECK_INTERFACE(ISurface, data, reply);
|
||||
int bufferIdx = data.readInt32();
|
||||
int usage = data.readInt32();
|
||||
sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage));
|
||||
uint32_t w = data.readInt32();
|
||||
uint32_t h = data.readInt32();
|
||||
uint32_t format = data.readInt32();
|
||||
uint32_t usage = data.readInt32();
|
||||
sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format, usage));
|
||||
if (buffer == NULL)
|
||||
return BAD_VALUE;
|
||||
return reply->write(*buffer);
|
||||
|
@ -527,13 +527,25 @@ void SharedBufferServer::setStatus(status_t status)
|
||||
}
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::reallocate()
|
||||
status_t SharedBufferServer::reallocateAll()
|
||||
{
|
||||
RWLock::AutoRLock _l(mLock);
|
||||
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
uint32_t mask = mBufferList.getMask();
|
||||
android_atomic_or(mask, &stack.reallocMask);
|
||||
android_atomic_or(mask, &stack.reallocMask);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::reallocateAllExcept(int buffer)
|
||||
{
|
||||
RWLock::AutoRLock _l(mLock);
|
||||
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
BufferList temp(mBufferList);
|
||||
temp.remove(buffer);
|
||||
uint32_t mask = temp.getMask();
|
||||
android_atomic_or(mask, &stack.reallocMask);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -349,15 +349,18 @@ void Surface::init()
|
||||
const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
|
||||
const_cast<uint32_t&>(android_native_window_t::flags) = 0;
|
||||
// be default we request a hardware surface
|
||||
mUsage = GRALLOC_USAGE_HW_RENDER;
|
||||
mConnected = 0;
|
||||
// two buffers by default
|
||||
mBuffers.setCapacity(2);
|
||||
mBuffers.insertAt(0, 2);
|
||||
}
|
||||
|
||||
Surface::~Surface()
|
||||
{
|
||||
// this is a client-side operation, the surface is destroyed, unmap
|
||||
// its buffers in this process.
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
size_t size = mBuffers.size();
|
||||
for (size_t i=0 ; i<size ; i++) {
|
||||
if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
|
||||
getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
|
||||
}
|
||||
@ -365,6 +368,7 @@ Surface::~Surface()
|
||||
|
||||
// clear all references and trigger an IPC now, to make sure things
|
||||
// happen without delay, since these resources are quite heavy.
|
||||
mBuffers.clear();
|
||||
mClient.clear();
|
||||
mSurface.clear();
|
||||
delete mSharedBufferClient;
|
||||
@ -463,6 +467,22 @@ int Surface::perform(android_native_window_t* window,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool Surface::needNewBuffer(int bufIdx,
|
||||
uint32_t *pWidth, uint32_t *pHeight,
|
||||
uint32_t *pFormat, uint32_t *pUsage) const
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
|
||||
// Always call needNewBuffer(), since it clears the needed buffers flags
|
||||
bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
|
||||
bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]);
|
||||
bool newNeewBuffer = needNewBuffer || !validBuffer;
|
||||
if (newNeewBuffer) {
|
||||
mBufferInfo.get(pWidth, pHeight, pFormat, pUsage);
|
||||
}
|
||||
return newNeewBuffer;
|
||||
}
|
||||
|
||||
int Surface::dequeueBuffer(android_native_buffer_t** buffer)
|
||||
{
|
||||
sp<SurfaceComposerClient> client(getClient());
|
||||
@ -476,27 +496,28 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
|
||||
return bufIdx;
|
||||
}
|
||||
|
||||
// below we make sure we AT LEAST have the usage flags we want
|
||||
const uint32_t usage(getUsage());
|
||||
const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
|
||||
// grow the buffer array if needed
|
||||
const size_t size = mBuffers.size();
|
||||
const size_t needed = bufIdx+1;
|
||||
if (size < needed) {
|
||||
mBuffers.insertAt(size, needed-size);
|
||||
}
|
||||
|
||||
// Always call needNewBuffer(), since it clears the needed buffers flags
|
||||
bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
|
||||
if (backBuffer == 0 ||
|
||||
((uint32_t(backBuffer->usage) & usage) != usage) ||
|
||||
needNewBuffer)
|
||||
{
|
||||
err = getBufferLocked(bufIdx, usage);
|
||||
LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
|
||||
bufIdx, usage, strerror(-err));
|
||||
uint32_t w, h, format, usage;
|
||||
if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) {
|
||||
err = getBufferLocked(bufIdx, w, h, format, usage);
|
||||
LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)",
|
||||
bufIdx, w, h, format, usage, strerror(-err));
|
||||
if (err == NO_ERROR) {
|
||||
// reset the width/height with the what we get from the buffer
|
||||
const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
|
||||
mWidth = uint32_t(backBuffer->width);
|
||||
mHeight = uint32_t(backBuffer->height);
|
||||
}
|
||||
}
|
||||
|
||||
// if we still don't have a buffer here, we probably ran out of memory
|
||||
const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
|
||||
if (!err && backBuffer==0) {
|
||||
err = NO_MEMORY;
|
||||
}
|
||||
@ -614,12 +635,17 @@ int Surface::dispatch_set_buffer_count(va_list args) {
|
||||
size_t bufferCount = va_arg(args, size_t);
|
||||
return setBufferCount(bufferCount);
|
||||
}
|
||||
|
||||
int Surface::dispatch_set_buffers_geometry(va_list args) {
|
||||
int w = va_arg(args, int);
|
||||
int h = va_arg(args, int);
|
||||
int f = va_arg(args, int);
|
||||
return setBuffersGeometry(w, h, f);
|
||||
}
|
||||
|
||||
void Surface::setUsage(uint32_t reqUsage)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
mUsage = reqUsage;
|
||||
mBufferInfo.set(reqUsage);
|
||||
}
|
||||
|
||||
int Surface::connect(int api)
|
||||
@ -660,18 +686,6 @@ int Surface::disconnect(int api)
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t Surface::getUsage() const
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
return mUsage;
|
||||
}
|
||||
|
||||
int Surface::getConnectedApi() const
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
int Surface::crop(Rect const* rect)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
@ -700,6 +714,26 @@ int Surface::setBufferCount(int bufferCount)
|
||||
return err;
|
||||
}
|
||||
|
||||
int Surface::setBuffersGeometry(int w, int h, int format)
|
||||
{
|
||||
if (w<0 || h<0 || format<0)
|
||||
return BAD_VALUE;
|
||||
|
||||
if ((w && !h) || (!w && h))
|
||||
return BAD_VALUE;
|
||||
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
mBufferInfo.set(w, h, format);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::getConnectedApi() const
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@ -830,7 +864,8 @@ int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
|
||||
return buffer->getIndex();
|
||||
}
|
||||
|
||||
status_t Surface::getBufferLocked(int index, int usage)
|
||||
status_t Surface::getBufferLocked(int index,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
||||
{
|
||||
sp<ISurface> s(mSurface);
|
||||
if (s == 0) return NO_INIT;
|
||||
@ -838,20 +873,21 @@ status_t Surface::getBufferLocked(int index, int usage)
|
||||
status_t err = NO_MEMORY;
|
||||
|
||||
// free the current buffer
|
||||
sp<GraphicBuffer>& currentBuffer(mBuffers[index]);
|
||||
sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
|
||||
if (currentBuffer != 0) {
|
||||
getBufferMapper().unregisterBuffer(currentBuffer->handle);
|
||||
currentBuffer.clear();
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> buffer = s->requestBuffer(index, usage);
|
||||
sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage);
|
||||
LOGE_IF(buffer==0,
|
||||
"ISurface::getBuffer(%d, %08x) returned NULL",
|
||||
index, usage);
|
||||
if (buffer != 0) { // this should never happen by construction
|
||||
LOGE_IF(buffer->handle == NULL,
|
||||
"Surface (identity=%d) requestBuffer(%d, %08x) returned"
|
||||
"a buffer with a null handle", mIdentity, index, usage);
|
||||
"Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) "
|
||||
"returned a buffer with a null handle",
|
||||
mIdentity, index, w, h, format, usage);
|
||||
err = mSharedBufferClient->getStatus();
|
||||
LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err);
|
||||
if (!err && buffer->handle != NULL) {
|
||||
@ -869,5 +905,44 @@ status_t Surface::getBufferLocked(int index, int usage)
|
||||
return err;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Surface::BufferInfo::BufferInfo()
|
||||
: mWidth(0), mHeight(0), mFormat(0),
|
||||
mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) {
|
||||
if ((mWidth != w) || (mHeight != h) || (mFormat != format)) {
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
mFormat = format;
|
||||
mDirty |= GEOMETRY;
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::BufferInfo::set(uint32_t usage) {
|
||||
mUsage = usage;
|
||||
}
|
||||
|
||||
void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight,
|
||||
uint32_t *pFormat, uint32_t *pUsage) const {
|
||||
*pWidth = mWidth;
|
||||
*pHeight = mHeight;
|
||||
*pFormat = mFormat;
|
||||
*pUsage = mUsage;
|
||||
}
|
||||
|
||||
bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const {
|
||||
// make sure we AT LEAST have the usage flags we want
|
||||
if (mDirty || buffer==0 ||
|
||||
((buffer->usage & mUsage) != mUsage)) {
|
||||
mDirty = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user