am b834b38a: Merge "added setCrop() to android_native_window_t" into kraken
This commit is contained in:
commit
e6b2da40fb
@ -70,9 +70,9 @@ class SharedClient;
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX
|
// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX
|
||||||
// 4 * (11 + 7 + (1 + 2*6)*16) * 31
|
// 4 * (11 + 7 + (1 + 2*7)*16) * 31
|
||||||
// 904 * 31
|
// 1032 * 31
|
||||||
// = ~27 KiB (28024)
|
// = ~27 KiB (31992)
|
||||||
|
|
||||||
class SharedBufferStack
|
class SharedBufferStack
|
||||||
{
|
{
|
||||||
@ -82,21 +82,31 @@ class SharedBufferStack
|
|||||||
friend class SharedBufferServer;
|
friend class SharedBufferServer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
|
|
||||||
static const unsigned int NUM_RECT_MAX = 6;
|
|
||||||
uint32_t count;
|
|
||||||
uint16_t rects[4*NUM_RECT_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Statistics { // 4 longs
|
struct Statistics { // 4 longs
|
||||||
typedef int32_t usecs_t;
|
typedef int32_t usecs_t;
|
||||||
usecs_t totalTime;
|
usecs_t totalTime;
|
||||||
usecs_t reserved[3];
|
usecs_t reserved[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SmallRect {
|
||||||
|
uint16_t l, t, r, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
|
||||||
|
static const unsigned int NUM_RECT_MAX = 6;
|
||||||
|
uint32_t count;
|
||||||
|
SmallRect rects[NUM_RECT_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BufferData {
|
||||||
|
FlatRegion dirtyRegion;
|
||||||
|
SmallRect crop;
|
||||||
|
};
|
||||||
|
|
||||||
SharedBufferStack();
|
SharedBufferStack();
|
||||||
void init(int32_t identity);
|
void init(int32_t identity);
|
||||||
status_t setDirtyRegion(int buffer, const Region& reg);
|
status_t setDirtyRegion(int buffer, const Region& reg);
|
||||||
|
status_t setCrop(int buffer, const Rect& reg);
|
||||||
Region getDirtyRegion(int buffer) const;
|
Region getDirtyRegion(int buffer) const;
|
||||||
|
|
||||||
// these attributes are part of the conditions/updates
|
// these attributes are part of the conditions/updates
|
||||||
@ -113,7 +123,7 @@ public:
|
|||||||
int32_t reserved32[6];
|
int32_t reserved32[6];
|
||||||
Statistics stats;
|
Statistics stats;
|
||||||
int32_t reserved;
|
int32_t reserved;
|
||||||
FlatRegion dirtyRegion[NUM_BUFFER_MAX]; // 832 bytes
|
BufferData buffers[NUM_BUFFER_MAX]; // 960 bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -243,6 +253,7 @@ public:
|
|||||||
status_t queue(int buf);
|
status_t queue(int buf);
|
||||||
bool needNewBuffer(int buffer) const;
|
bool needNewBuffer(int buffer) const;
|
||||||
status_t setDirtyRegion(int buffer, const Region& reg);
|
status_t setDirtyRegion(int buffer, const Region& reg);
|
||||||
|
status_t setCrop(int buffer, const Rect& reg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct Condition;
|
friend struct Condition;
|
||||||
|
@ -59,6 +59,9 @@ public:
|
|||||||
|
|
||||||
virtual sp<IMemoryHeap> getControlBlock() const = 0;
|
virtual sp<IMemoryHeap> getControlBlock() const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Requires ACCESS_SURFACE_FLINGER permission
|
||||||
|
*/
|
||||||
virtual sp<ISurface> createSurface( surface_data_t* data,
|
virtual sp<ISurface> createSurface( surface_data_t* data,
|
||||||
int pid,
|
int pid,
|
||||||
const String8& name,
|
const String8& name,
|
||||||
@ -68,8 +71,14 @@ public:
|
|||||||
PixelFormat format,
|
PixelFormat format,
|
||||||
uint32_t flags) = 0;
|
uint32_t flags) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Requires ACCESS_SURFACE_FLINGER permission
|
||||||
|
*/
|
||||||
virtual status_t destroySurface(SurfaceID sid) = 0;
|
virtual status_t destroySurface(SurfaceID sid) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Requires ACCESS_SURFACE_FLINGER permission
|
||||||
|
*/
|
||||||
virtual status_t setState(int32_t count, const layer_state_t* states) = 0;
|
virtual status_t setState(int32_t count, const layer_state_t* states) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,10 +215,12 @@ private:
|
|||||||
void dispatch_setUsage(va_list args);
|
void dispatch_setUsage(va_list args);
|
||||||
int dispatch_connect(va_list args);
|
int dispatch_connect(va_list args);
|
||||||
int dispatch_disconnect(va_list args);
|
int dispatch_disconnect(va_list args);
|
||||||
|
int dispatch_crop(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);
|
||||||
|
|
||||||
uint32_t getUsage() const;
|
uint32_t getUsage() const;
|
||||||
int getConnectedApi() const;
|
int getConnectedApi() const;
|
||||||
@ -237,6 +239,7 @@ private:
|
|||||||
Rect mSwapRectangle;
|
Rect mSwapRectangle;
|
||||||
uint32_t mUsage;
|
uint32_t mUsage;
|
||||||
int mConnected;
|
int mConnected;
|
||||||
|
Rect mNextBufferCrop;
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -41,6 +41,14 @@ extern "C" {
|
|||||||
|
|
||||||
struct android_native_buffer_t;
|
struct android_native_buffer_t;
|
||||||
|
|
||||||
|
typedef struct android_native_rect_t
|
||||||
|
{
|
||||||
|
int32_t left;
|
||||||
|
int32_t top;
|
||||||
|
int32_t right;
|
||||||
|
int32_t bottom;
|
||||||
|
} android_native_rect_t;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct android_native_base_t
|
typedef struct android_native_base_t
|
||||||
@ -63,15 +71,16 @@ typedef struct android_native_base_t
|
|||||||
/* attributes queriable with query() */
|
/* attributes queriable with query() */
|
||||||
enum {
|
enum {
|
||||||
NATIVE_WINDOW_WIDTH = 0,
|
NATIVE_WINDOW_WIDTH = 0,
|
||||||
NATIVE_WINDOW_HEIGHT = 1,
|
NATIVE_WINDOW_HEIGHT,
|
||||||
NATIVE_WINDOW_FORMAT = 2,
|
NATIVE_WINDOW_FORMAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* valid operations for the (*perform)() hook */
|
/* valid operations for the (*perform)() hook */
|
||||||
enum {
|
enum {
|
||||||
NATIVE_WINDOW_SET_USAGE = 0,
|
NATIVE_WINDOW_SET_USAGE = 0,
|
||||||
NATIVE_WINDOW_CONNECT = 1,
|
NATIVE_WINDOW_CONNECT,
|
||||||
NATIVE_WINDOW_DISCONNECT = 2
|
NATIVE_WINDOW_DISCONNECT,
|
||||||
|
NATIVE_WINDOW_SET_CROP,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
|
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
|
||||||
@ -125,7 +134,7 @@ typedef struct android_native_window_t
|
|||||||
*
|
*
|
||||||
* Returns 0 on success or -errno on error.
|
* Returns 0 on success or -errno on error.
|
||||||
*/
|
*/
|
||||||
int (*dequeueBuffer)(struct android_native_window_t* window,
|
int (*dequeueBuffer)(struct android_native_window_t* window,
|
||||||
struct android_native_buffer_t** buffer);
|
struct android_native_buffer_t** buffer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -171,6 +180,7 @@ typedef struct android_native_window_t
|
|||||||
* NATIVE_WINDOW_SET_USAGE
|
* NATIVE_WINDOW_SET_USAGE
|
||||||
* NATIVE_WINDOW_CONNECT
|
* NATIVE_WINDOW_CONNECT
|
||||||
* NATIVE_WINDOW_DISCONNECT
|
* NATIVE_WINDOW_DISCONNECT
|
||||||
|
* NATIVE_WINDOW_SET_CROP
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -221,6 +231,24 @@ static inline int native_window_disconnect(
|
|||||||
return window->perform(window, NATIVE_WINDOW_DISCONNECT, api);
|
return window->perform(window, NATIVE_WINDOW_DISCONNECT, api);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* native_window_set_crop(..., crop) sets which region of the next queued
|
||||||
|
* buffers needs to be considered.
|
||||||
|
* A buffer's crop region is scaled to match the surface's size.
|
||||||
|
*
|
||||||
|
* The specified crop region applies to all buffers queued after it is called.
|
||||||
|
*
|
||||||
|
* if 'crop' is NULL, subsequently queued buffers won't be cropped.
|
||||||
|
*
|
||||||
|
* An error is returned if for instance the crop region is invalid,
|
||||||
|
* out of the buffer's bound or if the window is invalid.
|
||||||
|
*/
|
||||||
|
static inline int native_window_set_crop(
|
||||||
|
android_native_window_t* window,
|
||||||
|
android_native_rect_t const * crop)
|
||||||
|
{
|
||||||
|
return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -67,6 +67,18 @@ void SharedBufferStack::init(int32_t i)
|
|||||||
identity = i;
|
identity = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t SharedBufferStack::setCrop(int buffer, const Rect& crop)
|
||||||
|
{
|
||||||
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||||
|
return BAD_INDEX;
|
||||||
|
|
||||||
|
buffers[buffer].crop.l = uint16_t(crop.left);
|
||||||
|
buffers[buffer].crop.t = uint16_t(crop.top);
|
||||||
|
buffers[buffer].crop.r = uint16_t(crop.right);
|
||||||
|
buffers[buffer].crop.b = uint16_t(crop.bottom);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
|
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
|
||||||
{
|
{
|
||||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||||
@ -75,21 +87,21 @@ status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
|
|||||||
// in the current implementation we only send a single rectangle
|
// in the current implementation we only send a single rectangle
|
||||||
size_t count;
|
size_t count;
|
||||||
Rect const* r = dirty.getArray(&count);
|
Rect const* r = dirty.getArray(&count);
|
||||||
FlatRegion& reg(dirtyRegion[buffer]);
|
FlatRegion& reg(buffers[buffer].dirtyRegion);
|
||||||
if (count > FlatRegion::NUM_RECT_MAX) {
|
if (count > FlatRegion::NUM_RECT_MAX) {
|
||||||
const Rect bounds(dirty.getBounds());
|
const Rect bounds(dirty.getBounds());
|
||||||
reg.count = 1;
|
reg.count = 1;
|
||||||
reg.rects[0] = uint16_t(bounds.left);
|
reg.rects[0].l = uint16_t(bounds.left);
|
||||||
reg.rects[1] = uint16_t(bounds.top);
|
reg.rects[0].t = uint16_t(bounds.top);
|
||||||
reg.rects[2] = uint16_t(bounds.right);
|
reg.rects[0].r = uint16_t(bounds.right);
|
||||||
reg.rects[3] = uint16_t(bounds.bottom);
|
reg.rects[0].b = uint16_t(bounds.bottom);
|
||||||
} else {
|
} else {
|
||||||
reg.count = count;
|
reg.count = count;
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
reg.rects[i*4 + 0] = uint16_t(r[i].left);
|
reg.rects[i].l = uint16_t(r[i].left);
|
||||||
reg.rects[i*4 + 1] = uint16_t(r[i].top);
|
reg.rects[i].t = uint16_t(r[i].top);
|
||||||
reg.rects[i*4 + 2] = uint16_t(r[i].right);
|
reg.rects[i].r = uint16_t(r[i].right);
|
||||||
reg.rects[i*4 + 3] = uint16_t(r[i].bottom);
|
reg.rects[i].b = uint16_t(r[i].bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
@ -101,19 +113,24 @@ Region SharedBufferStack::getDirtyRegion(int buffer) const
|
|||||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
const FlatRegion& reg(dirtyRegion[buffer]);
|
const FlatRegion& reg(buffers[buffer].dirtyRegion);
|
||||||
if (reg.count > FlatRegion::NUM_RECT_MAX)
|
if (reg.count > FlatRegion::NUM_RECT_MAX)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (reg.count == 1) {
|
if (reg.count == 1) {
|
||||||
res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3]));
|
const Rect r(
|
||||||
|
reg.rects[0].l,
|
||||||
|
reg.rects[0].t,
|
||||||
|
reg.rects[0].r,
|
||||||
|
reg.rects[0].b);
|
||||||
|
res.set(r);
|
||||||
} else {
|
} else {
|
||||||
for (size_t i=0 ; i<reg.count ; i++) {
|
for (size_t i=0 ; i<reg.count ; i++) {
|
||||||
const Rect r(
|
const Rect r(
|
||||||
reg.rects[i*4 + 0],
|
reg.rects[i].l,
|
||||||
reg.rects[i*4 + 1],
|
reg.rects[i].t,
|
||||||
reg.rects[i*4 + 2],
|
reg.rects[i].r,
|
||||||
reg.rects[i*4 + 3]);
|
reg.rects[i].b);
|
||||||
res.orSelf(r);
|
res.orSelf(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,6 +389,12 @@ bool SharedBufferClient::needNewBuffer(int buffer) const
|
|||||||
return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
|
return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t SharedBufferClient::setCrop(int buffer, const Rect& crop)
|
||||||
|
{
|
||||||
|
SharedBufferStack& stack( *mSharedStack );
|
||||||
|
return stack.setCrop(buffer, crop);
|
||||||
|
}
|
||||||
|
|
||||||
status_t SharedBufferClient::setDirtyRegion(int buffer, const Region& reg)
|
status_t SharedBufferClient::setDirtyRegion(int buffer, const Region& reg)
|
||||||
{
|
{
|
||||||
SharedBufferStack& stack( *mSharedStack );
|
SharedBufferStack& stack( *mSharedStack );
|
||||||
@ -389,7 +412,7 @@ SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
|
|||||||
mSharedStack->available = num;
|
mSharedStack->available = num;
|
||||||
mSharedStack->queued = 0;
|
mSharedStack->queued = 0;
|
||||||
mSharedStack->reallocMask = 0;
|
mSharedStack->reallocMask = 0;
|
||||||
memset(mSharedStack->dirtyRegion, 0, sizeof(mSharedStack->dirtyRegion));
|
memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t SharedBufferServer::retireAndLock()
|
ssize_t SharedBufferServer::retireAndLock()
|
||||||
|
@ -552,6 +552,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex();
|
int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex();
|
||||||
|
mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop);
|
||||||
mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
|
mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
|
||||||
err = mSharedBufferClient->queue(bufIdx);
|
err = mSharedBufferClient->queue(bufIdx);
|
||||||
LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
|
LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
|
||||||
@ -581,6 +582,10 @@ int Surface::query(int what, int* value)
|
|||||||
|
|
||||||
int Surface::perform(int operation, va_list args)
|
int Surface::perform(int operation, va_list args)
|
||||||
{
|
{
|
||||||
|
status_t err = validate();
|
||||||
|
if (err != NO_ERROR)
|
||||||
|
return err;
|
||||||
|
|
||||||
int res = NO_ERROR;
|
int res = NO_ERROR;
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case NATIVE_WINDOW_SET_USAGE:
|
case NATIVE_WINDOW_SET_USAGE:
|
||||||
@ -592,6 +597,9 @@ int Surface::perform(int operation, va_list args)
|
|||||||
case NATIVE_WINDOW_DISCONNECT:
|
case NATIVE_WINDOW_DISCONNECT:
|
||||||
res = dispatch_disconnect( args );
|
res = dispatch_disconnect( args );
|
||||||
break;
|
break;
|
||||||
|
case NATIVE_WINDOW_SET_CROP:
|
||||||
|
res = dispatch_crop( args );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
res = NAME_NOT_FOUND;
|
res = NAME_NOT_FOUND;
|
||||||
break;
|
break;
|
||||||
@ -611,6 +619,10 @@ int Surface::dispatch_disconnect(va_list args) {
|
|||||||
int api = va_arg(args, int);
|
int api = va_arg(args, int);
|
||||||
return disconnect( api );
|
return disconnect( api );
|
||||||
}
|
}
|
||||||
|
int Surface::dispatch_crop(va_list args) {
|
||||||
|
android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
|
||||||
|
return crop( reinterpret_cast<Rect const*>(rect) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Surface::setUsage(uint32_t reqUsage)
|
void Surface::setUsage(uint32_t reqUsage)
|
||||||
@ -669,6 +681,14 @@ int Surface::getConnectedApi() const
|
|||||||
return mConnected;
|
return mConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Surface::crop(Rect const* rect)
|
||||||
|
{
|
||||||
|
Mutex::Autolock _l(mSurfaceLock);
|
||||||
|
// TODO: validate rect size
|
||||||
|
mNextBufferCrop = *rect;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user