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