am b834b38a: Merge "added setCrop() to android_native_window_t" into kraken

This commit is contained in:
Mathias Agopian 2010-04-20 16:37:29 -07:00 committed by Android Git Automerger
commit e6b2da40fb
6 changed files with 125 additions and 31 deletions

View File

@ -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;

View File

@ -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;
}; };

View File

@ -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.

View File

@ -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);
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -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()

View File

@ -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;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------