unify SurfaceTexture and Surface
Add the concept of synchronous dequeueBuffer in SurfaceTexture Implement {Surface|SurfaceTextureClient}::setSwapInterval() Add SurfaceTexture logging fix onFrameAvailable
This commit is contained in:
parent
ac642349ba
commit
a67932fe68
|
@ -20,355 +20,12 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cutils/compiler.h>
|
||||
|
||||
#include <utils/Debug.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <ui/Rect.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* These classes manage a stack of buffers in shared memory.
|
||||
*
|
||||
* SharedClient: represents a client with several stacks
|
||||
* SharedBufferStack: represents a stack of buffers
|
||||
* SharedBufferClient: manipulates the SharedBufferStack from the client side
|
||||
* SharedBufferServer: manipulates the SharedBufferStack from the server side
|
||||
*
|
||||
* Buffers can be dequeued until there are none available, they can be locked
|
||||
* unless they are in use by the server, which is only the case for the last
|
||||
* dequeue-able buffer. When these various conditions are not met, the caller
|
||||
* waits until the condition is met.
|
||||
*
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class Region;
|
||||
class SharedBufferStack;
|
||||
class SharedClient;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class SharedBufferStack
|
||||
{
|
||||
friend class SharedClient;
|
||||
friend class SharedBufferBase;
|
||||
friend class SharedBufferClient;
|
||||
friend class SharedBufferServer;
|
||||
|
||||
public:
|
||||
// When changing these values, the COMPILE_TIME_ASSERT at the end of this
|
||||
// file need to be updated.
|
||||
static const unsigned int NUM_LAYERS_MAX = 31;
|
||||
static const unsigned int NUM_BUFFER_MAX = 32;
|
||||
static const unsigned int NUM_BUFFER_MIN = 2;
|
||||
static const unsigned int NUM_DISPLAY_MAX = 4;
|
||||
|
||||
struct Statistics { // 4 longs
|
||||
typedef int32_t usecs_t;
|
||||
usecs_t totalTime;
|
||||
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 = 5;
|
||||
uint32_t count;
|
||||
SmallRect rects[NUM_RECT_MAX];
|
||||
};
|
||||
|
||||
struct BufferData {
|
||||
FlatRegion dirtyRegion;
|
||||
SmallRect crop;
|
||||
uint8_t transform;
|
||||
uint8_t reserved[3];
|
||||
};
|
||||
|
||||
SharedBufferStack();
|
||||
void init(int32_t identity);
|
||||
status_t setDirtyRegion(int buffer, const Region& reg);
|
||||
status_t setCrop(int buffer, const Rect& reg);
|
||||
status_t setTransform(int buffer, uint8_t transform);
|
||||
Region getDirtyRegion(int buffer) const;
|
||||
Rect getCrop(int buffer) const;
|
||||
uint32_t getTransform(int buffer) const;
|
||||
|
||||
// these attributes are part of the conditions/updates
|
||||
volatile int32_t head; // server's current front buffer
|
||||
volatile int32_t available; // number of dequeue-able buffers
|
||||
volatile int32_t queued; // number of buffers waiting for post
|
||||
volatile int32_t reserved1;
|
||||
volatile status_t status; // surface's status code
|
||||
|
||||
// not part of the conditions
|
||||
volatile int32_t reallocMask;
|
||||
volatile int8_t index[NUM_BUFFER_MAX];
|
||||
|
||||
int32_t identity; // surface's identity (const)
|
||||
int32_t token; // surface's token (for debugging)
|
||||
Statistics stats;
|
||||
int8_t headBuf; // last retired buffer
|
||||
uint8_t reservedBytes[3];
|
||||
int32_t reserved;
|
||||
BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 64 KB max
|
||||
class SharedClient
|
||||
{
|
||||
public:
|
||||
SharedClient();
|
||||
~SharedClient();
|
||||
status_t validate(size_t token) const;
|
||||
|
||||
private:
|
||||
friend class SharedBufferBase;
|
||||
friend class SharedBufferClient;
|
||||
friend class SharedBufferServer;
|
||||
|
||||
// FIXME: this should be replaced by a lock-less primitive
|
||||
Mutex lock;
|
||||
Condition cv;
|
||||
SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
class SharedBufferBase
|
||||
{
|
||||
public:
|
||||
SharedBufferBase(SharedClient* sharedClient, int surface,
|
||||
int32_t identity);
|
||||
~SharedBufferBase();
|
||||
status_t getStatus() const;
|
||||
int32_t getIdentity() const;
|
||||
String8 dump(char const* prefix) const;
|
||||
|
||||
protected:
|
||||
SharedClient* const mSharedClient;
|
||||
SharedBufferStack* const mSharedStack;
|
||||
const int mIdentity;
|
||||
|
||||
friend struct Update;
|
||||
friend struct QueueUpdate;
|
||||
|
||||
struct ConditionBase {
|
||||
SharedBufferStack& stack;
|
||||
inline ConditionBase(SharedBufferBase* sbc)
|
||||
: stack(*sbc->mSharedStack) { }
|
||||
virtual ~ConditionBase() { };
|
||||
virtual bool operator()() const = 0;
|
||||
virtual const char* name() const = 0;
|
||||
};
|
||||
status_t waitForCondition(const ConditionBase& condition);
|
||||
|
||||
struct UpdateBase {
|
||||
SharedBufferStack& stack;
|
||||
inline UpdateBase(SharedBufferBase* sbb)
|
||||
: stack(*sbb->mSharedStack) { }
|
||||
};
|
||||
template <typename T>
|
||||
status_t updateCondition(T update);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
status_t SharedBufferBase::updateCondition(T update) {
|
||||
SharedClient& client( *mSharedClient );
|
||||
Mutex::Autolock _l(client.lock);
|
||||
ssize_t result = update();
|
||||
client.cv.broadcast();
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class SharedBufferClient : public SharedBufferBase
|
||||
{
|
||||
public:
|
||||
SharedBufferClient(SharedClient* sharedClient, int surface, int num,
|
||||
int32_t identity);
|
||||
|
||||
ssize_t dequeue();
|
||||
status_t undoDequeue(int buf);
|
||||
|
||||
status_t lock(int buf);
|
||||
status_t cancel(int buf);
|
||||
status_t queue(int buf);
|
||||
bool needNewBuffer(int buffer) const;
|
||||
status_t setDirtyRegion(int buffer, const Region& reg);
|
||||
status_t setCrop(int buffer, const Rect& reg);
|
||||
status_t setTransform(int buffer, uint32_t transform);
|
||||
|
||||
class SetBufferCountCallback {
|
||||
friend class SharedBufferClient;
|
||||
virtual status_t operator()(int bufferCount) const = 0;
|
||||
protected:
|
||||
virtual ~SetBufferCountCallback() { }
|
||||
};
|
||||
status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
|
||||
|
||||
private:
|
||||
friend struct Condition;
|
||||
friend struct DequeueCondition;
|
||||
friend struct LockCondition;
|
||||
|
||||
struct QueueUpdate : public UpdateBase {
|
||||
inline QueueUpdate(SharedBufferBase* sbb);
|
||||
inline ssize_t operator()();
|
||||
};
|
||||
|
||||
struct DequeueUpdate : public UpdateBase {
|
||||
inline DequeueUpdate(SharedBufferBase* sbb);
|
||||
inline ssize_t operator()();
|
||||
};
|
||||
|
||||
struct CancelUpdate : public UpdateBase {
|
||||
int tail, buf;
|
||||
inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf);
|
||||
inline ssize_t operator()();
|
||||
};
|
||||
|
||||
// --
|
||||
|
||||
struct DequeueCondition : public ConditionBase {
|
||||
inline DequeueCondition(SharedBufferClient* sbc);
|
||||
inline bool operator()() const;
|
||||
inline const char* name() const { return "DequeueCondition"; }
|
||||
};
|
||||
|
||||
struct LockCondition : public ConditionBase {
|
||||
int buf;
|
||||
inline LockCondition(SharedBufferClient* sbc, int buf);
|
||||
inline bool operator()() const;
|
||||
inline const char* name() const { return "LockCondition"; }
|
||||
};
|
||||
|
||||
int32_t computeTail() const;
|
||||
|
||||
mutable RWLock mLock;
|
||||
int mNumBuffers;
|
||||
|
||||
int32_t tail;
|
||||
int32_t queued_head;
|
||||
// statistics...
|
||||
nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class SharedBufferServer
|
||||
: public SharedBufferBase,
|
||||
public LightRefBase<SharedBufferServer>
|
||||
{
|
||||
public:
|
||||
SharedBufferServer(SharedClient* sharedClient, int surface, int num,
|
||||
int32_t identity);
|
||||
|
||||
ssize_t retireAndLock();
|
||||
void setStatus(status_t status);
|
||||
status_t reallocateAll();
|
||||
status_t reallocateAllExcept(int buffer);
|
||||
int32_t getQueuedCount() const;
|
||||
Region getDirtyRegion(int buffer) const;
|
||||
Rect getCrop(int buffer) const;
|
||||
uint32_t getTransform(int buffer) const;
|
||||
|
||||
status_t resize(int newNumBuffers);
|
||||
status_t grow(int newNumBuffers);
|
||||
status_t shrink(int newNumBuffers);
|
||||
|
||||
SharedBufferStack::Statistics getStats() const;
|
||||
|
||||
|
||||
private:
|
||||
friend class LightRefBase<SharedBufferServer>;
|
||||
~SharedBufferServer();
|
||||
|
||||
/*
|
||||
* BufferList is basically a fixed-capacity sorted-vector of
|
||||
* unsigned 5-bits ints using a 32-bits int as storage.
|
||||
* it has efficient iterators to find items in the list and not in the list.
|
||||
*/
|
||||
class BufferList {
|
||||
size_t mCapacity;
|
||||
uint32_t mList;
|
||||
public:
|
||||
BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
|
||||
: mCapacity(c), mList(0) { }
|
||||
status_t add(int value);
|
||||
status_t remove(int value);
|
||||
uint32_t getMask() const { return mList; }
|
||||
|
||||
class const_iterator {
|
||||
friend class BufferList;
|
||||
uint32_t mask, curr;
|
||||
const_iterator(uint32_t mask) :
|
||||
mask(mask), curr(__builtin_clz(mask)) {
|
||||
}
|
||||
public:
|
||||
inline bool operator == (const const_iterator& rhs) const {
|
||||
return mask == rhs.mask;
|
||||
}
|
||||
inline bool operator != (const const_iterator& rhs) const {
|
||||
return mask != rhs.mask;
|
||||
}
|
||||
inline int operator *() const { return curr; }
|
||||
inline const const_iterator& operator ++() {
|
||||
mask &= ~(1<<(31-curr));
|
||||
curr = __builtin_clz(mask);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator(mList);
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(0);
|
||||
}
|
||||
inline const_iterator free_begin() const {
|
||||
uint32_t mask = (1 << (32-mCapacity)) - 1;
|
||||
return const_iterator( ~(mList | mask) );
|
||||
}
|
||||
};
|
||||
|
||||
// this protects mNumBuffers and mBufferList
|
||||
mutable RWLock mLock;
|
||||
int mNumBuffers;
|
||||
BufferList mBufferList;
|
||||
|
||||
struct BuffersAvailableCondition : public ConditionBase {
|
||||
int mNumBuffers;
|
||||
inline BuffersAvailableCondition(SharedBufferServer* sbs,
|
||||
int numBuffers);
|
||||
inline bool operator()() const;
|
||||
inline const char* name() const { return "BuffersAvailableCondition"; }
|
||||
};
|
||||
|
||||
struct RetireUpdate : public UpdateBase {
|
||||
const int numBuffers;
|
||||
inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
|
||||
inline ssize_t operator()();
|
||||
};
|
||||
|
||||
struct StatusUpdate : public UpdateBase {
|
||||
const status_t status;
|
||||
inline StatusUpdate(SharedBufferBase* sbb, status_t status);
|
||||
inline ssize_t operator()();
|
||||
};
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
#define NUM_DISPLAY_MAX 4
|
||||
|
||||
struct display_cblk_t
|
||||
{
|
||||
|
@ -389,12 +46,11 @@ struct surface_flinger_cblk_t // 4KB max
|
|||
uint8_t connected;
|
||||
uint8_t reserved[3];
|
||||
uint32_t pad[7];
|
||||
display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];
|
||||
display_cblk_t displays[NUM_DISPLAY_MAX];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 65536)
|
||||
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class GraphicBuffer;
|
||||
|
||||
class IGraphicBufferAlloc : public IInterface
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -27,42 +27,23 @@
|
|||
|
||||
#include <ui/PixelFormat.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
typedef int32_t SurfaceID;
|
||||
|
||||
class GraphicBuffer;
|
||||
class ISurfaceTexture;
|
||||
|
||||
class ISurface : public IInterface
|
||||
{
|
||||
protected:
|
||||
enum {
|
||||
RESERVED0 = IBinder::FIRST_CALL_TRANSACTION,
|
||||
RESERVED1,
|
||||
RESERVED2,
|
||||
REQUEST_BUFFER,
|
||||
SET_BUFFER_COUNT,
|
||||
GET_SURFACE_TEXTURE = IBinder::FIRST_CALL_TRANSACTION,
|
||||
};
|
||||
|
||||
public:
|
||||
DECLARE_META_INTERFACE(Surface);
|
||||
|
||||
/*
|
||||
* requests a new buffer for the given index. If w, h, or format are
|
||||
* null the buffer is created with the parameters assigned to the
|
||||
* surface it is bound to. Otherwise the buffer's parameters are
|
||||
* set to those specified.
|
||||
*/
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
|
||||
|
||||
/*
|
||||
* sets the number of buffers dequeuable for this surface.
|
||||
*/
|
||||
virtual status_t setBufferCount(int bufferCount) = 0;
|
||||
virtual sp<ISurfaceTexture> getSurfaceTexture() const = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class IMemoryHeap;
|
||||
|
||||
class ISurfaceComposer : public IInterface
|
||||
{
|
||||
public:
|
||||
|
@ -95,10 +97,6 @@ public:
|
|||
*/
|
||||
virtual sp<ISurfaceComposerClient> createConnection() = 0;
|
||||
|
||||
/* create a client connection with surface flinger
|
||||
*/
|
||||
virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
|
||||
|
||||
/* create a graphic buffer allocator
|
||||
*/
|
||||
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
|
||||
|
@ -134,11 +132,6 @@ public:
|
|||
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
|
||||
virtual status_t turnElectronBeamOn(int32_t mode) = 0;
|
||||
|
||||
/* Signal surfaceflinger that there might be some work to do
|
||||
* This is an ASYNCHRONOUS call.
|
||||
*/
|
||||
virtual void signal() const = 0;
|
||||
|
||||
/* verify that an ISurface was created by SurfaceFlinger.
|
||||
*/
|
||||
virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0;
|
||||
|
@ -154,7 +147,6 @@ public:
|
|||
// Java by ActivityManagerService.
|
||||
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
|
||||
CREATE_CONNECTION,
|
||||
CREATE_CLIENT_CONNECTION,
|
||||
CREATE_GRAPHIC_BUFFER_ALLOC,
|
||||
GET_CBLK,
|
||||
OPEN_GLOBAL_TRANSACTION,
|
||||
|
@ -162,7 +154,6 @@ public:
|
|||
SET_ORIENTATION,
|
||||
FREEZE_DISPLAY,
|
||||
UNFREEZE_DISPLAY,
|
||||
SIGNAL,
|
||||
CAPTURE_SCREEN,
|
||||
TURN_ELECTRON_BEAM_OFF,
|
||||
TURN_ELECTRON_BEAM_ON,
|
||||
|
|
|
@ -33,9 +33,6 @@ namespace android {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class IMemoryHeap;
|
||||
|
||||
typedef int32_t ClientID;
|
||||
typedef int32_t DisplayID;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -57,9 +54,6 @@ public:
|
|||
status_t writeToParcel(Parcel* parcel) const;
|
||||
};
|
||||
|
||||
virtual sp<IMemoryHeap> getControlBlock() const = 0;
|
||||
virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const = 0;
|
||||
|
||||
/*
|
||||
* Requires ACCESS_SURFACE_FLINGER permission
|
||||
*/
|
||||
|
|
|
@ -43,9 +43,7 @@ class IOMX;
|
|||
class Rect;
|
||||
class Surface;
|
||||
class SurfaceComposerClient;
|
||||
class SharedClient;
|
||||
class SharedBufferClient;
|
||||
class SurfaceClient;
|
||||
class SurfaceTextureClient;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -162,9 +160,6 @@ public:
|
|||
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
|
||||
status_t unlockAndPost();
|
||||
|
||||
// setSwapRectangle() is intended to be used by GL ES clients
|
||||
void setSwapRectangle(const Rect& r);
|
||||
|
||||
sp<IBinder> asBinder() const;
|
||||
|
||||
private:
|
||||
|
@ -209,6 +204,7 @@ private:
|
|||
static int query(const ANativeWindow* window, int what, int* value);
|
||||
static int perform(ANativeWindow* window, int operation, ...);
|
||||
|
||||
int setSwapInterval(int interval);
|
||||
int dequeueBuffer(ANativeWindowBuffer** buffer);
|
||||
int lockBuffer(ANativeWindowBuffer* buffer);
|
||||
int queueBuffer(ANativeWindowBuffer* buffer);
|
||||
|
@ -216,83 +212,23 @@ private:
|
|||
int query(int what, int* value) const;
|
||||
int perform(int operation, va_list args);
|
||||
|
||||
void dispatch_setUsage(va_list args);
|
||||
int dispatch_connect(va_list args);
|
||||
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);
|
||||
int dispatch_set_buffers_transform(va_list args);
|
||||
int dispatch_set_buffers_timestamp(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);
|
||||
int setBuffersTransform(int transform);
|
||||
int setBuffersTimestamp(int64_t timestamp);
|
||||
|
||||
/*
|
||||
* private stuff...
|
||||
*/
|
||||
void init();
|
||||
status_t validate(bool inCancelBuffer = false) const;
|
||||
|
||||
// When the buffer pool is a fixed size we want to make sure SurfaceFlinger
|
||||
// won't stall clients, so we require an extra buffer.
|
||||
enum { MIN_UNDEQUEUED_BUFFERS = 2 };
|
||||
|
||||
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
|
||||
inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
|
||||
|
||||
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 getConnectedApi() const;
|
||||
|
||||
bool needNewBuffer(int bufIdx,
|
||||
uint32_t *pWidth, uint32_t *pHeight,
|
||||
uint32_t *pFormat, uint32_t *pUsage) const;
|
||||
|
||||
static void cleanCachedSurfacesLocked();
|
||||
|
||||
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
|
||||
GraphicBufferMapper& mBufferMapper;
|
||||
SurfaceClient& mClient;
|
||||
SharedBufferClient* mSharedBufferClient;
|
||||
status_t mInitCheck;
|
||||
sp<ISurface> mSurface;
|
||||
sp<SurfaceTextureClient> mSurfaceTextureClient;
|
||||
uint32_t mIdentity;
|
||||
PixelFormat mFormat;
|
||||
uint32_t mFlags;
|
||||
|
||||
// protected by mSurfaceLock
|
||||
Rect mSwapRectangle;
|
||||
int mConnected;
|
||||
Rect mNextBufferCrop;
|
||||
uint32_t mNextBufferTransform;
|
||||
BufferInfo mBufferInfo;
|
||||
|
||||
// protected by mSurfaceLock. These are also used from lock/unlock
|
||||
// but in that case, they must be called form the same thread.
|
||||
|
@ -304,9 +240,6 @@ 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;
|
||||
|
|
|
@ -36,10 +36,10 @@ namespace android {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Region;
|
||||
class SharedClient;
|
||||
class ISurfaceComposer;
|
||||
class DisplayInfo;
|
||||
class IMemoryHeap;
|
||||
class ISurfaceComposer;
|
||||
class Region;
|
||||
class surface_flinger_cblk_t;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -16,7 +16,6 @@ LOCAL_SRC_FILES:= \
|
|||
ISurfaceComposerClient.cpp \
|
||||
IGraphicBufferAlloc.cpp \
|
||||
LayerState.cpp \
|
||||
SharedBufferStack.cpp \
|
||||
Surface.cpp \
|
||||
SurfaceComposerClient.cpp \
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
|
||||
#include <binder/Parcel.h>
|
||||
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
||||
#include <surfaceflinger/Surface.h>
|
||||
#include <gui/ISurfaceTexture.h>
|
||||
#include <surfaceflinger/ISurface.h>
|
||||
|
||||
namespace android {
|
||||
|
@ -39,30 +37,11 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
||||
{
|
||||
virtual sp<ISurfaceTexture> getSurfaceTexture() const {
|
||||
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();
|
||||
reply.read(*buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
virtual status_t setBufferCount(int bufferCount)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
|
||||
data.writeInt32(bufferCount);
|
||||
remote()->transact(SET_BUFFER_COUNT, data, &reply);
|
||||
status_t err = reply.readInt32();
|
||||
return err;
|
||||
remote()->transact(GET_SURFACE_TEXTURE, data, &reply);
|
||||
return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -74,23 +53,9 @@ status_t BnSurface::onTransact(
|
|||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
switch(code) {
|
||||
case REQUEST_BUFFER: {
|
||||
case GET_SURFACE_TEXTURE: {
|
||||
CHECK_INTERFACE(ISurface, data, reply);
|
||||
int bufferIdx = data.readInt32();
|
||||
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);
|
||||
}
|
||||
case SET_BUFFER_COUNT: {
|
||||
CHECK_INTERFACE(ISurface, data, reply);
|
||||
int bufferCount = data.readInt32();
|
||||
status_t err = setBufferCount(bufferCount);
|
||||
reply->writeInt32(err);
|
||||
reply->writeStrongBinder( getSurfaceTexture()->asBinder() );
|
||||
return NO_ERROR;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -57,15 +57,6 @@ public:
|
|||
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
|
||||
}
|
||||
|
||||
virtual sp<ISurfaceComposerClient> createClientConnection()
|
||||
{
|
||||
uint32_t n;
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
remote()->transact(BnSurfaceComposer::CREATE_CLIENT_CONNECTION, data, &reply);
|
||||
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
|
||||
}
|
||||
|
||||
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
|
||||
{
|
||||
uint32_t n;
|
||||
|
@ -174,13 +165,6 @@ public:
|
|||
return reply.readInt32();
|
||||
}
|
||||
|
||||
virtual void signal() const
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
|
||||
}
|
||||
|
||||
virtual bool authenticateSurface(const sp<ISurface>& surface) const
|
||||
{
|
||||
Parcel data, reply;
|
||||
|
@ -229,11 +213,6 @@ status_t BnSurfaceComposer::onTransact(
|
|||
sp<IBinder> b = createConnection()->asBinder();
|
||||
reply->writeStrongBinder(b);
|
||||
} break;
|
||||
case CREATE_CLIENT_CONNECTION: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
sp<IBinder> b = createClientConnection()->asBinder();
|
||||
reply->writeStrongBinder(b);
|
||||
} break;
|
||||
case CREATE_GRAPHIC_BUFFER_ALLOC: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
|
||||
|
@ -270,10 +249,6 @@ status_t BnSurfaceComposer::onTransact(
|
|||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
bootFinished();
|
||||
} break;
|
||||
case SIGNAL: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
signal();
|
||||
} break;
|
||||
case GET_CBLK: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
sp<IBinder> b = getCblk()->asBinder();
|
||||
|
|
|
@ -50,9 +50,7 @@
|
|||
namespace android {
|
||||
|
||||
enum {
|
||||
GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
|
||||
GET_TOKEN,
|
||||
CREATE_SURFACE,
|
||||
CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
|
||||
DESTROY_SURFACE,
|
||||
SET_STATE
|
||||
};
|
||||
|
@ -65,23 +63,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual sp<IMemoryHeap> getControlBlock() const
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
|
||||
remote()->transact(GET_CBLK, data, &reply);
|
||||
return interface_cast<IMemoryHeap>(reply.readStrongBinder());
|
||||
}
|
||||
|
||||
virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
|
||||
data.writeStrongBinder(sur->asBinder());
|
||||
remote()->transact(GET_TOKEN, data, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
virtual sp<ISurface> createSurface( surface_data_t* params,
|
||||
const String8& name,
|
||||
DisplayID display,
|
||||
|
@ -131,41 +112,6 @@ IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClie
|
|||
status_t BnSurfaceComposerClient::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
// codes that don't require permission check
|
||||
|
||||
switch(code) {
|
||||
case GET_CBLK: {
|
||||
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
|
||||
sp<IMemoryHeap> ctl(getControlBlock());
|
||||
reply->writeStrongBinder(ctl->asBinder());
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case GET_TOKEN: {
|
||||
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
|
||||
sp<ISurface> sur = interface_cast<ISurface>(data.readStrongBinder());
|
||||
ssize_t token = getTokenForSurface(sur);
|
||||
reply->writeInt32(token);
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
}
|
||||
|
||||
// these must be checked
|
||||
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int pid = ipc->getCallingPid();
|
||||
const int uid = ipc->getCallingUid();
|
||||
const int self_pid = getpid();
|
||||
if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
|
||||
// we're called from a different process, do the real check
|
||||
if (!checkCallingPermission(
|
||||
String16("android.permission.ACCESS_SURFACE_FLINGER")))
|
||||
{
|
||||
LOGE("Permission Denial: "
|
||||
"can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
switch(code) {
|
||||
case CREATE_SURFACE: {
|
||||
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
|
||||
|
|
|
@ -1,714 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SharedBufferStack"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Debug.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <private/surfaceflinger/SharedBufferStack.h>
|
||||
|
||||
#include <ui/Rect.h>
|
||||
#include <ui/Region.h>
|
||||
|
||||
#define DEBUG_ATOMICS 0
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SharedClient::SharedClient()
|
||||
: lock(Mutex::SHARED), cv(Condition::SHARED)
|
||||
{
|
||||
}
|
||||
|
||||
SharedClient::~SharedClient() {
|
||||
}
|
||||
|
||||
|
||||
// these functions are used by the clients
|
||||
status_t SharedClient::validate(size_t i) const {
|
||||
if (uint32_t(i) >= uint32_t(SharedBufferStack::NUM_LAYERS_MAX))
|
||||
return BAD_INDEX;
|
||||
return surfaces[i].status;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
SharedBufferStack::SharedBufferStack()
|
||||
{
|
||||
}
|
||||
|
||||
void SharedBufferStack::init(int32_t i)
|
||||
{
|
||||
status = NO_ERROR;
|
||||
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::setTransform(int buffer, uint8_t transform)
|
||||
{
|
||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||
return BAD_INDEX;
|
||||
buffers[buffer].transform = transform;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
|
||||
{
|
||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||
return BAD_INDEX;
|
||||
|
||||
FlatRegion& reg(buffers[buffer].dirtyRegion);
|
||||
if (dirty.isEmpty()) {
|
||||
reg.count = 0;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
size_t count;
|
||||
Rect const* r = dirty.getArray(&count);
|
||||
if (count > FlatRegion::NUM_RECT_MAX) {
|
||||
const Rect bounds(dirty.getBounds());
|
||||
reg.count = 1;
|
||||
reg.rects[0].l = uint16_t(bounds.left);
|
||||
reg.rects[0].t = uint16_t(bounds.top);
|
||||
reg.rects[0].r = uint16_t(bounds.right);
|
||||
reg.rects[0].b = uint16_t(bounds.bottom);
|
||||
} else {
|
||||
reg.count = count;
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
reg.rects[i].l = uint16_t(r[i].left);
|
||||
reg.rects[i].t = uint16_t(r[i].top);
|
||||
reg.rects[i].r = uint16_t(r[i].right);
|
||||
reg.rects[i].b = uint16_t(r[i].bottom);
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
Region SharedBufferStack::getDirtyRegion(int buffer) const
|
||||
{
|
||||
Region res;
|
||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||
return res;
|
||||
|
||||
const FlatRegion& reg(buffers[buffer].dirtyRegion);
|
||||
if (reg.count > FlatRegion::NUM_RECT_MAX)
|
||||
return res;
|
||||
|
||||
if (reg.count == 1) {
|
||||
const Rect r(
|
||||
reg.rects[0].l,
|
||||
reg.rects[0].t,
|
||||
reg.rects[0].r,
|
||||
reg.rects[0].b);
|
||||
res.set(r);
|
||||
} else {
|
||||
for (size_t i=0 ; i<reg.count ; i++) {
|
||||
const Rect r(
|
||||
reg.rects[i].l,
|
||||
reg.rects[i].t,
|
||||
reg.rects[i].r,
|
||||
reg.rects[i].b);
|
||||
res.orSelf(r);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Rect SharedBufferStack::getCrop(int buffer) const
|
||||
{
|
||||
Rect res(-1, -1);
|
||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||
return res;
|
||||
res.left = buffers[buffer].crop.l;
|
||||
res.top = buffers[buffer].crop.t;
|
||||
res.right = buffers[buffer].crop.r;
|
||||
res.bottom = buffers[buffer].crop.b;
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t SharedBufferStack::getTransform(int buffer) const
|
||||
{
|
||||
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
||||
return 0;
|
||||
return buffers[buffer].transform;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
|
||||
int surface, int32_t identity)
|
||||
: mSharedClient(sharedClient),
|
||||
mSharedStack(sharedClient->surfaces + surface),
|
||||
mIdentity(identity)
|
||||
{
|
||||
}
|
||||
|
||||
SharedBufferBase::~SharedBufferBase()
|
||||
{
|
||||
}
|
||||
|
||||
status_t SharedBufferBase::getStatus() const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.status;
|
||||
}
|
||||
|
||||
int32_t SharedBufferBase::getIdentity() const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.identity;
|
||||
}
|
||||
|
||||
String8 SharedBufferBase::dump(char const* prefix) const
|
||||
{
|
||||
const size_t SIZE = 1024;
|
||||
char buffer[SIZE];
|
||||
String8 result;
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
snprintf(buffer, SIZE,
|
||||
"%s[ head=%2d, available=%2d, queued=%2d ] "
|
||||
"reallocMask=%08x, identity=%d, status=%d",
|
||||
prefix, stack.head, stack.available, stack.queued,
|
||||
stack.reallocMask, stack.identity, stack.status);
|
||||
result.append(buffer);
|
||||
result.append("\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
status_t SharedBufferBase::waitForCondition(const ConditionBase& condition)
|
||||
{
|
||||
const SharedBufferStack& stack( *mSharedStack );
|
||||
SharedClient& client( *mSharedClient );
|
||||
const nsecs_t TIMEOUT = s2ns(1);
|
||||
const int identity = mIdentity;
|
||||
|
||||
Mutex::Autolock _l(client.lock);
|
||||
while ((condition()==false) &&
|
||||
(stack.identity == identity) &&
|
||||
(stack.status == NO_ERROR))
|
||||
{
|
||||
status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
|
||||
// handle errors and timeouts
|
||||
if (CC_UNLIKELY(err != NO_ERROR)) {
|
||||
if (err == TIMED_OUT) {
|
||||
if (condition()) {
|
||||
LOGE("waitForCondition(%s) timed out (identity=%d), "
|
||||
"but condition is true! We recovered but it "
|
||||
"shouldn't happen." , condition.name(), stack.identity);
|
||||
break;
|
||||
} else {
|
||||
LOGW("waitForCondition(%s) timed out "
|
||||
"(identity=%d, status=%d). "
|
||||
"CPU may be pegged. trying again.", condition.name(),
|
||||
stack.identity, stack.status);
|
||||
}
|
||||
} else {
|
||||
LOGE("waitForCondition(%s) error (%s) ",
|
||||
condition.name(), strerror(-err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
|
||||
}
|
||||
// ============================================================================
|
||||
// conditions and updates
|
||||
// ============================================================================
|
||||
|
||||
SharedBufferClient::DequeueCondition::DequeueCondition(
|
||||
SharedBufferClient* sbc) : ConditionBase(sbc) {
|
||||
}
|
||||
bool SharedBufferClient::DequeueCondition::operator()() const {
|
||||
return stack.available > 0;
|
||||
}
|
||||
|
||||
SharedBufferClient::LockCondition::LockCondition(
|
||||
SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) {
|
||||
}
|
||||
bool SharedBufferClient::LockCondition::operator()() const {
|
||||
// NOTE: if stack.head is messed up, we could crash the client
|
||||
// or cause some drawing artifacts. This is okay, as long as it is
|
||||
// limited to the client.
|
||||
return (buf != stack.index[stack.head]);
|
||||
}
|
||||
|
||||
SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition(
|
||||
SharedBufferServer* sbs, int numBuffers) : ConditionBase(sbs),
|
||||
mNumBuffers(numBuffers) {
|
||||
}
|
||||
bool SharedBufferServer::BuffersAvailableCondition::operator()() const {
|
||||
return stack.available == mNumBuffers;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
|
||||
: UpdateBase(sbb) {
|
||||
}
|
||||
ssize_t SharedBufferClient::QueueUpdate::operator()() {
|
||||
android_atomic_inc(&stack.queued);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
SharedBufferClient::DequeueUpdate::DequeueUpdate(SharedBufferBase* sbb)
|
||||
: UpdateBase(sbb) {
|
||||
}
|
||||
ssize_t SharedBufferClient::DequeueUpdate::operator()() {
|
||||
if (android_atomic_dec(&stack.available) == 0) {
|
||||
LOGW("dequeue probably called from multiple threads!");
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
SharedBufferClient::CancelUpdate::CancelUpdate(SharedBufferBase* sbb,
|
||||
int tail, int buf)
|
||||
: UpdateBase(sbb), tail(tail), buf(buf) {
|
||||
}
|
||||
ssize_t SharedBufferClient::CancelUpdate::operator()() {
|
||||
stack.index[tail] = buf;
|
||||
android_atomic_inc(&stack.available);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
SharedBufferServer::RetireUpdate::RetireUpdate(
|
||||
SharedBufferBase* sbb, int numBuffers)
|
||||
: UpdateBase(sbb), numBuffers(numBuffers) {
|
||||
}
|
||||
ssize_t SharedBufferServer::RetireUpdate::operator()() {
|
||||
int32_t head = stack.head;
|
||||
if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
|
||||
return BAD_VALUE;
|
||||
|
||||
// Decrement the number of queued buffers
|
||||
int32_t queued;
|
||||
do {
|
||||
queued = stack.queued;
|
||||
if (queued == 0) {
|
||||
return NOT_ENOUGH_DATA;
|
||||
}
|
||||
} while (android_atomic_cmpxchg(queued, queued-1, &stack.queued));
|
||||
|
||||
// lock the buffer before advancing head, which automatically unlocks
|
||||
// the buffer we preventively locked upon entering this function
|
||||
|
||||
head = (head + 1) % numBuffers;
|
||||
const int8_t headBuf = stack.index[head];
|
||||
stack.headBuf = headBuf;
|
||||
|
||||
// head is only modified here, so we don't need to use cmpxchg
|
||||
android_atomic_write(head, &stack.head);
|
||||
|
||||
// now that head has moved, we can increment the number of available buffers
|
||||
android_atomic_inc(&stack.available);
|
||||
return head;
|
||||
}
|
||||
|
||||
SharedBufferServer::StatusUpdate::StatusUpdate(
|
||||
SharedBufferBase* sbb, status_t status)
|
||||
: UpdateBase(sbb), status(status) {
|
||||
}
|
||||
|
||||
ssize_t SharedBufferServer::StatusUpdate::operator()() {
|
||||
android_atomic_write(status, &stack.status);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
|
||||
int surface, int num, int32_t identity)
|
||||
: SharedBufferBase(sharedClient, surface, identity),
|
||||
mNumBuffers(num), tail(0)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
tail = computeTail();
|
||||
queued_head = stack.head;
|
||||
}
|
||||
|
||||
int32_t SharedBufferClient::computeTail() const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
|
||||
}
|
||||
|
||||
ssize_t SharedBufferClient::dequeue()
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
|
||||
RWLock::AutoRLock _rd(mLock);
|
||||
|
||||
const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
|
||||
|
||||
//LOGD("[%d] about to dequeue a buffer",
|
||||
// mSharedStack->identity);
|
||||
DequeueCondition condition(this);
|
||||
status_t err = waitForCondition(condition);
|
||||
if (err != NO_ERROR)
|
||||
return ssize_t(err);
|
||||
|
||||
DequeueUpdate update(this);
|
||||
updateCondition( update );
|
||||
|
||||
int dequeued = stack.index[tail];
|
||||
tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
|
||||
LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s",
|
||||
dequeued, tail, dump("").string());
|
||||
|
||||
mDequeueTime[dequeued] = dequeueTime;
|
||||
|
||||
return dequeued;
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::undoDequeue(int buf)
|
||||
{
|
||||
return cancel(buf);
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::cancel(int buf)
|
||||
{
|
||||
RWLock::AutoRLock _rd(mLock);
|
||||
|
||||
// calculate the new position of the tail index (essentially tail--)
|
||||
int localTail = (tail + mNumBuffers - 1) % mNumBuffers;
|
||||
CancelUpdate update(this, localTail, buf);
|
||||
status_t err = updateCondition( update );
|
||||
if (err == NO_ERROR) {
|
||||
tail = localTail;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::lock(int buf)
|
||||
{
|
||||
RWLock::AutoRLock _rd(mLock);
|
||||
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
LockCondition condition(this, buf);
|
||||
status_t err = waitForCondition(condition);
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::queue(int buf)
|
||||
{
|
||||
RWLock::AutoRLock _rd(mLock);
|
||||
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
|
||||
queued_head = (queued_head + 1) % mNumBuffers;
|
||||
stack.index[queued_head] = buf;
|
||||
|
||||
QueueUpdate update(this);
|
||||
status_t err = updateCondition( update );
|
||||
LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
|
||||
|
||||
const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
|
||||
stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool SharedBufferClient::needNewBuffer(int buf) const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
const uint32_t mask = 1<<(31-buf);
|
||||
return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::setCrop(int buf, const Rect& crop)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.setCrop(buf, crop);
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::setTransform(int buf, uint32_t transform)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.setTransform(buf, uint8_t(transform));
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.setDirtyRegion(buf, reg);
|
||||
}
|
||||
|
||||
status_t SharedBufferClient::setBufferCount(
|
||||
int bufferCount, const SetBufferCountCallback& ipc)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
if (uint32_t(bufferCount) >= SharedBufferStack::NUM_BUFFER_MAX)
|
||||
return BAD_VALUE;
|
||||
|
||||
if (uint32_t(bufferCount) < SharedBufferStack::NUM_BUFFER_MIN)
|
||||
return BAD_VALUE;
|
||||
|
||||
RWLock::AutoWLock _wr(mLock);
|
||||
|
||||
status_t err = ipc(bufferCount);
|
||||
if (err == NO_ERROR) {
|
||||
mNumBuffers = bufferCount;
|
||||
queued_head = (stack.head + stack.queued) % mNumBuffers;
|
||||
tail = computeTail();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
|
||||
int surface, int num, int32_t identity)
|
||||
: SharedBufferBase(sharedClient, surface, identity),
|
||||
mNumBuffers(num)
|
||||
{
|
||||
mSharedStack->init(identity);
|
||||
mSharedStack->token = surface;
|
||||
mSharedStack->head = num-1;
|
||||
mSharedStack->available = num;
|
||||
mSharedStack->queued = 0;
|
||||
mSharedStack->reallocMask = 0;
|
||||
memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));
|
||||
for (int i=0 ; i<num ; i++) {
|
||||
mBufferList.add(i);
|
||||
mSharedStack->index[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
SharedBufferServer::~SharedBufferServer()
|
||||
{
|
||||
}
|
||||
|
||||
ssize_t SharedBufferServer::retireAndLock()
|
||||
{
|
||||
RWLock::AutoRLock _l(mLock);
|
||||
|
||||
RetireUpdate update(this, mNumBuffers);
|
||||
ssize_t buf = updateCondition( update );
|
||||
if (buf >= 0) {
|
||||
if (uint32_t(buf) >= SharedBufferStack::NUM_BUFFER_MAX)
|
||||
return BAD_VALUE;
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
buf = stack.index[buf];
|
||||
LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s",
|
||||
int(buf), dump("").string());
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void SharedBufferServer::setStatus(status_t status)
|
||||
{
|
||||
if (status < NO_ERROR) {
|
||||
StatusUpdate update(this, status);
|
||||
updateCondition( update );
|
||||
}
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::reallocateAll()
|
||||
{
|
||||
RWLock::AutoRLock _l(mLock);
|
||||
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
uint32_t mask = mBufferList.getMask();
|
||||
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;
|
||||
}
|
||||
|
||||
int32_t SharedBufferServer::getQueuedCount() const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.queued;
|
||||
}
|
||||
|
||||
Region SharedBufferServer::getDirtyRegion(int buf) const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.getDirtyRegion(buf);
|
||||
}
|
||||
|
||||
Rect SharedBufferServer::getCrop(int buf) const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.getCrop(buf);
|
||||
}
|
||||
|
||||
uint32_t SharedBufferServer::getTransform(int buf) const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.getTransform(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: this is not thread-safe on the server-side, meaning
|
||||
* 'head' cannot move during this operation. The client-side
|
||||
* can safely operate an usual.
|
||||
*
|
||||
*/
|
||||
status_t SharedBufferServer::resize(int newNumBuffers)
|
||||
{
|
||||
if ((unsigned int)(newNumBuffers) < SharedBufferStack::NUM_BUFFER_MIN ||
|
||||
(unsigned int)(newNumBuffers) > SharedBufferStack::NUM_BUFFER_MAX) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
RWLock::AutoWLock _l(mLock);
|
||||
|
||||
if (newNumBuffers < mNumBuffers) {
|
||||
return shrink(newNumBuffers);
|
||||
} else {
|
||||
return grow(newNumBuffers);
|
||||
}
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::grow(int newNumBuffers)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
const int numBuffers = mNumBuffers;
|
||||
const int extra = newNumBuffers - numBuffers;
|
||||
|
||||
// read the head, make sure it's valid
|
||||
int32_t head = stack.head;
|
||||
if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
|
||||
return BAD_VALUE;
|
||||
|
||||
int base = numBuffers;
|
||||
int32_t avail = stack.available;
|
||||
int tail = head - avail + 1;
|
||||
|
||||
if (tail >= 0) {
|
||||
int8_t* const index = const_cast<int8_t*>(stack.index);
|
||||
const int nb = numBuffers - head;
|
||||
memmove(&index[head + extra], &index[head], nb);
|
||||
base = head;
|
||||
// move head 'extra' ahead, this doesn't impact stack.index[head];
|
||||
stack.head = head + extra;
|
||||
}
|
||||
stack.available += extra;
|
||||
|
||||
// fill the new free space with unused buffers
|
||||
BufferList::const_iterator curr(mBufferList.free_begin());
|
||||
for (int i=0 ; i<extra ; i++) {
|
||||
stack.index[base+i] = *curr;
|
||||
mBufferList.add(*curr);
|
||||
++curr;
|
||||
}
|
||||
|
||||
mNumBuffers = newNumBuffers;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::shrink(int newNumBuffers)
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
|
||||
// Shrinking is only supported if there are no buffers currently dequeued.
|
||||
int32_t avail = stack.available;
|
||||
int32_t queued = stack.queued;
|
||||
if (avail + queued != mNumBuffers) {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// Wait for any queued buffers to be displayed.
|
||||
BuffersAvailableCondition condition(this, mNumBuffers);
|
||||
status_t err = waitForCondition(condition);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Reset head to index 0 and make it refer to buffer 0. The same renaming
|
||||
// (head -> 0) is done in the BufferManager.
|
||||
int32_t head = stack.head;
|
||||
int8_t* index = const_cast<int8_t*>(stack.index);
|
||||
for (int8_t i = 0; i < newNumBuffers; i++) {
|
||||
index[i] = i;
|
||||
}
|
||||
stack.head = 0;
|
||||
stack.headBuf = 0;
|
||||
|
||||
// Free the buffers from the end of the list that are no longer needed.
|
||||
for (int i = newNumBuffers; i < mNumBuffers; i++) {
|
||||
mBufferList.remove(i);
|
||||
}
|
||||
|
||||
// Tell the client to reallocate all the buffers.
|
||||
reallocateAll();
|
||||
|
||||
mNumBuffers = newNumBuffers;
|
||||
stack.available = newNumBuffers;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
SharedBufferStack::Statistics SharedBufferServer::getStats() const
|
||||
{
|
||||
SharedBufferStack& stack( *mSharedStack );
|
||||
return stack.stats;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
status_t SharedBufferServer::BufferList::add(int value)
|
||||
{
|
||||
if (uint32_t(value) >= mCapacity)
|
||||
return BAD_VALUE;
|
||||
uint32_t mask = 1<<(31-value);
|
||||
if (mList & mask)
|
||||
return ALREADY_EXISTS;
|
||||
mList |= mask;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SharedBufferServer::BufferList::remove(int value)
|
||||
{
|
||||
if (uint32_t(value) >= mCapacity)
|
||||
return BAD_VALUE;
|
||||
uint32_t mask = 1<<(31-value);
|
||||
if (!(mList & mask))
|
||||
return NAME_NOT_FOUND;
|
||||
mList &= ~mask;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
|
@ -21,13 +21,15 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/CallStack.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IMemory.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
|
||||
#include <gui/SurfaceTextureClient.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
@ -35,12 +37,11 @@
|
|||
#include <ui/GraphicLog.h>
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include <surfaceflinger/Surface.h>
|
||||
#include <surfaceflinger/ISurface.h>
|
||||
#include <surfaceflinger/ISurfaceComposer.h>
|
||||
#include <surfaceflinger/Surface.h>
|
||||
#include <surfaceflinger/SurfaceComposerClient.h>
|
||||
|
||||
#include <private/surfaceflinger/SharedBufferStack.h>
|
||||
#include <private/surfaceflinger/LayerState.h>
|
||||
|
||||
namespace android {
|
||||
|
@ -273,58 +274,10 @@ sp<Surface> SurfaceControl::getSurface() const
|
|||
// Surface
|
||||
// ============================================================================
|
||||
|
||||
class SurfaceClient : public Singleton<SurfaceClient>
|
||||
{
|
||||
// all these attributes are constants
|
||||
sp<ISurfaceComposer> mComposerService;
|
||||
sp<ISurfaceComposerClient> mClient;
|
||||
status_t mStatus;
|
||||
SharedClient* mControl;
|
||||
sp<IMemoryHeap> mControlMemory;
|
||||
|
||||
SurfaceClient()
|
||||
: Singleton<SurfaceClient>(), mStatus(NO_INIT)
|
||||
{
|
||||
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
|
||||
mComposerService = sf;
|
||||
mClient = sf->createClientConnection();
|
||||
if (mClient != NULL) {
|
||||
mControlMemory = mClient->getControlBlock();
|
||||
if (mControlMemory != NULL) {
|
||||
mControl = static_cast<SharedClient *>(
|
||||
mControlMemory->getBase());
|
||||
if (mControl) {
|
||||
mStatus = NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
friend class Singleton<SurfaceClient>;
|
||||
public:
|
||||
status_t initCheck() const {
|
||||
return mStatus;
|
||||
}
|
||||
SharedClient* getSharedClient() const {
|
||||
return mControl;
|
||||
}
|
||||
ssize_t getTokenForSurface(const sp<ISurface>& sur) const {
|
||||
// TODO: we could cache a few tokens here to avoid an IPC
|
||||
return mClient->getTokenForSurface(sur);
|
||||
}
|
||||
void signalServer() const {
|
||||
mComposerService->signal();
|
||||
}
|
||||
};
|
||||
|
||||
ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Surface::Surface(const sp<SurfaceControl>& surface)
|
||||
: mBufferMapper(GraphicBufferMapper::get()),
|
||||
mClient(SurfaceClient::getInstance()),
|
||||
mSharedBufferClient(NULL),
|
||||
mInitCheck(NO_INIT),
|
||||
: mInitCheck(NO_INIT),
|
||||
mSurface(surface->mSurface),
|
||||
mIdentity(surface->mIdentity),
|
||||
mFormat(surface->mFormat), mFlags(surface->mFlags),
|
||||
|
@ -334,10 +287,7 @@ Surface::Surface(const sp<SurfaceControl>& surface)
|
|||
}
|
||||
|
||||
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
|
||||
: mBufferMapper(GraphicBufferMapper::get()),
|
||||
mClient(SurfaceClient::getInstance()),
|
||||
mSharedBufferClient(NULL),
|
||||
mInitCheck(NO_INIT)
|
||||
: mInitCheck(NO_INIT)
|
||||
{
|
||||
mSurface = interface_cast<ISurface>(ref);
|
||||
mIdentity = parcel.readInt32();
|
||||
|
@ -382,7 +332,6 @@ status_t Surface::writeToParcel(
|
|||
|
||||
}
|
||||
|
||||
|
||||
Mutex Surface::sCachedSurfacesLock;
|
||||
DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
|
||||
|
||||
|
@ -422,32 +371,29 @@ void Surface::init()
|
|||
ANativeWindow::query = query;
|
||||
ANativeWindow::perform = perform;
|
||||
|
||||
DisplayInfo dinfo;
|
||||
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
||||
const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
|
||||
const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
|
||||
// FIXME: set real values here
|
||||
const_cast<int&>(ANativeWindow::minSwapInterval) = 1;
|
||||
const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
|
||||
const_cast<uint32_t&>(ANativeWindow::flags) = 0;
|
||||
if (mSurface != NULL) {
|
||||
sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
|
||||
LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
|
||||
if (surfaceTexture != NULL) {
|
||||
mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
|
||||
mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER);
|
||||
}
|
||||
|
||||
mNextBufferTransform = 0;
|
||||
mConnected = 0;
|
||||
mSwapRectangle.makeInvalid();
|
||||
mNextBufferCrop = Rect(0,0);
|
||||
// two buffers by default
|
||||
mBuffers.setCapacity(2);
|
||||
mBuffers.insertAt(0, 2);
|
||||
DisplayInfo dinfo;
|
||||
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
||||
const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
|
||||
const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
|
||||
|
||||
if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
|
||||
int32_t token = mClient.getTokenForSurface(mSurface);
|
||||
if (token >= 0) {
|
||||
mSharedBufferClient = new SharedBufferClient(
|
||||
mClient.getSharedClient(), token, 2, mIdentity);
|
||||
mInitCheck = mClient.getSharedClient()->validate(token);
|
||||
} else {
|
||||
LOGW("Not initializing the shared buffer client because token = %d",
|
||||
token);
|
||||
const_cast<int&>(ANativeWindow::minSwapInterval) =
|
||||
mSurfaceTextureClient->minSwapInterval;
|
||||
|
||||
const_cast<int&>(ANativeWindow::maxSwapInterval) =
|
||||
mSurfaceTextureClient->maxSwapInterval;
|
||||
|
||||
const_cast<uint32_t&>(ANativeWindow::flags) = 0;
|
||||
|
||||
if (mSurfaceTextureClient != 0) {
|
||||
mInitCheck = NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -456,9 +402,8 @@ 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();
|
||||
mSurfaceTextureClient.clear();
|
||||
mSurface.clear();
|
||||
delete mSharedBufferClient;
|
||||
IPCThreadState::self()->flushCommands();
|
||||
}
|
||||
|
||||
|
@ -473,32 +418,6 @@ status_t Surface::validate(bool inCancelBuffer) const
|
|||
LOGE("invalid token (identity=%u)", mIdentity);
|
||||
return mInitCheck;
|
||||
}
|
||||
|
||||
// verify the identity of this surface
|
||||
uint32_t identity = mSharedBufferClient->getIdentity();
|
||||
if (mIdentity != identity) {
|
||||
LOGE("[Surface] using an invalid surface, "
|
||||
"identity=%u should be %d",
|
||||
mIdentity, identity);
|
||||
CallStack stack;
|
||||
stack.update();
|
||||
stack.dump("Surface");
|
||||
return BAD_INDEX;
|
||||
}
|
||||
|
||||
// check the surface didn't become invalid
|
||||
status_t err = mSharedBufferClient->getStatus();
|
||||
if (err != NO_ERROR) {
|
||||
if (!inCancelBuffer) {
|
||||
LOGE("surface (identity=%u) is invalid, err=%d (%s)",
|
||||
mIdentity, err, strerror(-err));
|
||||
CallStack stack;
|
||||
stack.update();
|
||||
stack.dump("Surface");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -509,7 +428,8 @@ sp<IBinder> Surface::asBinder() const {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::setSwapInterval(ANativeWindow* window, int interval) {
|
||||
return 0;
|
||||
Surface* self = getSelf(window);
|
||||
return self->setSwapInterval(interval);
|
||||
}
|
||||
|
||||
int Surface::dequeueBuffer(ANativeWindow* window,
|
||||
|
@ -554,383 +474,52 @@ int Surface::perform(ANativeWindow* 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::setSwapInterval(int interval) {
|
||||
return mSurfaceTextureClient->setSwapInterval(interval);
|
||||
}
|
||||
|
||||
int Surface::dequeueBuffer(ANativeWindowBuffer** buffer)
|
||||
{
|
||||
status_t err = validate();
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
GraphicLog& logger(GraphicLog::getInstance());
|
||||
logger.log(GraphicLog::SF_APP_DEQUEUE_BEFORE, mIdentity, -1);
|
||||
|
||||
ssize_t bufIdx = mSharedBufferClient->dequeue();
|
||||
|
||||
logger.log(GraphicLog::SF_APP_DEQUEUE_AFTER, mIdentity, bufIdx);
|
||||
|
||||
if (bufIdx < 0) {
|
||||
LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
|
||||
return 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) {
|
||||
status_t err = mSurfaceTextureClient->dequeueBuffer(buffer);
|
||||
if (err == NO_ERROR) {
|
||||
mDirtyRegion.set(backBuffer->width, backBuffer->height);
|
||||
*buffer = backBuffer.get();
|
||||
} else {
|
||||
mSharedBufferClient->undoDequeue(bufIdx);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int Surface::cancelBuffer(ANativeWindowBuffer* buffer)
|
||||
{
|
||||
status_t err = validate(true);
|
||||
switch (err) {
|
||||
case NO_ERROR:
|
||||
// no error, common case
|
||||
break;
|
||||
case BAD_INDEX:
|
||||
// legitimate errors here
|
||||
return err;
|
||||
default:
|
||||
// other errors happen because the surface is now invalid,
|
||||
// for instance because it has been destroyed. In this case,
|
||||
// we just fail silently (canceling a buffer is not technically
|
||||
// an error at this point)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
|
||||
|
||||
err = mSharedBufferClient->cancel(bufIdx);
|
||||
|
||||
LOGE_IF(err, "error canceling buffer %d (%s)", bufIdx, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int Surface::lockBuffer(ANativeWindowBuffer* buffer)
|
||||
{
|
||||
status_t err = validate();
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
|
||||
|
||||
GraphicLog& logger(GraphicLog::getInstance());
|
||||
logger.log(GraphicLog::SF_APP_LOCK_BEFORE, mIdentity, bufIdx);
|
||||
|
||||
err = mSharedBufferClient->lock(bufIdx);
|
||||
|
||||
logger.log(GraphicLog::SF_APP_LOCK_AFTER, mIdentity, bufIdx);
|
||||
|
||||
LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
int Surface::queueBuffer(ANativeWindowBuffer* buffer)
|
||||
{
|
||||
status_t err = validate();
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
if (mSwapRectangle.isValid()) {
|
||||
mDirtyRegion.set(mSwapRectangle);
|
||||
}
|
||||
|
||||
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
|
||||
|
||||
GraphicLog::getInstance().log(GraphicLog::SF_APP_QUEUE, mIdentity, bufIdx);
|
||||
|
||||
mSharedBufferClient->setTransform(bufIdx, mNextBufferTransform);
|
||||
mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop);
|
||||
mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
|
||||
err = mSharedBufferClient->queue(bufIdx);
|
||||
LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
// TODO: can we avoid this IPC if we know there is one pending?
|
||||
mClient.signalServer();
|
||||
mDirtyRegion.set(buffer[0]->width, buffer[0]->height);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int Surface::query(int what, int* value) const
|
||||
{
|
||||
int Surface::cancelBuffer(ANativeWindowBuffer* buffer) {
|
||||
return mSurfaceTextureClient->cancelBuffer(buffer);
|
||||
}
|
||||
|
||||
int Surface::lockBuffer(ANativeWindowBuffer* buffer) {
|
||||
return mSurfaceTextureClient->lockBuffer(buffer);
|
||||
}
|
||||
|
||||
int Surface::queueBuffer(ANativeWindowBuffer* buffer) {
|
||||
return mSurfaceTextureClient->queueBuffer(buffer);
|
||||
}
|
||||
|
||||
int Surface::query(int what, int* value) const {
|
||||
switch (what) {
|
||||
case NATIVE_WINDOW_WIDTH:
|
||||
*value = int(mWidth);
|
||||
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
|
||||
// TODO: this is not needed anymore
|
||||
*value = 1;
|
||||
return NO_ERROR;
|
||||
case NATIVE_WINDOW_HEIGHT:
|
||||
*value = int(mHeight);
|
||||
return NO_ERROR;
|
||||
case NATIVE_WINDOW_FORMAT:
|
||||
*value = int(mFormat);
|
||||
return NO_ERROR;
|
||||
case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
|
||||
*value = MIN_UNDEQUEUED_BUFFERS;
|
||||
return NO_ERROR;
|
||||
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
|
||||
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
|
||||
*value = sf->authenticateSurface(mSurface) ? 1 : 0;
|
||||
return NO_ERROR;
|
||||
}
|
||||
case NATIVE_WINDOW_CONCRETE_TYPE:
|
||||
// TODO: this is not needed anymore
|
||||
*value = NATIVE_WINDOW_SURFACE;
|
||||
return NO_ERROR;
|
||||
}
|
||||
return BAD_VALUE;
|
||||
return mSurfaceTextureClient->query(what, value);
|
||||
}
|
||||
|
||||
int Surface::perform(int operation, va_list args)
|
||||
{
|
||||
status_t err = validate();
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
int res = NO_ERROR;
|
||||
switch (operation) {
|
||||
case NATIVE_WINDOW_SET_USAGE:
|
||||
dispatch_setUsage( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_CONNECT:
|
||||
res = dispatch_connect( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_DISCONNECT:
|
||||
res = dispatch_disconnect( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_CROP:
|
||||
res = dispatch_crop( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_BUFFER_COUNT:
|
||||
res = dispatch_set_buffer_count( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
|
||||
res = dispatch_set_buffers_geometry( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
|
||||
res = dispatch_set_buffers_transform( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
|
||||
res = dispatch_set_buffers_timestamp( args );
|
||||
break;
|
||||
default:
|
||||
res = NAME_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Surface::dispatch_setUsage(va_list args) {
|
||||
int usage = va_arg(args, int);
|
||||
setUsage( usage );
|
||||
}
|
||||
int Surface::dispatch_connect(va_list args) {
|
||||
int api = va_arg(args, int);
|
||||
return connect( api );
|
||||
}
|
||||
int Surface::dispatch_disconnect(va_list args) {
|
||||
int api = va_arg(args, int);
|
||||
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) );
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
int Surface::dispatch_set_buffers_transform(va_list args) {
|
||||
int transform = va_arg(args, int);
|
||||
return setBuffersTransform(transform);
|
||||
}
|
||||
|
||||
int Surface::dispatch_set_buffers_timestamp(va_list args) {
|
||||
int64_t timestamp = va_arg(args, int64_t);
|
||||
return setBuffersTimestamp(timestamp);
|
||||
}
|
||||
|
||||
void Surface::setUsage(uint32_t reqUsage)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
mBufferInfo.set(reqUsage);
|
||||
}
|
||||
|
||||
int Surface::connect(int api)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
int err = NO_ERROR;
|
||||
switch (api) {
|
||||
case NATIVE_WINDOW_API_EGL:
|
||||
if (mConnected) {
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
mConnected = api;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int Surface::disconnect(int api)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
int err = NO_ERROR;
|
||||
switch (api) {
|
||||
case NATIVE_WINDOW_API_EGL:
|
||||
if (mConnected == api) {
|
||||
mConnected = 0;
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int Surface::crop(Rect const* rect)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
// TODO: validate rect size
|
||||
|
||||
if (rect == NULL || rect->isEmpty()) {
|
||||
mNextBufferCrop = Rect(0,0);
|
||||
} else {
|
||||
mNextBufferCrop = *rect;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int Surface::setBufferCount(int bufferCount)
|
||||
{
|
||||
sp<ISurface> s(mSurface);
|
||||
if (s == 0) return NO_INIT;
|
||||
|
||||
class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
|
||||
sp<ISurface> surface;
|
||||
virtual status_t operator()(int bufferCount) const {
|
||||
return surface->setBufferCount(bufferCount);
|
||||
}
|
||||
public:
|
||||
SetBufferCountIPC(const sp<ISurface>& surface) : surface(surface) { }
|
||||
} ipc(s);
|
||||
|
||||
status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc);
|
||||
LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
|
||||
bufferCount, strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
// Clear out any references to the old buffers.
|
||||
mBuffers.clear();
|
||||
}
|
||||
|
||||
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);
|
||||
if (mConnected == NATIVE_WINDOW_API_EGL) {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
mBufferInfo.set(w, h, format);
|
||||
if (format != 0) {
|
||||
// we update the format of the surface as reported by query().
|
||||
// this is to allow applications to change the format of a surface's
|
||||
// buffer, and have it reflected in EGL; which is needed for
|
||||
// EGLConfig validation.
|
||||
mFormat = format;
|
||||
}
|
||||
|
||||
mNextBufferCrop = Rect(0,0);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int Surface::setBuffersTransform(int transform)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
mNextBufferTransform = transform;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int Surface::setBuffersTimestamp(int64_t timestamp)
|
||||
{
|
||||
// Surface doesn't really have anything meaningful to do with timestamps
|
||||
// so they'll just be dropped here.
|
||||
return NO_ERROR;
|
||||
int Surface::perform(int operation, va_list args) {
|
||||
return mSurfaceTextureClient->perform(operation, args);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::getConnectedApi() const
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
return mConnected;
|
||||
int Surface::getConnectedApi() const {
|
||||
return mSurfaceTextureClient->getConnectedApi();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -967,16 +556,17 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
|
|||
}
|
||||
|
||||
// we're intending to do software rendering from this point
|
||||
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
||||
mSurfaceTextureClient->setUsage(
|
||||
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
||||
|
||||
ANativeWindowBuffer* out;
|
||||
status_t err = dequeueBuffer(&out);
|
||||
status_t err = mSurfaceTextureClient->dequeueBuffer(&out);
|
||||
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
|
||||
if (err == NO_ERROR) {
|
||||
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
|
||||
err = lockBuffer(backBuffer.get());
|
||||
LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
|
||||
getBufferIndex(backBuffer), strerror(-err));
|
||||
err = mSurfaceTextureClient->lockBuffer(backBuffer.get());
|
||||
LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
|
||||
backBuffer->handle, strerror(-err));
|
||||
if (err == NO_ERROR) {
|
||||
const Rect bounds(backBuffer->width, backBuffer->height);
|
||||
const Region boundsRegion(bounds);
|
||||
|
@ -1043,110 +633,14 @@ status_t Surface::unlockAndPost()
|
|||
status_t err = mLockedBuffer->unlock();
|
||||
LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
|
||||
|
||||
err = queueBuffer(mLockedBuffer.get());
|
||||
LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
|
||||
getBufferIndex(mLockedBuffer), strerror(-err));
|
||||
err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get());
|
||||
LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
|
||||
mLockedBuffer->handle, strerror(-err));
|
||||
|
||||
mPostedBuffer = mLockedBuffer;
|
||||
mLockedBuffer = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
void Surface::setSwapRectangle(const Rect& r) {
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
mSwapRectangle = r;
|
||||
}
|
||||
|
||||
int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
|
||||
{
|
||||
int idx = buffer->getIndex();
|
||||
if (idx < 0) {
|
||||
// The buffer doesn't have an index set. See if the handle the same as
|
||||
// one of the buffers for which we do know the index. This can happen
|
||||
// e.g. if GraphicBuffer is used to wrap an ANativeWindowBuffer that
|
||||
// was dequeued from an ANativeWindow.
|
||||
for (size_t i = 0; i < mBuffers.size(); i++) {
|
||||
if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) {
|
||||
idx = mBuffers[i]->getIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
status_t err = NO_MEMORY;
|
||||
|
||||
// free the current buffer
|
||||
sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
|
||||
if (currentBuffer != 0) {
|
||||
currentBuffer.clear();
|
||||
}
|
||||
|
||||
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 always happen by construction
|
||||
LOGE_IF(buffer->handle == NULL,
|
||||
"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) {
|
||||
currentBuffer = buffer;
|
||||
currentBuffer->setIndex(index);
|
||||
} else {
|
||||
err = err<0 ? err : status_t(NO_MEMORY);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
|
|
@ -20,19 +20,20 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Singleton.h>
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <binder/IMemory.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
|
||||
#include <surfaceflinger/ISurface.h>
|
||||
#include <surfaceflinger/ISurfaceComposer.h>
|
||||
#include <surfaceflinger/ISurfaceComposerClient.h>
|
||||
#include <surfaceflinger/ISurface.h>
|
||||
#include <surfaceflinger/SurfaceComposerClient.h>
|
||||
|
||||
#include <private/surfaceflinger/LayerState.h>
|
||||
|
@ -217,7 +218,7 @@ void SurfaceComposerClient::dispose()
|
|||
status_t SurfaceComposerClient::getDisplayInfo(
|
||||
DisplayID dpy, DisplayInfo* info)
|
||||
{
|
||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
||||
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||
return BAD_VALUE;
|
||||
|
||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||
|
@ -235,7 +236,7 @@ status_t SurfaceComposerClient::getDisplayInfo(
|
|||
|
||||
ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
|
||||
{
|
||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
||||
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||
return BAD_VALUE;
|
||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
|
||||
|
@ -244,7 +245,7 @@ ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
|
|||
|
||||
ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
|
||||
{
|
||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
||||
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||
return BAD_VALUE;
|
||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
|
||||
|
@ -253,7 +254,7 @@ ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
|
|||
|
||||
ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
|
||||
{
|
||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
||||
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||
return BAD_VALUE;
|
||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
|
||||
|
|
|
@ -181,6 +181,12 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
|
|||
int SurfaceTextureClient::query(int what, int* value) const {
|
||||
LOGV("SurfaceTextureClient::query");
|
||||
switch (what) {
|
||||
case NATIVE_WINDOW_FORMAT:
|
||||
if (mReqFormat) {
|
||||
*value = mReqFormat;
|
||||
return NO_ERROR;
|
||||
}
|
||||
break;
|
||||
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
|
||||
// TODO: this is not needed anymore
|
||||
*value = 0;
|
||||
|
|
|
@ -2,18 +2,18 @@ LOCAL_PATH:= $(call my-dir)
|
|||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
clz.cpp.arm \
|
||||
DisplayHardware/DisplayHardware.cpp \
|
||||
Layer.cpp \
|
||||
LayerBase.cpp \
|
||||
LayerDim.cpp \
|
||||
DisplayHardware/DisplayHardware.cpp \
|
||||
DisplayHardware/DisplayHardwareBase.cpp \
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
GLExtensions.cpp \
|
||||
Layer.cpp \
|
||||
LayerBase.cpp \
|
||||
LayerDim.cpp \
|
||||
MessageQueue.cpp \
|
||||
SurfaceFlinger.cpp \
|
||||
TextureManager.cpp \
|
||||
Transform.cpp
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
GLExtensions.cpp \
|
||||
MessageQueue.cpp \
|
||||
SurfaceFlinger.cpp \
|
||||
SurfaceTextureLayer.cpp \
|
||||
Transform.cpp \
|
||||
|
||||
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,9 +20,11 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <gui/SurfaceTexture.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
@ -30,8 +32,8 @@
|
|||
#include <GLES/glext.h>
|
||||
|
||||
#include "LayerBase.h"
|
||||
#include "SurfaceTextureLayer.h"
|
||||
#include "Transform.h"
|
||||
#include "TextureManager.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
|
@ -40,7 +42,6 @@ namespace android {
|
|||
class FreezeLock;
|
||||
class Client;
|
||||
class GLExtensions;
|
||||
class UserClient;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -58,164 +59,59 @@ public:
|
|||
status_t setBuffers(uint32_t w, uint32_t h,
|
||||
PixelFormat format, uint32_t flags=0);
|
||||
|
||||
// associate a UserClient to this Layer
|
||||
status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
|
||||
int32_t getToken() const;
|
||||
sp<UserClient> getClient() const;
|
||||
|
||||
// Set this Layer's buffers size
|
||||
void setBufferSize(uint32_t w, uint32_t h);
|
||||
bool isFixedSize() const;
|
||||
|
||||
// LayerBase interface
|
||||
virtual void setGeometry(hwc_layer_t* hwcl);
|
||||
virtual void setPerFrameData(hwc_layer_t* hwcl);
|
||||
virtual void drawForSreenShot() const;
|
||||
virtual void onDraw(const Region& clip) const;
|
||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||
virtual void lockPageFlip(bool& recomputeVisibleRegions);
|
||||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
||||
virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const;
|
||||
virtual bool needsBlending() const;
|
||||
virtual bool isOpaque() const;
|
||||
virtual bool needsDithering() const { return mNeedsDithering; }
|
||||
virtual bool needsFiltering() const;
|
||||
virtual bool isSecure() const { return mSecure; }
|
||||
virtual bool isProtected() const;
|
||||
virtual sp<Surface> createSurface() const;
|
||||
virtual void onRemoved();
|
||||
|
||||
// only for debugging
|
||||
inline sp<GraphicBuffer> getBuffer(int i) const {
|
||||
return mBufferManager.getBuffer(i); }
|
||||
// only for debugging
|
||||
inline const sp<FreezeLock>& getFreezeLock() const {
|
||||
return mFreezeLock; }
|
||||
inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
|
||||
|
||||
protected:
|
||||
virtual void destroy() const;
|
||||
virtual void onFirstRef();
|
||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||
|
||||
private:
|
||||
void reloadTexture(const Region& dirty);
|
||||
friend class SurfaceTextureLayer;
|
||||
void onFrameQueued();
|
||||
virtual sp<ISurface> createSurface();
|
||||
uint32_t getEffectiveUsage(uint32_t usage) const;
|
||||
sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||
status_t setBufferCount(int bufferCount);
|
||||
void setFixedSize(bool fixedSize);
|
||||
bool isCropped() const;
|
||||
static bool getOpacityForFormat(uint32_t format);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
class SurfaceLayer : public LayerBaseClient::Surface {
|
||||
public:
|
||||
SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner);
|
||||
~SurfaceLayer();
|
||||
private:
|
||||
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());
|
||||
}
|
||||
};
|
||||
friend class SurfaceLayer;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
class ClientRef {
|
||||
ClientRef(const ClientRef& rhs);
|
||||
ClientRef& operator = (const ClientRef& rhs);
|
||||
mutable Mutex mLock;
|
||||
// binder thread, page-flip thread
|
||||
sp<SharedBufferServer> mControlBlock;
|
||||
wp<UserClient> mUserClient;
|
||||
int32_t mToken;
|
||||
public:
|
||||
ClientRef();
|
||||
~ClientRef();
|
||||
int32_t getToken() const;
|
||||
sp<UserClient> getClient() const;
|
||||
status_t setToken(const sp<UserClient>& uc,
|
||||
const sp<SharedBufferServer>& sharedClient, int32_t token);
|
||||
sp<UserClient> getUserClientUnsafe() const;
|
||||
class Access {
|
||||
Access(const Access& rhs);
|
||||
Access& operator = (const Access& rhs);
|
||||
sp<UserClient> mUserClientStrongRef;
|
||||
sp<SharedBufferServer> mControlBlock;
|
||||
public:
|
||||
Access(const ClientRef& ref);
|
||||
~Access();
|
||||
inline SharedBufferServer* get() const { return mControlBlock.get(); }
|
||||
};
|
||||
friend class Access;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
class BufferManager {
|
||||
static const size_t NUM_BUFFERS = 2;
|
||||
struct BufferData {
|
||||
sp<GraphicBuffer> buffer;
|
||||
Image texture;
|
||||
};
|
||||
// this lock protect mBufferData[].buffer but since there
|
||||
// is very little contention, we have only one like for
|
||||
// the whole array, we also use it to protect mNumBuffers.
|
||||
mutable Mutex mLock;
|
||||
BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX];
|
||||
size_t mNumBuffers;
|
||||
Texture mFailoverTexture;
|
||||
TextureManager& mTextureManager;
|
||||
ssize_t mActiveBufferIndex;
|
||||
sp<GraphicBuffer> mActiveBuffer;
|
||||
bool mFailover;
|
||||
static status_t destroyTexture(Image* tex, EGLDisplay dpy);
|
||||
|
||||
public:
|
||||
static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
|
||||
BufferManager(TextureManager& tm);
|
||||
~BufferManager();
|
||||
|
||||
// detach/attach buffer from/to given index
|
||||
sp<GraphicBuffer> detachBuffer(size_t index);
|
||||
status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
|
||||
// resize the number of active buffers
|
||||
status_t resize(size_t size, const sp<SurfaceFlinger>& flinger,
|
||||
EGLDisplay dpy);
|
||||
|
||||
// ----------------------------------------------
|
||||
// must be called from GL thread
|
||||
|
||||
// set/get active buffer index
|
||||
status_t setActiveBufferIndex(size_t index);
|
||||
size_t getActiveBufferIndex() const;
|
||||
// return the active buffer
|
||||
sp<GraphicBuffer> getActiveBuffer() const;
|
||||
// return wether we have an active buffer
|
||||
bool hasActiveBuffer() const;
|
||||
// return the active texture (or fail-over)
|
||||
Texture getActiveTexture() const;
|
||||
// frees resources associated with all buffers
|
||||
status_t destroy(EGLDisplay dpy);
|
||||
// load bitmap data into the active buffer
|
||||
status_t loadTexture(const Region& dirty, const GGLSurface& t);
|
||||
// make active buffer an EGLImage if needed
|
||||
status_t initEglImage(EGLDisplay dpy,
|
||||
const sp<GraphicBuffer>& buffer);
|
||||
|
||||
// ----------------------------------------------
|
||||
// only for debugging
|
||||
sp<GraphicBuffer> getBuffer(size_t index) const;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// constants
|
||||
sp<SurfaceTextureLayer> mSurfaceTexture;
|
||||
GLuint mTextureName;
|
||||
|
||||
// thread-safe
|
||||
ClientRef mUserClientRef;
|
||||
volatile int32_t mQueuedFrames;
|
||||
|
||||
// main thread
|
||||
sp<GraphicBuffer> mActiveBuffer;
|
||||
GLfloat mTextureMatrix[16];
|
||||
Rect mCurrentCrop;
|
||||
uint32_t mCurrentTransform;
|
||||
bool mCurrentOpacity;
|
||||
|
||||
// constants
|
||||
PixelFormat mFormat;
|
||||
const GLExtensions& mGLExtensions;
|
||||
bool mNeedsBlending;
|
||||
bool mOpaqueLayer;
|
||||
bool mNeedsDithering;
|
||||
|
||||
// page-flip thread (currently main thread)
|
||||
|
@ -226,18 +122,8 @@ private:
|
|||
// page-flip thread and transaction thread (currently main thread)
|
||||
sp<FreezeLock> mFreezeLock;
|
||||
|
||||
// see threading usage in declaration
|
||||
TextureManager mTextureManager;
|
||||
BufferManager mBufferManager;
|
||||
|
||||
// binder thread, transaction thread
|
||||
mutable Mutex mLock;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mReqWidth;
|
||||
uint32_t mReqHeight;
|
||||
uint32_t mReqFormat;
|
||||
bool mNeedsScaling;
|
||||
bool mFixedSize;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#include "LayerBase.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "TextureManager.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
|
@ -44,7 +42,7 @@ int32_t LayerBase::sSequence = 1;
|
|||
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
||||
: dpy(display), contentDirty(false),
|
||||
sequence(uint32_t(android_atomic_inc(&sSequence))),
|
||||
mFlinger(flinger),
|
||||
mFlinger(flinger), mFiltering(false),
|
||||
mNeedsFiltering(false),
|
||||
mOrientation(0),
|
||||
mLeft(0), mTop(0),
|
||||
|
@ -54,8 +52,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
|||
{
|
||||
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
||||
mFlags = hw.getFlags();
|
||||
mBufferCrop.makeInvalid();
|
||||
mBufferTransform = 0;
|
||||
}
|
||||
|
||||
LayerBase::~LayerBase()
|
||||
|
@ -310,6 +306,16 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
|
|||
hwcl->handle = NULL;
|
||||
}
|
||||
|
||||
void LayerBase::setFiltering(bool filtering)
|
||||
{
|
||||
mFiltering = filtering;
|
||||
}
|
||||
|
||||
bool LayerBase::getFiltering() const
|
||||
{
|
||||
return mFiltering;
|
||||
}
|
||||
|
||||
void LayerBase::draw(const Region& clip) const
|
||||
{
|
||||
// reset GL state
|
||||
|
@ -318,10 +324,12 @@ void LayerBase::draw(const Region& clip) const
|
|||
onDraw(clip);
|
||||
}
|
||||
|
||||
void LayerBase::drawForSreenShot() const
|
||||
void LayerBase::drawForSreenShot()
|
||||
{
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
setFiltering(true);
|
||||
onDraw( Region(hw.bounds()) );
|
||||
setFiltering(false);
|
||||
}
|
||||
|
||||
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
|
||||
|
@ -332,8 +340,12 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
|
|||
const uint32_t fbHeight = hw.getHeight();
|
||||
glColor4f(red,green,blue,alpha);
|
||||
|
||||
TextureManager::deactivateTextures();
|
||||
|
||||
#if defined(GL_OES_EGL_image_external)
|
||||
if (GLExtensions::getInstance().haveTextureExternal()) {
|
||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
}
|
||||
#endif
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DITHER);
|
||||
|
||||
|
@ -354,24 +366,11 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
|
|||
clearWithOpenGL(clip,0,0,0,0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline
|
||||
void swap(T& a, T& b) {
|
||||
T t(a);
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
||||
void LayerBase::drawWithOpenGL(const Region& clip) const
|
||||
{
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
const uint32_t fbHeight = hw.getHeight();
|
||||
const State& s(drawingState());
|
||||
|
||||
// bind our texture
|
||||
TextureManager::activateTexture(texture, needsFiltering());
|
||||
uint32_t width = texture.width;
|
||||
uint32_t height = texture.height;
|
||||
|
||||
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
||||
if (UNLIKELY(s.alpha < 0xFF)) {
|
||||
|
@ -387,7 +386,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
|||
} else {
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
if (needsBlending()) {
|
||||
if (!isOpaque()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
|
@ -395,86 +394,20 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* compute texture coordinates
|
||||
* here, we handle NPOT, cropping and buffer transformations
|
||||
*/
|
||||
|
||||
GLfloat cl, ct, cr, cb;
|
||||
if (!mBufferCrop.isEmpty()) {
|
||||
// source is cropped
|
||||
const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width;
|
||||
const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height;
|
||||
cl = mBufferCrop.left * us;
|
||||
ct = mBufferCrop.top * vs;
|
||||
cr = mBufferCrop.right * us;
|
||||
cb = mBufferCrop.bottom * vs;
|
||||
} else {
|
||||
cl = 0;
|
||||
ct = 0;
|
||||
cr = (texture.NPOTAdjust ? texture.wScale : 1.0f);
|
||||
cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
* For the buffer transformation, we apply the rotation last.
|
||||
* Since we're transforming the texture-coordinates, we need
|
||||
* to apply the inverse of the buffer transformation:
|
||||
* inverse( FLIP_V -> FLIP_H -> ROT_90 )
|
||||
* <=> inverse( ROT_90 * FLIP_H * FLIP_V )
|
||||
* = inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90)
|
||||
* = FLIP_V * FLIP_H * ROT_270
|
||||
* <=> ROT_270 -> FLIP_H -> FLIP_V
|
||||
*
|
||||
* The rotation is performed first, in the texture coordinate space.
|
||||
*
|
||||
*/
|
||||
|
||||
struct TexCoords {
|
||||
GLfloat u;
|
||||
GLfloat v;
|
||||
};
|
||||
|
||||
enum {
|
||||
// name of the corners in the texture map
|
||||
LB = 0, // left-bottom
|
||||
LT = 1, // left-top
|
||||
RT = 2, // right-top
|
||||
RB = 3 // right-bottom
|
||||
};
|
||||
|
||||
// vertices in screen space
|
||||
int vLT = LB;
|
||||
int vLB = LT;
|
||||
int vRB = RT;
|
||||
int vRT = RB;
|
||||
|
||||
// the texture's source is rotated
|
||||
uint32_t transform = mBufferTransform;
|
||||
if (transform & HAL_TRANSFORM_ROT_90) {
|
||||
vLT = RB;
|
||||
vLB = LB;
|
||||
vRB = LT;
|
||||
vRT = RT;
|
||||
}
|
||||
if (transform & HAL_TRANSFORM_FLIP_V) {
|
||||
swap(vLT, vLB);
|
||||
swap(vRT, vRB);
|
||||
}
|
||||
if (transform & HAL_TRANSFORM_FLIP_H) {
|
||||
swap(vLT, vRT);
|
||||
swap(vLB, vRB);
|
||||
}
|
||||
|
||||
TexCoords texCoords[4];
|
||||
texCoords[vLT].u = cl;
|
||||
texCoords[vLT].v = ct;
|
||||
texCoords[vLB].u = cl;
|
||||
texCoords[vLB].v = cb;
|
||||
texCoords[vRB].u = cr;
|
||||
texCoords[vRB].v = cb;
|
||||
texCoords[vRT].u = cr;
|
||||
texCoords[vRT].v = ct;
|
||||
texCoords[0].u = 0;
|
||||
texCoords[0].v = 1;
|
||||
texCoords[1].u = 0;
|
||||
texCoords[1].v = 0;
|
||||
texCoords[2].u = 1;
|
||||
texCoords[2].v = 0;
|
||||
texCoords[3].u = 1;
|
||||
texCoords[3].v = 1;
|
||||
|
||||
if (needsDithering()) {
|
||||
glEnable(GL_DITHER);
|
||||
|
@ -497,20 +430,6 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
|||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
void LayerBase::setBufferCrop(const Rect& crop) {
|
||||
if (mBufferCrop != crop) {
|
||||
mBufferCrop = crop;
|
||||
mFlinger->invalidateHwcGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerBase::setBufferTransform(uint32_t transform) {
|
||||
if (mBufferTransform != transform) {
|
||||
mBufferTransform = transform;
|
||||
mFlinger->invalidateHwcGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
const Layer::State& s(drawingState());
|
||||
|
@ -518,10 +437,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
|||
"+ %s %p\n"
|
||||
" "
|
||||
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
|
||||
"needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
|
||||
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
|
||||
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
|
||||
getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
|
||||
needsBlending(), needsDithering(), contentDirty,
|
||||
isOpaque(), needsDithering(), contentDirty,
|
||||
s.alpha, s.flags,
|
||||
s.transform[0][0], s.transform[0][1],
|
||||
s.transform[1][0], s.transform[1][1]);
|
||||
|
@ -555,9 +474,22 @@ LayerBaseClient::~LayerBaseClient()
|
|||
}
|
||||
}
|
||||
|
||||
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
|
||||
sp<ISurface> LayerBaseClient::createSurface()
|
||||
{
|
||||
sp<Surface> s;
|
||||
class BSurface : public BnSurface, public LayerCleaner {
|
||||
virtual sp<ISurfaceTexture> getSurfaceTexture() const { return 0; }
|
||||
public:
|
||||
BSurface(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<LayerBaseClient>& layer)
|
||||
: LayerCleaner(flinger, layer) { }
|
||||
};
|
||||
sp<ISurface> sur(new BSurface(mFlinger, this));
|
||||
return sur;
|
||||
}
|
||||
|
||||
sp<ISurface> LayerBaseClient::getSurface()
|
||||
{
|
||||
sp<ISurface> s;
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mHasSurface,
|
||||
|
@ -573,12 +505,6 @@ wp<IBinder> LayerBaseClient::getSurfaceBinder() const {
|
|||
return mClientSurfaceBinder;
|
||||
}
|
||||
|
||||
sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
|
||||
{
|
||||
return new Surface(mFlinger, mIdentity,
|
||||
const_cast<LayerBaseClient *>(this));
|
||||
}
|
||||
|
||||
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
LayerBase::dump(result, buffer, SIZE);
|
||||
|
@ -601,44 +527,14 @@ void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) con
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerBaseClient::Surface::Surface(
|
||||
const sp<SurfaceFlinger>& flinger,
|
||||
int identity,
|
||||
const sp<LayerBaseClient>& owner)
|
||||
: mFlinger(flinger), mIdentity(identity), mOwner(owner)
|
||||
{
|
||||
LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<LayerBaseClient>& layer)
|
||||
: mFlinger(flinger), mLayer(layer) {
|
||||
}
|
||||
|
||||
LayerBaseClient::Surface::~Surface()
|
||||
{
|
||||
/*
|
||||
* This is a good place to clean-up all client resources
|
||||
*/
|
||||
|
||||
LayerBaseClient::LayerCleaner::~LayerCleaner() {
|
||||
// destroy client resources
|
||||
mFlinger->destroySurface(mOwner);
|
||||
}
|
||||
|
||||
sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
|
||||
sp<LayerBaseClient> owner(mOwner.promote());
|
||||
return owner;
|
||||
}
|
||||
|
||||
status_t LayerBaseClient::Surface::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
return BnSurface::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_t LayerBaseClient::Surface::setBufferCount(int bufferCount)
|
||||
{
|
||||
return INVALID_OPERATION;
|
||||
mFlinger->destroySurface(mLayer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <ui/Region.h>
|
||||
|
||||
#include <surfaceflinger/ISurfaceComposerClient.h>
|
||||
#include <private/surfaceflinger/SharedBufferStack.h>
|
||||
#include <private/surfaceflinger/LayerState.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
@ -43,13 +42,12 @@ namespace android {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class DisplayHardware;
|
||||
class Client;
|
||||
class DisplayHardware;
|
||||
class GraphicBuffer;
|
||||
class GraphicPlane;
|
||||
class LayerBaseClient;
|
||||
class SurfaceFlinger;
|
||||
class Texture;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -121,7 +119,7 @@ public:
|
|||
* to perform the actual drawing.
|
||||
*/
|
||||
virtual void draw(const Region& clip) const;
|
||||
virtual void drawForSreenShot() const;
|
||||
virtual void drawForSreenShot();
|
||||
|
||||
/**
|
||||
* onDraw - draws the surface.
|
||||
|
@ -174,9 +172,9 @@ public:
|
|||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
||||
|
||||
/**
|
||||
* needsBlending - true if this surface needs blending
|
||||
* isOpaque - true if this surface is opaque
|
||||
*/
|
||||
virtual bool needsBlending() const { return false; }
|
||||
virtual bool isOpaque() const { return true; }
|
||||
|
||||
/**
|
||||
* needsDithering - true if this surface needs dithering
|
||||
|
@ -184,11 +182,9 @@ public:
|
|||
virtual bool needsDithering() const { return false; }
|
||||
|
||||
/**
|
||||
* needsLinearFiltering - true if this surface needs filtering
|
||||
* needsLinearFiltering - true if this surface's state requires filtering
|
||||
*/
|
||||
virtual bool needsFiltering() const {
|
||||
return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
|
||||
}
|
||||
virtual bool needsFiltering() const { return mNeedsFiltering; }
|
||||
|
||||
/**
|
||||
* isSecure - true if this surface is secure, that is if it prevents
|
||||
|
@ -231,21 +227,25 @@ protected:
|
|||
void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
|
||||
GLclampf b, GLclampf alpha) const;
|
||||
void clearWithOpenGL(const Region& clip) const;
|
||||
void drawWithOpenGL(const Region& clip, const Texture& texture) const;
|
||||
|
||||
// these must be called from the post/drawing thread
|
||||
void setBufferCrop(const Rect& crop);
|
||||
void setBufferTransform(uint32_t transform);
|
||||
void drawWithOpenGL(const Region& clip) const;
|
||||
|
||||
void setFiltering(bool filtering);
|
||||
bool getFiltering() const;
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
uint32_t mFlags;
|
||||
|
||||
// post/drawing thread
|
||||
Rect mBufferCrop;
|
||||
uint32_t mBufferTransform;
|
||||
private:
|
||||
// accessed only in the main thread
|
||||
// Whether filtering is forced on or not
|
||||
bool mFiltering;
|
||||
|
||||
// cached during validateVisibility()
|
||||
// Whether filtering is needed b/c of the drawingstate
|
||||
bool mNeedsFiltering;
|
||||
|
||||
protected:
|
||||
// cached during validateVisibility()
|
||||
int32_t mOrientation;
|
||||
GLfloat mVertices[4][2];
|
||||
Rect mTransformedBounds;
|
||||
|
@ -281,52 +281,38 @@ private:
|
|||
class LayerBaseClient : public LayerBase
|
||||
{
|
||||
public:
|
||||
class Surface;
|
||||
|
||||
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
||||
const sp<Client>& client);
|
||||
virtual ~LayerBaseClient();
|
||||
|
||||
sp<Surface> getSurface();
|
||||
virtual ~LayerBaseClient();
|
||||
|
||||
sp<ISurface> getSurface();
|
||||
wp<IBinder> getSurfaceBinder() const;
|
||||
virtual sp<Surface> createSurface() const;
|
||||
|
||||
virtual sp<LayerBaseClient> getLayerBaseClient() const {
|
||||
return const_cast<LayerBaseClient*>(this); }
|
||||
|
||||
virtual const char* getTypeId() const { return "LayerBaseClient"; }
|
||||
|
||||
uint32_t getIdentity() const { return mIdentity; }
|
||||
|
||||
class Surface : public BnSurface {
|
||||
public:
|
||||
int32_t getIdentity() const { return mIdentity; }
|
||||
|
||||
protected:
|
||||
Surface(const sp<SurfaceFlinger>& flinger, int identity,
|
||||
const sp<LayerBaseClient>& owner);
|
||||
virtual ~Surface();
|
||||
virtual status_t onTransact(uint32_t code, const Parcel& data,
|
||||
Parcel* reply, uint32_t flags);
|
||||
sp<LayerBaseClient> getOwner() const;
|
||||
|
||||
private:
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||
virtual status_t setBufferCount(int bufferCount);
|
||||
|
||||
protected:
|
||||
friend class LayerBaseClient;
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
int32_t mIdentity;
|
||||
wp<LayerBaseClient> mOwner;
|
||||
};
|
||||
|
||||
friend class Surface;
|
||||
|
||||
protected:
|
||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||
virtual void shortDump(String8& result, char* scratch, size_t size) const;
|
||||
|
||||
class LayerCleaner {
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
wp<LayerBaseClient> mLayer;
|
||||
protected:
|
||||
~LayerCleaner();
|
||||
public:
|
||||
LayerCleaner(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<LayerBaseClient>& layer);
|
||||
};
|
||||
|
||||
private:
|
||||
virtual sp<ISurface> createSurface();
|
||||
|
||||
mutable Mutex mLock;
|
||||
mutable bool mHasSurface;
|
||||
wp<IBinder> mClientSurfaceBinder;
|
||||
|
|
|
@ -65,8 +65,6 @@ void LayerDim::onDraw(const Region& clip) const
|
|||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
}
|
||||
#endif
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
||||
|
||||
while (it != end) {
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
virtual ~LayerDim();
|
||||
|
||||
virtual void onDraw(const Region& clip) const;
|
||||
virtual bool needsBlending() const { return true; }
|
||||
virtual bool isOpaque() const { return false; }
|
||||
virtual bool isSecure() const { return false; }
|
||||
virtual bool isProtectedByApp() const { return false; }
|
||||
virtual bool isProtectedByDRM() const { return false; }
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "DisplayHardware/HWComposer.h"
|
||||
|
||||
#include <private/surfaceflinger/SharedBufferStack.h>
|
||||
|
||||
/* ideally AID_GRAPHICS would be in a semi-public header
|
||||
* or there would be a way to map a user/group name to its id
|
||||
*/
|
||||
|
@ -133,17 +135,6 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
|
|||
return bclient;
|
||||
}
|
||||
|
||||
sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection()
|
||||
{
|
||||
sp<ISurfaceComposerClient> bclient;
|
||||
sp<UserClient> client(new UserClient(this));
|
||||
status_t err = client->initCheck();
|
||||
if (err == NO_ERROR) {
|
||||
bclient = client;
|
||||
}
|
||||
return bclient;
|
||||
}
|
||||
|
||||
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
|
||||
{
|
||||
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
|
||||
|
@ -322,11 +313,6 @@ void SurfaceFlinger::signalEvent() {
|
|||
mEventQueue.invalidate();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signal() const {
|
||||
// this is the IPC call
|
||||
const_cast<SurfaceFlinger*>(this)->signalEvent();
|
||||
}
|
||||
|
||||
bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
sp<IBinder> surfBinder(surface->asBinder());
|
||||
|
@ -658,7 +644,7 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
|
||||
// handle hidden surfaces by setting the visible region to empty
|
||||
if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
|
||||
const bool translucent = layer->needsBlending();
|
||||
const bool translucent = !layer->isOpaque();
|
||||
const Rect bounds(layer->visibleBounds());
|
||||
visibleRegion.set(bounds);
|
||||
visibleRegion.andSelf(screenRegion);
|
||||
|
@ -921,7 +907,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
|
|||
for (size_t i=0 ; i<count ; i++) {
|
||||
if (cur[i].hints & HWC_HINT_CLEAR_FB) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
if (!(layer->needsBlending())) {
|
||||
if (layer->isOpaque()) {
|
||||
transparent.orSelf(layer->visibleRegionScreen);
|
||||
}
|
||||
}
|
||||
|
@ -979,8 +965,6 @@ void SurfaceFlinger::debugFlashRegions()
|
|||
composeSurfaces(repaint);
|
||||
}
|
||||
|
||||
TextureManager::deactivateTextures();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DITHER);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
@ -1070,6 +1054,7 @@ void SurfaceFlinger::drawWormhole() const
|
|||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
@ -1269,7 +1254,7 @@ sp<ISurface> SurfaceFlinger::createSurface(
|
|||
uint32_t flags)
|
||||
{
|
||||
sp<LayerBaseClient> layer;
|
||||
sp<LayerBaseClient::Surface> surfaceHandle;
|
||||
sp<ISurface> surfaceHandle;
|
||||
|
||||
if (int32_t(w|h) < 0) {
|
||||
LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
|
||||
|
@ -1300,13 +1285,13 @@ sp<ISurface> SurfaceFlinger::createSurface(
|
|||
surfaceHandle = layer->getSurface();
|
||||
if (surfaceHandle != 0) {
|
||||
params->token = token;
|
||||
params->identity = surfaceHandle->getIdentity();
|
||||
params->identity = layer->getIdentity();
|
||||
params->width = w;
|
||||
params->height = h;
|
||||
params->format = format;
|
||||
if (normalLayer != 0) {
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
|
||||
mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1782,7 +1767,6 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
|
|||
|
||||
GLfloat vtx[8];
|
||||
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tname);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
@ -1900,6 +1884,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
|
|||
glEnable(GL_SCISSOR_TEST);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDeleteTextures(1, &tname);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1930,7 +1915,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
|
|||
|
||||
GLfloat vtx[8];
|
||||
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tname);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
@ -2044,6 +2028,7 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
|
|||
glEnable(GL_SCISSOR_TEST);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDeleteTextures(1, &tname);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
@ -2408,20 +2393,72 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
|
|||
return lbc;
|
||||
}
|
||||
|
||||
sp<IMemoryHeap> Client::getControlBlock() const {
|
||||
return 0;
|
||||
}
|
||||
ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
|
||||
return -1;
|
||||
|
||||
status_t Client::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
// these must be checked
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int pid = ipc->getCallingPid();
|
||||
const int uid = ipc->getCallingUid();
|
||||
const int self_pid = getpid();
|
||||
if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
|
||||
// we're called from a different process, do the real check
|
||||
if (!checkCallingPermission(
|
||||
String16("android.permission.ACCESS_SURFACE_FLINGER")))
|
||||
{
|
||||
LOGE("Permission Denial: "
|
||||
"can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
}
|
||||
return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
|
||||
sp<ISurface> Client::createSurface(
|
||||
ISurfaceComposerClient::surface_data_t* params,
|
||||
const String8& name,
|
||||
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
|
||||
uint32_t flags)
|
||||
{
|
||||
return mFlinger->createSurface(params, name, this,
|
||||
display, w, h, format, flags);
|
||||
/*
|
||||
* createSurface must be called from the GL thread so that it can
|
||||
* have access to the GL context.
|
||||
*/
|
||||
|
||||
class MessageCreateSurface : public MessageBase {
|
||||
sp<ISurface> result;
|
||||
SurfaceFlinger* flinger;
|
||||
ISurfaceComposerClient::surface_data_t* params;
|
||||
Client* client;
|
||||
const String8& name;
|
||||
DisplayID display;
|
||||
uint32_t w, h;
|
||||
PixelFormat format;
|
||||
uint32_t flags;
|
||||
public:
|
||||
MessageCreateSurface(SurfaceFlinger* flinger,
|
||||
ISurfaceComposerClient::surface_data_t* params,
|
||||
const String8& name, Client* client,
|
||||
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
|
||||
uint32_t flags)
|
||||
: flinger(flinger), params(params), client(client), name(name),
|
||||
display(display), w(w), h(h), format(format), flags(flags)
|
||||
{
|
||||
}
|
||||
sp<ISurface> getResult() const { return result; }
|
||||
virtual bool handler() {
|
||||
result = flinger->createSurface(params, name, client,
|
||||
display, w, h, format, flags);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),
|
||||
params, name, this, display, w, h, format, flags);
|
||||
mFlinger->postMessageSync(msg);
|
||||
return static_cast<MessageCreateSurface*>( msg.get() )->getResult();
|
||||
}
|
||||
status_t Client::destroySurface(SurfaceID sid) {
|
||||
return mFlinger->removeSurface(this, sid);
|
||||
|
@ -2432,113 +2469,6 @@ status_t Client::setState(int32_t count, const layer_state_t* states) {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UserClient::UserClient(const sp<SurfaceFlinger>& flinger)
|
||||
: ctrlblk(0), mBitmap(0), mFlinger(flinger)
|
||||
{
|
||||
const int pgsize = getpagesize();
|
||||
const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
|
||||
|
||||
mCblkHeap = new MemoryHeapBase(cblksize, 0,
|
||||
"SurfaceFlinger Client control-block");
|
||||
|
||||
ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
|
||||
if (ctrlblk) { // construct the shared structure in-place.
|
||||
new(ctrlblk) SharedClient;
|
||||
}
|
||||
}
|
||||
|
||||
UserClient::~UserClient()
|
||||
{
|
||||
if (ctrlblk) {
|
||||
ctrlblk->~SharedClient(); // destroy our shared-structure.
|
||||
}
|
||||
|
||||
/*
|
||||
* When a UserClient dies, it's unclear what to do exactly.
|
||||
* We could go ahead and destroy all surfaces linked to that client
|
||||
* however, it wouldn't be fair to the main Client
|
||||
* (usually the the window-manager), which might want to re-target
|
||||
* the layer to another UserClient.
|
||||
* I think the best is to do nothing, or not much; in most cases the
|
||||
* WM itself will go ahead and clean things up when it detects a client of
|
||||
* his has died.
|
||||
* The remaining question is what to display? currently we keep
|
||||
* just keep the current buffer.
|
||||
*/
|
||||
}
|
||||
|
||||
status_t UserClient::initCheck() const {
|
||||
return ctrlblk == 0 ? NO_INIT : NO_ERROR;
|
||||
}
|
||||
|
||||
void UserClient::detachLayer(const Layer* layer)
|
||||
{
|
||||
int32_t name = layer->getToken();
|
||||
if (name >= 0) {
|
||||
int32_t mask = 1LU<<name;
|
||||
if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
|
||||
LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sp<IMemoryHeap> UserClient::getControlBlock() const {
|
||||
return mCblkHeap;
|
||||
}
|
||||
|
||||
ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
|
||||
{
|
||||
int32_t name = NAME_NOT_FOUND;
|
||||
sp<Layer> layer(mFlinger->getLayer(sur));
|
||||
if (layer == 0) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// if this layer already has a token, just return it
|
||||
name = layer->getToken();
|
||||
if ((name >= 0) && (layer->getClient() == this)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
name = 0;
|
||||
do {
|
||||
int32_t mask = 1LU<<name;
|
||||
if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
|
||||
// we found and locked that name
|
||||
status_t err = layer->setToken(
|
||||
const_cast<UserClient*>(this), ctrlblk, name);
|
||||
if (err != NO_ERROR) {
|
||||
// free the name
|
||||
android_atomic_and(~mask, &mBitmap);
|
||||
name = err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (++name >= int32_t(SharedBufferStack::NUM_LAYERS_MAX))
|
||||
name = NO_MEMORY;
|
||||
} while(name >= 0);
|
||||
|
||||
//LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)",
|
||||
// sur->asBinder().get(), name, this, mBitmap);
|
||||
return name;
|
||||
}
|
||||
|
||||
sp<ISurface> UserClient::createSurface(
|
||||
ISurfaceComposerClient::surface_data_t* params,
|
||||
const String8& name,
|
||||
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
|
||||
uint32_t flags) {
|
||||
return 0;
|
||||
}
|
||||
status_t UserClient::destroySurface(SurfaceID sid) {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
status_t UserClient::setState(int32_t count, const layer_state_t* states) {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GraphicBufferAlloc::GraphicBufferAlloc() {}
|
||||
|
||||
GraphicBufferAlloc::~GraphicBufferAlloc() {}
|
||||
|
@ -2547,11 +2477,11 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h
|
|||
PixelFormat format, uint32_t usage) {
|
||||
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
|
||||
status_t err = graphicBuffer->initCheck();
|
||||
if (err != 0) {
|
||||
LOGE("createGraphicBuffer: init check failed: %d", err);
|
||||
return 0;
|
||||
} else if (graphicBuffer->handle == 0) {
|
||||
LOGE("createGraphicBuffer: unable to create GraphicBuffer");
|
||||
if (err != 0 || graphicBuffer->handle == 0) {
|
||||
GraphicBuffer::dumpAllocationsToSystemLog();
|
||||
LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
|
||||
"failed (%s), handle=%p",
|
||||
w, h, strerror(-err), graphicBuffer->handle);
|
||||
return 0;
|
||||
}
|
||||
return graphicBuffer;
|
||||
|
|
|
@ -50,6 +50,7 @@ class DisplayHardware;
|
|||
class FreezeLock;
|
||||
class Layer;
|
||||
class LayerDim;
|
||||
struct surface_flinger_cblk_t;
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
@ -72,14 +73,14 @@ public:
|
|||
private:
|
||||
|
||||
// ISurfaceComposerClient interface
|
||||
virtual sp<IMemoryHeap> getControlBlock() const;
|
||||
virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
|
||||
virtual sp<ISurface> createSurface(
|
||||
surface_data_t* params, const String8& name,
|
||||
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
|
||||
uint32_t flags);
|
||||
virtual status_t destroySurface(SurfaceID surfaceId);
|
||||
virtual status_t setState(int32_t count, const layer_state_t* states);
|
||||
virtual status_t onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
|
||||
|
||||
// constant
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
|
@ -92,40 +93,6 @@ private:
|
|||
mutable Mutex mLock;
|
||||
};
|
||||
|
||||
class UserClient : public BnSurfaceComposerClient
|
||||
{
|
||||
public:
|
||||
// pointer to this client's control block
|
||||
SharedClient* ctrlblk;
|
||||
|
||||
public:
|
||||
UserClient(const sp<SurfaceFlinger>& flinger);
|
||||
~UserClient();
|
||||
|
||||
status_t initCheck() const;
|
||||
|
||||
// protected by SurfaceFlinger::mStateLock
|
||||
void detachLayer(const Layer* layer);
|
||||
|
||||
private:
|
||||
|
||||
// ISurfaceComposerClient interface
|
||||
virtual sp<IMemoryHeap> getControlBlock() const;
|
||||
virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
|
||||
virtual sp<ISurface> createSurface(
|
||||
surface_data_t* params, const String8& name,
|
||||
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
|
||||
uint32_t flags);
|
||||
virtual status_t destroySurface(SurfaceID surfaceId);
|
||||
virtual status_t setState(int32_t count, const layer_state_t* states);
|
||||
|
||||
// atomic-ops
|
||||
mutable volatile int32_t mBitmap;
|
||||
|
||||
sp<IMemoryHeap> mCblkHeap;
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
};
|
||||
|
||||
class GraphicBufferAlloc : public BnGraphicBufferAlloc
|
||||
{
|
||||
public:
|
||||
|
@ -199,7 +166,6 @@ public:
|
|||
|
||||
// ISurfaceComposer interface
|
||||
virtual sp<ISurfaceComposerClient> createConnection();
|
||||
virtual sp<ISurfaceComposerClient> createClientConnection();
|
||||
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
|
||||
virtual sp<IMemoryHeap> getCblk() const;
|
||||
virtual void bootFinished();
|
||||
|
@ -208,7 +174,6 @@ public:
|
|||
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
|
||||
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
|
||||
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
|
||||
virtual void signal() const;
|
||||
virtual bool authenticateSurface(const sp<ISurface>& surface) const;
|
||||
|
||||
virtual status_t captureScreen(DisplayID dpy,
|
||||
|
@ -235,7 +200,6 @@ private:
|
|||
friend class Client;
|
||||
friend class LayerBase;
|
||||
friend class LayerBaseClient;
|
||||
friend class LayerBaseClient::Surface;
|
||||
friend class Layer;
|
||||
friend class LayerDim;
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include "Layer.h"
|
||||
#include "SurfaceTextureLayer.h"
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer)
|
||||
: SurfaceTexture(tex), mLayer(layer) {
|
||||
}
|
||||
|
||||
SurfaceTextureLayer::~SurfaceTextureLayer() {
|
||||
}
|
||||
|
||||
|
||||
status_t SurfaceTextureLayer::setDefaultBufferSize(uint32_t w, uint32_t h)
|
||||
{
|
||||
//LOGD("%s, w=%u, h=%u", __PRETTY_FUNCTION__, w, h);
|
||||
return SurfaceTexture::setDefaultBufferSize(w, h);
|
||||
}
|
||||
|
||||
status_t SurfaceTextureLayer::setDefaultBufferFormat(uint32_t format)
|
||||
{
|
||||
mDefaultFormat = format;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SurfaceTextureLayer::setBufferCount(int bufferCount) {
|
||||
status_t res = SurfaceTexture::setBufferCount(bufferCount);
|
||||
return res;
|
||||
}
|
||||
|
||||
status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
|
||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
||||
|
||||
status_t res(NO_INIT);
|
||||
sp<Layer> layer(mLayer.promote());
|
||||
if (layer != NULL) {
|
||||
if (format == 0)
|
||||
format = mDefaultFormat;
|
||||
uint32_t effectiveUsage = layer->getEffectiveUsage(usage);
|
||||
//LOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x",
|
||||
// __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage);
|
||||
res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage);
|
||||
if (res == NO_ERROR) {
|
||||
layer->setFixedSize(w && h);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_SURFACE_TEXTURE_LAYER_H
|
||||
#define ANDROID_SURFACE_TEXTURE_LAYER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <gui/SurfaceTexture.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Layer;
|
||||
|
||||
class SurfaceTextureLayer : public SurfaceTexture
|
||||
{
|
||||
wp<Layer> mLayer;
|
||||
uint32_t mDefaultFormat;
|
||||
|
||||
public:
|
||||
SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer);
|
||||
~SurfaceTextureLayer();
|
||||
|
||||
status_t setDefaultBufferSize(uint32_t w, uint32_t h);
|
||||
status_t setDefaultBufferFormat(uint32_t format);
|
||||
|
||||
public:
|
||||
virtual status_t setBufferCount(int bufferCount);
|
||||
|
||||
protected:
|
||||
virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
|
||||
uint32_t format, uint32_t usage);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_SURFACE_TEXTURE_LAYER_H
|
|
@ -20,18 +20,10 @@
|
|||
|
||||
namespace android {
|
||||
|
||||
int clz_impl(int32_t x);
|
||||
|
||||
int inline clz(int32_t x)
|
||||
{
|
||||
#if defined(__arm__) && !defined(__thumb__)
|
||||
int inline clz(int32_t x) {
|
||||
return __builtin_clz(x);
|
||||
#else
|
||||
return clz_impl(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
|
||||
|
|
Loading…
Reference in New Issue