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 <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <cutils/compiler.h>
|
|
||||||
|
|
||||||
#include <utils/Debug.h>
|
#include <utils/Debug.h>
|
||||||
#include <utils/threads.h>
|
|
||||||
#include <utils/String8.h>
|
|
||||||
|
|
||||||
#include <ui/Rect.h>
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
#define NUM_DISPLAY_MAX 4
|
||||||
* 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()();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
struct display_cblk_t
|
struct display_cblk_t
|
||||||
{
|
{
|
||||||
|
@ -389,12 +46,11 @@ struct surface_flinger_cblk_t // 4KB max
|
||||||
uint8_t connected;
|
uint8_t connected;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
uint32_t pad[7];
|
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)
|
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class GraphicBuffer;
|
||||||
|
|
||||||
class IGraphicBufferAlloc : public IInterface
|
class IGraphicBufferAlloc : public IInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -27,42 +27,23 @@
|
||||||
|
|
||||||
#include <ui/PixelFormat.h>
|
#include <ui/PixelFormat.h>
|
||||||
|
|
||||||
#include <hardware/hardware.h>
|
|
||||||
#include <hardware/gralloc.h>
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
typedef int32_t SurfaceID;
|
typedef int32_t SurfaceID;
|
||||||
|
|
||||||
class GraphicBuffer;
|
class ISurfaceTexture;
|
||||||
|
|
||||||
class ISurface : public IInterface
|
class ISurface : public IInterface
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
enum {
|
enum {
|
||||||
RESERVED0 = IBinder::FIRST_CALL_TRANSACTION,
|
GET_SURFACE_TEXTURE = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
RESERVED1,
|
|
||||||
RESERVED2,
|
|
||||||
REQUEST_BUFFER,
|
|
||||||
SET_BUFFER_COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DECLARE_META_INTERFACE(Surface);
|
DECLARE_META_INTERFACE(Surface);
|
||||||
|
|
||||||
/*
|
virtual sp<ISurfaceTexture> getSurfaceTexture() const = 0;
|
||||||
* 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class IMemoryHeap;
|
||||||
|
|
||||||
class ISurfaceComposer : public IInterface
|
class ISurfaceComposer : public IInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -95,10 +97,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual sp<ISurfaceComposerClient> createConnection() = 0;
|
virtual sp<ISurfaceComposerClient> createConnection() = 0;
|
||||||
|
|
||||||
/* create a client connection with surface flinger
|
|
||||||
*/
|
|
||||||
virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
|
|
||||||
|
|
||||||
/* create a graphic buffer allocator
|
/* create a graphic buffer allocator
|
||||||
*/
|
*/
|
||||||
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
|
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
|
||||||
|
@ -134,11 +132,6 @@ public:
|
||||||
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
|
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
|
||||||
virtual status_t turnElectronBeamOn(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.
|
/* verify that an ISurface was created by SurfaceFlinger.
|
||||||
*/
|
*/
|
||||||
virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0;
|
virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0;
|
||||||
|
@ -154,7 +147,6 @@ public:
|
||||||
// Java by ActivityManagerService.
|
// Java by ActivityManagerService.
|
||||||
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
|
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
CREATE_CONNECTION,
|
CREATE_CONNECTION,
|
||||||
CREATE_CLIENT_CONNECTION,
|
|
||||||
CREATE_GRAPHIC_BUFFER_ALLOC,
|
CREATE_GRAPHIC_BUFFER_ALLOC,
|
||||||
GET_CBLK,
|
GET_CBLK,
|
||||||
OPEN_GLOBAL_TRANSACTION,
|
OPEN_GLOBAL_TRANSACTION,
|
||||||
|
@ -162,7 +154,6 @@ public:
|
||||||
SET_ORIENTATION,
|
SET_ORIENTATION,
|
||||||
FREEZE_DISPLAY,
|
FREEZE_DISPLAY,
|
||||||
UNFREEZE_DISPLAY,
|
UNFREEZE_DISPLAY,
|
||||||
SIGNAL,
|
|
||||||
CAPTURE_SCREEN,
|
CAPTURE_SCREEN,
|
||||||
TURN_ELECTRON_BEAM_OFF,
|
TURN_ELECTRON_BEAM_OFF,
|
||||||
TURN_ELECTRON_BEAM_ON,
|
TURN_ELECTRON_BEAM_ON,
|
||||||
|
|
|
@ -33,9 +33,6 @@ namespace android {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class IMemoryHeap;
|
|
||||||
|
|
||||||
typedef int32_t ClientID;
|
|
||||||
typedef int32_t DisplayID;
|
typedef int32_t DisplayID;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -57,9 +54,6 @@ public:
|
||||||
status_t writeToParcel(Parcel* parcel) const;
|
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
|
* Requires ACCESS_SURFACE_FLINGER permission
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,9 +43,7 @@ class IOMX;
|
||||||
class Rect;
|
class Rect;
|
||||||
class Surface;
|
class Surface;
|
||||||
class SurfaceComposerClient;
|
class SurfaceComposerClient;
|
||||||
class SharedClient;
|
class SurfaceTextureClient;
|
||||||
class SharedBufferClient;
|
|
||||||
class SurfaceClient;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -162,9 +160,6 @@ public:
|
||||||
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
|
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
|
||||||
status_t unlockAndPost();
|
status_t unlockAndPost();
|
||||||
|
|
||||||
// setSwapRectangle() is intended to be used by GL ES clients
|
|
||||||
void setSwapRectangle(const Rect& r);
|
|
||||||
|
|
||||||
sp<IBinder> asBinder() const;
|
sp<IBinder> asBinder() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -209,6 +204,7 @@ private:
|
||||||
static int query(const ANativeWindow* window, int what, int* value);
|
static int query(const ANativeWindow* window, int what, int* value);
|
||||||
static int perform(ANativeWindow* window, int operation, ...);
|
static int perform(ANativeWindow* window, int operation, ...);
|
||||||
|
|
||||||
|
int setSwapInterval(int interval);
|
||||||
int dequeueBuffer(ANativeWindowBuffer** buffer);
|
int dequeueBuffer(ANativeWindowBuffer** buffer);
|
||||||
int lockBuffer(ANativeWindowBuffer* buffer);
|
int lockBuffer(ANativeWindowBuffer* buffer);
|
||||||
int queueBuffer(ANativeWindowBuffer* buffer);
|
int queueBuffer(ANativeWindowBuffer* buffer);
|
||||||
|
@ -216,83 +212,23 @@ private:
|
||||||
int query(int what, int* value) const;
|
int query(int what, int* value) const;
|
||||||
int perform(int operation, va_list args);
|
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...
|
* private stuff...
|
||||||
*/
|
*/
|
||||||
void init();
|
void init();
|
||||||
status_t validate(bool inCancelBuffer = false) const;
|
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;
|
int getConnectedApi() const;
|
||||||
|
|
||||||
bool needNewBuffer(int bufIdx,
|
|
||||||
uint32_t *pWidth, uint32_t *pHeight,
|
|
||||||
uint32_t *pFormat, uint32_t *pUsage) const;
|
|
||||||
|
|
||||||
static void cleanCachedSurfacesLocked();
|
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
|
// constants
|
||||||
GraphicBufferMapper& mBufferMapper;
|
|
||||||
SurfaceClient& mClient;
|
|
||||||
SharedBufferClient* mSharedBufferClient;
|
|
||||||
status_t mInitCheck;
|
status_t mInitCheck;
|
||||||
sp<ISurface> mSurface;
|
sp<ISurface> mSurface;
|
||||||
|
sp<SurfaceTextureClient> mSurfaceTextureClient;
|
||||||
uint32_t mIdentity;
|
uint32_t mIdentity;
|
||||||
PixelFormat mFormat;
|
PixelFormat mFormat;
|
||||||
uint32_t mFlags;
|
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
|
// protected by mSurfaceLock. These are also used from lock/unlock
|
||||||
// but in that case, they must be called form the same thread.
|
// but in that case, they must be called form the same thread.
|
||||||
|
@ -304,9 +240,6 @@ private:
|
||||||
mutable Region mOldDirtyRegion;
|
mutable Region mOldDirtyRegion;
|
||||||
bool mReserved;
|
bool mReserved;
|
||||||
|
|
||||||
// only used from dequeueBuffer()
|
|
||||||
Vector< sp<GraphicBuffer> > mBuffers;
|
|
||||||
|
|
||||||
// query() must be called from dequeueBuffer() thread
|
// query() must be called from dequeueBuffer() thread
|
||||||
uint32_t mWidth;
|
uint32_t mWidth;
|
||||||
uint32_t mHeight;
|
uint32_t mHeight;
|
||||||
|
|
|
@ -36,10 +36,10 @@ namespace android {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class Region;
|
|
||||||
class SharedClient;
|
|
||||||
class ISurfaceComposer;
|
|
||||||
class DisplayInfo;
|
class DisplayInfo;
|
||||||
|
class IMemoryHeap;
|
||||||
|
class ISurfaceComposer;
|
||||||
|
class Region;
|
||||||
class surface_flinger_cblk_t;
|
class surface_flinger_cblk_t;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -16,7 +16,6 @@ LOCAL_SRC_FILES:= \
|
||||||
ISurfaceComposerClient.cpp \
|
ISurfaceComposerClient.cpp \
|
||||||
IGraphicBufferAlloc.cpp \
|
IGraphicBufferAlloc.cpp \
|
||||||
LayerState.cpp \
|
LayerState.cpp \
|
||||||
SharedBufferStack.cpp \
|
|
||||||
Surface.cpp \
|
Surface.cpp \
|
||||||
SurfaceComposerClient.cpp \
|
SurfaceComposerClient.cpp \
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,7 @@
|
||||||
|
|
||||||
#include <binder/Parcel.h>
|
#include <binder/Parcel.h>
|
||||||
|
|
||||||
#include <ui/GraphicBuffer.h>
|
#include <gui/ISurfaceTexture.h>
|
||||||
|
|
||||||
#include <surfaceflinger/Surface.h>
|
|
||||||
#include <surfaceflinger/ISurface.h>
|
#include <surfaceflinger/ISurface.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
@ -39,30 +37,11 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
virtual sp<ISurfaceTexture> getSurfaceTexture() const {
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
|
||||||
{
|
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
|
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
|
||||||
data.writeInt32(bufferIdx);
|
remote()->transact(GET_SURFACE_TEXTURE, data, &reply);
|
||||||
data.writeInt32(w);
|
return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,23 +53,9 @@ status_t BnSurface::onTransact(
|
||||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||||
{
|
{
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case REQUEST_BUFFER: {
|
case GET_SURFACE_TEXTURE: {
|
||||||
CHECK_INTERFACE(ISurface, data, reply);
|
CHECK_INTERFACE(ISurface, data, reply);
|
||||||
int bufferIdx = data.readInt32();
|
reply->writeStrongBinder( getSurfaceTexture()->asBinder() );
|
||||||
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);
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -57,15 +57,6 @@ public:
|
||||||
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
|
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()
|
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
|
||||||
{
|
{
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
|
@ -174,13 +165,6 @@ public:
|
||||||
return reply.readInt32();
|
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
|
virtual bool authenticateSurface(const sp<ISurface>& surface) const
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
|
@ -229,11 +213,6 @@ status_t BnSurfaceComposer::onTransact(
|
||||||
sp<IBinder> b = createConnection()->asBinder();
|
sp<IBinder> b = createConnection()->asBinder();
|
||||||
reply->writeStrongBinder(b);
|
reply->writeStrongBinder(b);
|
||||||
} break;
|
} break;
|
||||||
case CREATE_CLIENT_CONNECTION: {
|
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
|
||||||
sp<IBinder> b = createClientConnection()->asBinder();
|
|
||||||
reply->writeStrongBinder(b);
|
|
||||||
} break;
|
|
||||||
case CREATE_GRAPHIC_BUFFER_ALLOC: {
|
case CREATE_GRAPHIC_BUFFER_ALLOC: {
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
|
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
|
||||||
|
@ -270,10 +249,6 @@ status_t BnSurfaceComposer::onTransact(
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
bootFinished();
|
bootFinished();
|
||||||
} break;
|
} break;
|
||||||
case SIGNAL: {
|
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
|
||||||
signal();
|
|
||||||
} break;
|
|
||||||
case GET_CBLK: {
|
case GET_CBLK: {
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
sp<IBinder> b = getCblk()->asBinder();
|
sp<IBinder> b = getCblk()->asBinder();
|
||||||
|
|
|
@ -50,9 +50,7 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
|
CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
GET_TOKEN,
|
|
||||||
CREATE_SURFACE,
|
|
||||||
DESTROY_SURFACE,
|
DESTROY_SURFACE,
|
||||||
SET_STATE
|
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,
|
virtual sp<ISurface> createSurface( surface_data_t* params,
|
||||||
const String8& name,
|
const String8& name,
|
||||||
DisplayID display,
|
DisplayID display,
|
||||||
|
@ -131,41 +112,6 @@ IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClie
|
||||||
status_t BnSurfaceComposerClient::onTransact(
|
status_t BnSurfaceComposerClient::onTransact(
|
||||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
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) {
|
switch(code) {
|
||||||
case CREATE_SURFACE: {
|
case CREATE_SURFACE: {
|
||||||
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
|
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/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <utils/Errors.h>
|
|
||||||
#include <utils/threads.h>
|
|
||||||
#include <utils/CallStack.h>
|
#include <utils/CallStack.h>
|
||||||
|
#include <utils/Errors.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
|
#include <utils/threads.h>
|
||||||
|
|
||||||
#include <binder/IPCThreadState.h>
|
|
||||||
#include <binder/IMemory.h>
|
#include <binder/IMemory.h>
|
||||||
|
#include <binder/IPCThreadState.h>
|
||||||
|
|
||||||
|
#include <gui/SurfaceTextureClient.h>
|
||||||
|
|
||||||
#include <ui/DisplayInfo.h>
|
#include <ui/DisplayInfo.h>
|
||||||
#include <ui/GraphicBuffer.h>
|
#include <ui/GraphicBuffer.h>
|
||||||
|
@ -35,12 +37,11 @@
|
||||||
#include <ui/GraphicLog.h>
|
#include <ui/GraphicLog.h>
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
|
|
||||||
#include <surfaceflinger/Surface.h>
|
|
||||||
#include <surfaceflinger/ISurface.h>
|
#include <surfaceflinger/ISurface.h>
|
||||||
#include <surfaceflinger/ISurfaceComposer.h>
|
#include <surfaceflinger/ISurfaceComposer.h>
|
||||||
|
#include <surfaceflinger/Surface.h>
|
||||||
#include <surfaceflinger/SurfaceComposerClient.h>
|
#include <surfaceflinger/SurfaceComposerClient.h>
|
||||||
|
|
||||||
#include <private/surfaceflinger/SharedBufferStack.h>
|
|
||||||
#include <private/surfaceflinger/LayerState.h>
|
#include <private/surfaceflinger/LayerState.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
@ -273,58 +274,10 @@ sp<Surface> SurfaceControl::getSurface() const
|
||||||
// Surface
|
// 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)
|
Surface::Surface(const sp<SurfaceControl>& surface)
|
||||||
: mBufferMapper(GraphicBufferMapper::get()),
|
: mInitCheck(NO_INIT),
|
||||||
mClient(SurfaceClient::getInstance()),
|
|
||||||
mSharedBufferClient(NULL),
|
|
||||||
mInitCheck(NO_INIT),
|
|
||||||
mSurface(surface->mSurface),
|
mSurface(surface->mSurface),
|
||||||
mIdentity(surface->mIdentity),
|
mIdentity(surface->mIdentity),
|
||||||
mFormat(surface->mFormat), mFlags(surface->mFlags),
|
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)
|
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
|
||||||
: mBufferMapper(GraphicBufferMapper::get()),
|
: mInitCheck(NO_INIT)
|
||||||
mClient(SurfaceClient::getInstance()),
|
|
||||||
mSharedBufferClient(NULL),
|
|
||||||
mInitCheck(NO_INIT)
|
|
||||||
{
|
{
|
||||||
mSurface = interface_cast<ISurface>(ref);
|
mSurface = interface_cast<ISurface>(ref);
|
||||||
mIdentity = parcel.readInt32();
|
mIdentity = parcel.readInt32();
|
||||||
|
@ -382,7 +332,6 @@ status_t Surface::writeToParcel(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mutex Surface::sCachedSurfacesLock;
|
Mutex Surface::sCachedSurfacesLock;
|
||||||
DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
|
DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
|
||||||
|
|
||||||
|
@ -422,32 +371,29 @@ void Surface::init()
|
||||||
ANativeWindow::query = query;
|
ANativeWindow::query = query;
|
||||||
ANativeWindow::perform = perform;
|
ANativeWindow::perform = perform;
|
||||||
|
|
||||||
DisplayInfo dinfo;
|
if (mSurface != NULL) {
|
||||||
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
|
||||||
const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
|
LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
|
||||||
const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
|
if (surfaceTexture != NULL) {
|
||||||
// FIXME: set real values here
|
mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
|
||||||
const_cast<int&>(ANativeWindow::minSwapInterval) = 1;
|
mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER);
|
||||||
const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
|
}
|
||||||
const_cast<uint32_t&>(ANativeWindow::flags) = 0;
|
|
||||||
|
|
||||||
mNextBufferTransform = 0;
|
DisplayInfo dinfo;
|
||||||
mConnected = 0;
|
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
||||||
mSwapRectangle.makeInvalid();
|
const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
|
||||||
mNextBufferCrop = Rect(0,0);
|
const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
|
||||||
// two buffers by default
|
|
||||||
mBuffers.setCapacity(2);
|
|
||||||
mBuffers.insertAt(0, 2);
|
|
||||||
|
|
||||||
if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
|
const_cast<int&>(ANativeWindow::minSwapInterval) =
|
||||||
int32_t token = mClient.getTokenForSurface(mSurface);
|
mSurfaceTextureClient->minSwapInterval;
|
||||||
if (token >= 0) {
|
|
||||||
mSharedBufferClient = new SharedBufferClient(
|
const_cast<int&>(ANativeWindow::maxSwapInterval) =
|
||||||
mClient.getSharedClient(), token, 2, mIdentity);
|
mSurfaceTextureClient->maxSwapInterval;
|
||||||
mInitCheck = mClient.getSharedClient()->validate(token);
|
|
||||||
} else {
|
const_cast<uint32_t&>(ANativeWindow::flags) = 0;
|
||||||
LOGW("Not initializing the shared buffer client because token = %d",
|
|
||||||
token);
|
if (mSurfaceTextureClient != 0) {
|
||||||
|
mInitCheck = NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,9 +402,8 @@ Surface::~Surface()
|
||||||
{
|
{
|
||||||
// clear all references and trigger an IPC now, to make sure things
|
// clear all references and trigger an IPC now, to make sure things
|
||||||
// happen without delay, since these resources are quite heavy.
|
// happen without delay, since these resources are quite heavy.
|
||||||
mBuffers.clear();
|
mSurfaceTextureClient.clear();
|
||||||
mSurface.clear();
|
mSurface.clear();
|
||||||
delete mSharedBufferClient;
|
|
||||||
IPCThreadState::self()->flushCommands();
|
IPCThreadState::self()->flushCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,32 +418,6 @@ status_t Surface::validate(bool inCancelBuffer) const
|
||||||
LOGE("invalid token (identity=%u)", mIdentity);
|
LOGE("invalid token (identity=%u)", mIdentity);
|
||||||
return mInitCheck;
|
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;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +428,8 @@ sp<IBinder> Surface::asBinder() const {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
int Surface::setSwapInterval(ANativeWindow* window, int interval) {
|
int Surface::setSwapInterval(ANativeWindow* window, int interval) {
|
||||||
return 0;
|
Surface* self = getSelf(window);
|
||||||
|
return self->setSwapInterval(interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Surface::dequeueBuffer(ANativeWindow* window,
|
int Surface::dequeueBuffer(ANativeWindow* window,
|
||||||
|
@ -554,383 +474,52 @@ int Surface::perform(ANativeWindow* window,
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool Surface::needNewBuffer(int bufIdx,
|
int Surface::setSwapInterval(int interval) {
|
||||||
uint32_t *pWidth, uint32_t *pHeight,
|
return mSurfaceTextureClient->setSwapInterval(interval);
|
||||||
uint32_t *pFormat, uint32_t *pUsage) const
|
|
||||||
{
|
|
||||||
Mutex::Autolock _l(mSurfaceLock);
|
|
||||||
|
|
||||||
// Always call needNewBuffer(), since it clears the needed buffers flags
|
|
||||||
bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
|
|
||||||
bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]);
|
|
||||||
bool newNeewBuffer = needNewBuffer || !validBuffer;
|
|
||||||
if (newNeewBuffer) {
|
|
||||||
mBufferInfo.get(pWidth, pHeight, pFormat, pUsage);
|
|
||||||
}
|
|
||||||
return newNeewBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Surface::dequeueBuffer(ANativeWindowBuffer** buffer)
|
int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) {
|
||||||
{
|
status_t err = mSurfaceTextureClient->dequeueBuffer(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err == NO_ERROR) {
|
if (err == NO_ERROR) {
|
||||||
mDirtyRegion.set(backBuffer->width, backBuffer->height);
|
mDirtyRegion.set(buffer[0]->width, buffer[0]->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();
|
|
||||||
}
|
}
|
||||||
return err;
|
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) {
|
switch (what) {
|
||||||
case NATIVE_WINDOW_WIDTH:
|
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
|
||||||
*value = int(mWidth);
|
// TODO: this is not needed anymore
|
||||||
|
*value = 1;
|
||||||
return NO_ERROR;
|
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:
|
case NATIVE_WINDOW_CONCRETE_TYPE:
|
||||||
|
// TODO: this is not needed anymore
|
||||||
*value = NATIVE_WINDOW_SURFACE;
|
*value = NATIVE_WINDOW_SURFACE;
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
return BAD_VALUE;
|
return mSurfaceTextureClient->query(what, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Surface::perform(int operation, va_list args)
|
int Surface::perform(int operation, va_list args) {
|
||||||
{
|
return mSurfaceTextureClient->perform(operation, 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::getConnectedApi() const
|
int Surface::getConnectedApi() const {
|
||||||
{
|
return mSurfaceTextureClient->getConnectedApi();
|
||||||
Mutex::Autolock _l(mSurfaceLock);
|
|
||||||
return mConnected;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -967,16 +556,17 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're intending to do software rendering from this point
|
// 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;
|
ANativeWindowBuffer* out;
|
||||||
status_t err = dequeueBuffer(&out);
|
status_t err = mSurfaceTextureClient->dequeueBuffer(&out);
|
||||||
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
|
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
|
||||||
if (err == NO_ERROR) {
|
if (err == NO_ERROR) {
|
||||||
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
|
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
|
||||||
err = lockBuffer(backBuffer.get());
|
err = mSurfaceTextureClient->lockBuffer(backBuffer.get());
|
||||||
LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
|
LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
|
||||||
getBufferIndex(backBuffer), strerror(-err));
|
backBuffer->handle, strerror(-err));
|
||||||
if (err == NO_ERROR) {
|
if (err == NO_ERROR) {
|
||||||
const Rect bounds(backBuffer->width, backBuffer->height);
|
const Rect bounds(backBuffer->width, backBuffer->height);
|
||||||
const Region boundsRegion(bounds);
|
const Region boundsRegion(bounds);
|
||||||
|
@ -1043,110 +633,14 @@ status_t Surface::unlockAndPost()
|
||||||
status_t err = mLockedBuffer->unlock();
|
status_t err = mLockedBuffer->unlock();
|
||||||
LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
|
LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
|
||||||
|
|
||||||
err = queueBuffer(mLockedBuffer.get());
|
err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get());
|
||||||
LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
|
LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
|
||||||
getBufferIndex(mLockedBuffer), strerror(-err));
|
mLockedBuffer->handle, strerror(-err));
|
||||||
|
|
||||||
mPostedBuffer = mLockedBuffer;
|
mPostedBuffer = mLockedBuffer;
|
||||||
mLockedBuffer = 0;
|
mLockedBuffer = 0;
|
||||||
return err;
|
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
|
}; // namespace android
|
||||||
|
|
|
@ -20,19 +20,20 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <utils/Errors.h>
|
#include <utils/Errors.h>
|
||||||
#include <utils/threads.h>
|
|
||||||
#include <utils/SortedVector.h>
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/Singleton.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/IMemory.h>
|
||||||
|
#include <binder/IServiceManager.h>
|
||||||
|
|
||||||
#include <ui/DisplayInfo.h>
|
#include <ui/DisplayInfo.h>
|
||||||
|
|
||||||
|
#include <surfaceflinger/ISurface.h>
|
||||||
#include <surfaceflinger/ISurfaceComposer.h>
|
#include <surfaceflinger/ISurfaceComposer.h>
|
||||||
#include <surfaceflinger/ISurfaceComposerClient.h>
|
#include <surfaceflinger/ISurfaceComposerClient.h>
|
||||||
#include <surfaceflinger/ISurface.h>
|
|
||||||
#include <surfaceflinger/SurfaceComposerClient.h>
|
#include <surfaceflinger/SurfaceComposerClient.h>
|
||||||
|
|
||||||
#include <private/surfaceflinger/LayerState.h>
|
#include <private/surfaceflinger/LayerState.h>
|
||||||
|
@ -217,7 +218,7 @@ void SurfaceComposerClient::dispose()
|
||||||
status_t SurfaceComposerClient::getDisplayInfo(
|
status_t SurfaceComposerClient::getDisplayInfo(
|
||||||
DisplayID dpy, DisplayInfo* info)
|
DisplayID dpy, DisplayInfo* info)
|
||||||
{
|
{
|
||||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
|
|
||||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||||
|
@ -235,7 +236,7 @@ status_t SurfaceComposerClient::getDisplayInfo(
|
||||||
|
|
||||||
ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
|
ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
|
||||||
{
|
{
|
||||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||||
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
|
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)
|
ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
|
||||||
{
|
{
|
||||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||||
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
|
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)
|
ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
|
||||||
{
|
{
|
||||||
if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
|
if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
volatile surface_flinger_cblk_t const * cblk = get_cblk();
|
||||||
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
|
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 {
|
int SurfaceTextureClient::query(int what, int* value) const {
|
||||||
LOGV("SurfaceTextureClient::query");
|
LOGV("SurfaceTextureClient::query");
|
||||||
switch (what) {
|
switch (what) {
|
||||||
|
case NATIVE_WINDOW_FORMAT:
|
||||||
|
if (mReqFormat) {
|
||||||
|
*value = mReqFormat;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
|
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
|
||||||
// TODO: this is not needed anymore
|
// TODO: this is not needed anymore
|
||||||
*value = 0;
|
*value = 0;
|
||||||
|
|
|
@ -2,18 +2,18 @@ LOCAL_PATH:= $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
clz.cpp.arm \
|
Layer.cpp \
|
||||||
DisplayHardware/DisplayHardware.cpp \
|
LayerBase.cpp \
|
||||||
|
LayerDim.cpp \
|
||||||
|
DisplayHardware/DisplayHardware.cpp \
|
||||||
DisplayHardware/DisplayHardwareBase.cpp \
|
DisplayHardware/DisplayHardwareBase.cpp \
|
||||||
DisplayHardware/HWComposer.cpp \
|
DisplayHardware/HWComposer.cpp \
|
||||||
GLExtensions.cpp \
|
GLExtensions.cpp \
|
||||||
Layer.cpp \
|
MessageQueue.cpp \
|
||||||
LayerBase.cpp \
|
SurfaceFlinger.cpp \
|
||||||
LayerDim.cpp \
|
SurfaceTextureLayer.cpp \
|
||||||
MessageQueue.cpp \
|
Transform.cpp \
|
||||||
SurfaceFlinger.cpp \
|
|
||||||
TextureManager.cpp \
|
|
||||||
Transform.cpp
|
|
||||||
|
|
||||||
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
|
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
|
||||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
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 <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <gui/SurfaceTexture.h>
|
||||||
|
|
||||||
|
#include <pixelflinger/pixelflinger.h>
|
||||||
#include <ui/GraphicBuffer.h>
|
#include <ui/GraphicBuffer.h>
|
||||||
#include <ui/PixelFormat.h>
|
#include <ui/PixelFormat.h>
|
||||||
#include <pixelflinger/pixelflinger.h>
|
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
@ -30,8 +32,8 @@
|
||||||
#include <GLES/glext.h>
|
#include <GLES/glext.h>
|
||||||
|
|
||||||
#include "LayerBase.h"
|
#include "LayerBase.h"
|
||||||
|
#include "SurfaceTextureLayer.h"
|
||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
#include "TextureManager.h"
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
@ -40,7 +42,6 @@ namespace android {
|
||||||
class FreezeLock;
|
class FreezeLock;
|
||||||
class Client;
|
class Client;
|
||||||
class GLExtensions;
|
class GLExtensions;
|
||||||
class UserClient;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -58,164 +59,59 @@ public:
|
||||||
status_t setBuffers(uint32_t w, uint32_t h,
|
status_t setBuffers(uint32_t w, uint32_t h,
|
||||||
PixelFormat format, uint32_t flags=0);
|
PixelFormat format, uint32_t flags=0);
|
||||||
|
|
||||||
// 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
|
// Set this Layer's buffers size
|
||||||
void setBufferSize(uint32_t w, uint32_t h);
|
|
||||||
bool isFixedSize() const;
|
bool isFixedSize() const;
|
||||||
|
|
||||||
// LayerBase interface
|
// LayerBase interface
|
||||||
virtual void setGeometry(hwc_layer_t* hwcl);
|
virtual void setGeometry(hwc_layer_t* hwcl);
|
||||||
virtual void setPerFrameData(hwc_layer_t* hwcl);
|
virtual void setPerFrameData(hwc_layer_t* hwcl);
|
||||||
virtual void drawForSreenShot() const;
|
|
||||||
virtual void onDraw(const Region& clip) const;
|
virtual void onDraw(const Region& clip) const;
|
||||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||||
virtual void lockPageFlip(bool& recomputeVisibleRegions);
|
virtual void lockPageFlip(bool& recomputeVisibleRegions);
|
||||||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
||||||
virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const;
|
virtual bool isOpaque() const;
|
||||||
virtual bool needsBlending() const;
|
|
||||||
virtual bool needsDithering() const { return mNeedsDithering; }
|
virtual bool needsDithering() const { return mNeedsDithering; }
|
||||||
virtual bool needsFiltering() const;
|
|
||||||
virtual bool isSecure() const { return mSecure; }
|
virtual bool isSecure() const { return mSecure; }
|
||||||
virtual bool isProtected() const;
|
virtual bool isProtected() const;
|
||||||
virtual sp<Surface> createSurface() const;
|
|
||||||
virtual void onRemoved();
|
virtual void onRemoved();
|
||||||
|
|
||||||
// only for debugging
|
// only for debugging
|
||||||
inline sp<GraphicBuffer> getBuffer(int i) const {
|
inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
|
||||||
return mBufferManager.getBuffer(i); }
|
|
||||||
// only for debugging
|
|
||||||
inline const sp<FreezeLock>& getFreezeLock() const {
|
|
||||||
return mFreezeLock; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void destroy() const;
|
virtual void destroy() const;
|
||||||
|
virtual void onFirstRef();
|
||||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reloadTexture(const Region& dirty);
|
friend class SurfaceTextureLayer;
|
||||||
|
void onFrameQueued();
|
||||||
|
virtual sp<ISurface> createSurface();
|
||||||
uint32_t getEffectiveUsage(uint32_t usage) const;
|
uint32_t getEffectiveUsage(uint32_t usage) const;
|
||||||
sp<GraphicBuffer> requestBuffer(int bufferIdx,
|
void setFixedSize(bool fixedSize);
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
bool isCropped() const;
|
||||||
status_t setBufferCount(int bufferCount);
|
static bool getOpacityForFormat(uint32_t format);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
class SurfaceLayer : public LayerBaseClient::Surface {
|
// constants
|
||||||
public:
|
sp<SurfaceTextureLayer> mSurfaceTexture;
|
||||||
SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner);
|
GLuint mTextureName;
|
||||||
~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;
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
// thread-safe
|
// thread-safe
|
||||||
ClientRef mUserClientRef;
|
volatile int32_t mQueuedFrames;
|
||||||
|
|
||||||
|
// main thread
|
||||||
|
sp<GraphicBuffer> mActiveBuffer;
|
||||||
|
GLfloat mTextureMatrix[16];
|
||||||
|
Rect mCurrentCrop;
|
||||||
|
uint32_t mCurrentTransform;
|
||||||
|
bool mCurrentOpacity;
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
PixelFormat mFormat;
|
PixelFormat mFormat;
|
||||||
const GLExtensions& mGLExtensions;
|
const GLExtensions& mGLExtensions;
|
||||||
bool mNeedsBlending;
|
bool mOpaqueLayer;
|
||||||
bool mNeedsDithering;
|
bool mNeedsDithering;
|
||||||
|
|
||||||
// page-flip thread (currently main thread)
|
// page-flip thread (currently main thread)
|
||||||
|
@ -226,18 +122,8 @@ private:
|
||||||
// page-flip thread and transaction thread (currently main thread)
|
// page-flip thread and transaction thread (currently main thread)
|
||||||
sp<FreezeLock> mFreezeLock;
|
sp<FreezeLock> mFreezeLock;
|
||||||
|
|
||||||
// see threading usage in declaration
|
|
||||||
TextureManager mTextureManager;
|
|
||||||
BufferManager mBufferManager;
|
|
||||||
|
|
||||||
// binder thread, transaction thread
|
// binder thread, transaction thread
|
||||||
mutable Mutex mLock;
|
mutable Mutex mLock;
|
||||||
uint32_t mWidth;
|
|
||||||
uint32_t mHeight;
|
|
||||||
uint32_t mReqWidth;
|
|
||||||
uint32_t mReqHeight;
|
|
||||||
uint32_t mReqFormat;
|
|
||||||
bool mNeedsScaling;
|
|
||||||
bool mFixedSize;
|
bool mFixedSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#include "LayerBase.h"
|
#include "LayerBase.h"
|
||||||
#include "SurfaceFlinger.h"
|
#include "SurfaceFlinger.h"
|
||||||
#include "DisplayHardware/DisplayHardware.h"
|
#include "DisplayHardware/DisplayHardware.h"
|
||||||
#include "TextureManager.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
@ -44,7 +42,7 @@ int32_t LayerBase::sSequence = 1;
|
||||||
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
||||||
: dpy(display), contentDirty(false),
|
: dpy(display), contentDirty(false),
|
||||||
sequence(uint32_t(android_atomic_inc(&sSequence))),
|
sequence(uint32_t(android_atomic_inc(&sSequence))),
|
||||||
mFlinger(flinger),
|
mFlinger(flinger), mFiltering(false),
|
||||||
mNeedsFiltering(false),
|
mNeedsFiltering(false),
|
||||||
mOrientation(0),
|
mOrientation(0),
|
||||||
mLeft(0), mTop(0),
|
mLeft(0), mTop(0),
|
||||||
|
@ -54,8 +52,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
||||||
{
|
{
|
||||||
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
||||||
mFlags = hw.getFlags();
|
mFlags = hw.getFlags();
|
||||||
mBufferCrop.makeInvalid();
|
|
||||||
mBufferTransform = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerBase::~LayerBase()
|
LayerBase::~LayerBase()
|
||||||
|
@ -310,6 +306,16 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
|
||||||
hwcl->handle = NULL;
|
hwcl->handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayerBase::setFiltering(bool filtering)
|
||||||
|
{
|
||||||
|
mFiltering = filtering;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerBase::getFiltering() const
|
||||||
|
{
|
||||||
|
return mFiltering;
|
||||||
|
}
|
||||||
|
|
||||||
void LayerBase::draw(const Region& clip) const
|
void LayerBase::draw(const Region& clip) const
|
||||||
{
|
{
|
||||||
// reset GL state
|
// reset GL state
|
||||||
|
@ -318,10 +324,12 @@ void LayerBase::draw(const Region& clip) const
|
||||||
onDraw(clip);
|
onDraw(clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerBase::drawForSreenShot() const
|
void LayerBase::drawForSreenShot()
|
||||||
{
|
{
|
||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
|
setFiltering(true);
|
||||||
onDraw( Region(hw.bounds()) );
|
onDraw( Region(hw.bounds()) );
|
||||||
|
setFiltering(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
|
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();
|
const uint32_t fbHeight = hw.getHeight();
|
||||||
glColor4f(red,green,blue,alpha);
|
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_BLEND);
|
||||||
glDisable(GL_DITHER);
|
glDisable(GL_DITHER);
|
||||||
|
|
||||||
|
@ -354,24 +366,11 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
|
||||||
clearWithOpenGL(clip,0,0,0,0);
|
clearWithOpenGL(clip,0,0,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
void LayerBase::drawWithOpenGL(const Region& clip) const
|
||||||
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
|
|
||||||
{
|
{
|
||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
const uint32_t fbHeight = hw.getHeight();
|
const uint32_t fbHeight = hw.getHeight();
|
||||||
const State& s(drawingState());
|
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;
|
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
||||||
if (UNLIKELY(s.alpha < 0xFF)) {
|
if (UNLIKELY(s.alpha < 0xFF)) {
|
||||||
|
@ -387,7 +386,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
||||||
} else {
|
} else {
|
||||||
glColor4f(1, 1, 1, 1);
|
glColor4f(1, 1, 1, 1);
|
||||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
if (needsBlending()) {
|
if (!isOpaque()) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
} else {
|
} 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 {
|
struct TexCoords {
|
||||||
GLfloat u;
|
GLfloat u;
|
||||||
GLfloat v;
|
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 texCoords[4];
|
||||||
texCoords[vLT].u = cl;
|
texCoords[0].u = 0;
|
||||||
texCoords[vLT].v = ct;
|
texCoords[0].v = 1;
|
||||||
texCoords[vLB].u = cl;
|
texCoords[1].u = 0;
|
||||||
texCoords[vLB].v = cb;
|
texCoords[1].v = 0;
|
||||||
texCoords[vRB].u = cr;
|
texCoords[2].u = 1;
|
||||||
texCoords[vRB].v = cb;
|
texCoords[2].v = 0;
|
||||||
texCoords[vRT].u = cr;
|
texCoords[3].u = 1;
|
||||||
texCoords[vRT].v = ct;
|
texCoords[3].v = 1;
|
||||||
|
|
||||||
if (needsDithering()) {
|
if (needsDithering()) {
|
||||||
glEnable(GL_DITHER);
|
glEnable(GL_DITHER);
|
||||||
|
@ -497,20 +430,6 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
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
|
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
||||||
{
|
{
|
||||||
const Layer::State& s(drawingState());
|
const Layer::State& s(drawingState());
|
||||||
|
@ -518,10 +437,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
||||||
"+ %s %p\n"
|
"+ %s %p\n"
|
||||||
" "
|
" "
|
||||||
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
|
"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",
|
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
|
||||||
getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
|
getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
|
||||||
needsBlending(), needsDithering(), contentDirty,
|
isOpaque(), needsDithering(), contentDirty,
|
||||||
s.alpha, s.flags,
|
s.alpha, s.flags,
|
||||||
s.transform[0][0], s.transform[0][1],
|
s.transform[0][0], s.transform[0][1],
|
||||||
s.transform[1][0], s.transform[1][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);
|
Mutex::Autolock _l(mLock);
|
||||||
|
|
||||||
LOG_ALWAYS_FATAL_IF(mHasSurface,
|
LOG_ALWAYS_FATAL_IF(mHasSurface,
|
||||||
|
@ -573,12 +505,6 @@ wp<IBinder> LayerBaseClient::getSurfaceBinder() const {
|
||||||
return mClientSurfaceBinder;
|
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
|
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
|
||||||
{
|
{
|
||||||
LayerBase::dump(result, buffer, SIZE);
|
LayerBase::dump(result, buffer, SIZE);
|
||||||
|
@ -601,44 +527,14 @@ void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) con
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
LayerBaseClient::Surface::Surface(
|
LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
|
||||||
const sp<SurfaceFlinger>& flinger,
|
const sp<LayerBaseClient>& layer)
|
||||||
int identity,
|
: mFlinger(flinger), mLayer(layer) {
|
||||||
const sp<LayerBaseClient>& owner)
|
|
||||||
: mFlinger(flinger), mIdentity(identity), mOwner(owner)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerBaseClient::Surface::~Surface()
|
LayerBaseClient::LayerCleaner::~LayerCleaner() {
|
||||||
{
|
|
||||||
/*
|
|
||||||
* This is a good place to clean-up all client resources
|
|
||||||
*/
|
|
||||||
|
|
||||||
// destroy client resources
|
// destroy client resources
|
||||||
mFlinger->destroySurface(mOwner);
|
mFlinger->destroySurface(mLayer);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include <ui/Region.h>
|
#include <ui/Region.h>
|
||||||
|
|
||||||
#include <surfaceflinger/ISurfaceComposerClient.h>
|
#include <surfaceflinger/ISurfaceComposerClient.h>
|
||||||
#include <private/surfaceflinger/SharedBufferStack.h>
|
|
||||||
#include <private/surfaceflinger/LayerState.h>
|
#include <private/surfaceflinger/LayerState.h>
|
||||||
|
|
||||||
#include <pixelflinger/pixelflinger.h>
|
#include <pixelflinger/pixelflinger.h>
|
||||||
|
@ -43,13 +42,12 @@ namespace android {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class DisplayHardware;
|
|
||||||
class Client;
|
class Client;
|
||||||
|
class DisplayHardware;
|
||||||
class GraphicBuffer;
|
class GraphicBuffer;
|
||||||
class GraphicPlane;
|
class GraphicPlane;
|
||||||
class LayerBaseClient;
|
class LayerBaseClient;
|
||||||
class SurfaceFlinger;
|
class SurfaceFlinger;
|
||||||
class Texture;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -121,7 +119,7 @@ public:
|
||||||
* to perform the actual drawing.
|
* to perform the actual drawing.
|
||||||
*/
|
*/
|
||||||
virtual void draw(const Region& clip) const;
|
virtual void draw(const Region& clip) const;
|
||||||
virtual void drawForSreenShot() const;
|
virtual void drawForSreenShot();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* onDraw - draws the surface.
|
* onDraw - draws the surface.
|
||||||
|
@ -174,9 +172,9 @@ public:
|
||||||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
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
|
* needsDithering - true if this surface needs dithering
|
||||||
|
@ -184,11 +182,9 @@ public:
|
||||||
virtual bool needsDithering() const { return false; }
|
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 {
|
virtual bool needsFiltering() const { return mNeedsFiltering; }
|
||||||
return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isSecure - true if this surface is secure, that is if it prevents
|
* 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,
|
void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
|
||||||
GLclampf b, GLclampf alpha) const;
|
GLclampf b, GLclampf alpha) const;
|
||||||
void clearWithOpenGL(const Region& clip) const;
|
void clearWithOpenGL(const Region& clip) const;
|
||||||
void drawWithOpenGL(const Region& clip, const Texture& texture) const;
|
void drawWithOpenGL(const Region& clip) const;
|
||||||
|
|
||||||
// these must be called from the post/drawing thread
|
void setFiltering(bool filtering);
|
||||||
void setBufferCrop(const Rect& crop);
|
bool getFiltering() const;
|
||||||
void setBufferTransform(uint32_t transform);
|
|
||||||
|
|
||||||
sp<SurfaceFlinger> mFlinger;
|
sp<SurfaceFlinger> mFlinger;
|
||||||
uint32_t mFlags;
|
uint32_t mFlags;
|
||||||
|
|
||||||
// post/drawing thread
|
private:
|
||||||
Rect mBufferCrop;
|
// accessed only in the main thread
|
||||||
uint32_t mBufferTransform;
|
// Whether filtering is forced on or not
|
||||||
|
bool mFiltering;
|
||||||
|
|
||||||
// cached during validateVisibility()
|
// cached during validateVisibility()
|
||||||
|
// Whether filtering is needed b/c of the drawingstate
|
||||||
bool mNeedsFiltering;
|
bool mNeedsFiltering;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// cached during validateVisibility()
|
||||||
int32_t mOrientation;
|
int32_t mOrientation;
|
||||||
GLfloat mVertices[4][2];
|
GLfloat mVertices[4][2];
|
||||||
Rect mTransformedBounds;
|
Rect mTransformedBounds;
|
||||||
|
@ -281,52 +281,38 @@ private:
|
||||||
class LayerBaseClient : public LayerBase
|
class LayerBaseClient : public LayerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class Surface;
|
|
||||||
|
|
||||||
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
||||||
const sp<Client>& client);
|
const sp<Client>& client);
|
||||||
virtual ~LayerBaseClient();
|
|
||||||
|
|
||||||
sp<Surface> getSurface();
|
virtual ~LayerBaseClient();
|
||||||
|
|
||||||
|
sp<ISurface> getSurface();
|
||||||
wp<IBinder> getSurfaceBinder() const;
|
wp<IBinder> getSurfaceBinder() const;
|
||||||
virtual sp<Surface> createSurface() const;
|
|
||||||
virtual sp<LayerBaseClient> getLayerBaseClient() const {
|
virtual sp<LayerBaseClient> getLayerBaseClient() const {
|
||||||
return const_cast<LayerBaseClient*>(this); }
|
return const_cast<LayerBaseClient*>(this); }
|
||||||
|
|
||||||
virtual const char* getTypeId() const { return "LayerBaseClient"; }
|
virtual const char* getTypeId() const { return "LayerBaseClient"; }
|
||||||
|
|
||||||
uint32_t getIdentity() const { return mIdentity; }
|
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:
|
protected:
|
||||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||||
virtual void shortDump(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:
|
private:
|
||||||
|
virtual sp<ISurface> createSurface();
|
||||||
|
|
||||||
mutable Mutex mLock;
|
mutable Mutex mLock;
|
||||||
mutable bool mHasSurface;
|
mutable bool mHasSurface;
|
||||||
wp<IBinder> mClientSurfaceBinder;
|
wp<IBinder> mClientSurfaceBinder;
|
||||||
|
|
|
@ -65,8 +65,6 @@ void LayerDim::onDraw(const Region& clip) const
|
||||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
||||||
|
|
||||||
while (it != end) {
|
while (it != end) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
virtual ~LayerDim();
|
virtual ~LayerDim();
|
||||||
|
|
||||||
virtual void onDraw(const Region& clip) const;
|
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 isSecure() const { return false; }
|
||||||
virtual bool isProtectedByApp() const { return false; }
|
virtual bool isProtectedByApp() const { return false; }
|
||||||
virtual bool isProtectedByDRM() const { return false; }
|
virtual bool isProtectedByDRM() const { return false; }
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#include "DisplayHardware/DisplayHardware.h"
|
#include "DisplayHardware/DisplayHardware.h"
|
||||||
#include "DisplayHardware/HWComposer.h"
|
#include "DisplayHardware/HWComposer.h"
|
||||||
|
|
||||||
|
#include <private/surfaceflinger/SharedBufferStack.h>
|
||||||
|
|
||||||
/* ideally AID_GRAPHICS would be in a semi-public header
|
/* 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
|
* 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;
|
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<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
|
||||||
{
|
{
|
||||||
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
|
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
|
||||||
|
@ -322,11 +313,6 @@ void SurfaceFlinger::signalEvent() {
|
||||||
mEventQueue.invalidate();
|
mEventQueue.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::signal() const {
|
|
||||||
// this is the IPC call
|
|
||||||
const_cast<SurfaceFlinger*>(this)->signalEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
|
bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
|
||||||
Mutex::Autolock _l(mStateLock);
|
Mutex::Autolock _l(mStateLock);
|
||||||
sp<IBinder> surfBinder(surface->asBinder());
|
sp<IBinder> surfBinder(surface->asBinder());
|
||||||
|
@ -658,7 +644,7 @@ void SurfaceFlinger::computeVisibleRegions(
|
||||||
|
|
||||||
// handle hidden surfaces by setting the visible region to empty
|
// handle hidden surfaces by setting the visible region to empty
|
||||||
if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
|
if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
|
||||||
const bool translucent = layer->needsBlending();
|
const bool translucent = !layer->isOpaque();
|
||||||
const Rect bounds(layer->visibleBounds());
|
const Rect bounds(layer->visibleBounds());
|
||||||
visibleRegion.set(bounds);
|
visibleRegion.set(bounds);
|
||||||
visibleRegion.andSelf(screenRegion);
|
visibleRegion.andSelf(screenRegion);
|
||||||
|
@ -921,7 +907,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
if (cur[i].hints & HWC_HINT_CLEAR_FB) {
|
if (cur[i].hints & HWC_HINT_CLEAR_FB) {
|
||||||
const sp<LayerBase>& layer(layers[i]);
|
const sp<LayerBase>& layer(layers[i]);
|
||||||
if (!(layer->needsBlending())) {
|
if (layer->isOpaque()) {
|
||||||
transparent.orSelf(layer->visibleRegionScreen);
|
transparent.orSelf(layer->visibleRegionScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -979,8 +965,6 @@ void SurfaceFlinger::debugFlashRegions()
|
||||||
composeSurfaces(repaint);
|
composeSurfaces(repaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureManager::deactivateTextures();
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDisable(GL_DITHER);
|
glDisable(GL_DITHER);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
@ -1070,6 +1054,7 @@ void SurfaceFlinger::drawWormhole() const
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
}
|
}
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1254,7 @@ sp<ISurface> SurfaceFlinger::createSurface(
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
sp<LayerBaseClient> layer;
|
sp<LayerBaseClient> layer;
|
||||||
sp<LayerBaseClient::Surface> surfaceHandle;
|
sp<ISurface> surfaceHandle;
|
||||||
|
|
||||||
if (int32_t(w|h) < 0) {
|
if (int32_t(w|h) < 0) {
|
||||||
LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
|
LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
|
||||||
|
@ -1300,13 +1285,13 @@ sp<ISurface> SurfaceFlinger::createSurface(
|
||||||
surfaceHandle = layer->getSurface();
|
surfaceHandle = layer->getSurface();
|
||||||
if (surfaceHandle != 0) {
|
if (surfaceHandle != 0) {
|
||||||
params->token = token;
|
params->token = token;
|
||||||
params->identity = surfaceHandle->getIdentity();
|
params->identity = layer->getIdentity();
|
||||||
params->width = w;
|
params->width = w;
|
||||||
params->height = h;
|
params->height = h;
|
||||||
params->format = format;
|
params->format = format;
|
||||||
if (normalLayer != 0) {
|
if (normalLayer != 0) {
|
||||||
Mutex::Autolock _l(mStateLock);
|
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];
|
GLfloat vtx[8];
|
||||||
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
|
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tname);
|
glBindTexture(GL_TEXTURE_2D, tname);
|
||||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
@ -1900,6 +1884,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
glDeleteTextures(1, &tname);
|
glDeleteTextures(1, &tname);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1930,7 +1915,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
|
||||||
|
|
||||||
GLfloat vtx[8];
|
GLfloat vtx[8];
|
||||||
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
|
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tname);
|
glBindTexture(GL_TEXTURE_2D, tname);
|
||||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
@ -2044,6 +2028,7 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
glDeleteTextures(1, &tname);
|
glDeleteTextures(1, &tname);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -2408,20 +2393,72 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
|
||||||
return lbc;
|
return lbc;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<IMemoryHeap> Client::getControlBlock() const {
|
|
||||||
return 0;
|
status_t Client::onTransact(
|
||||||
}
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||||
ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
|
{
|
||||||
return -1;
|
// 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(
|
sp<ISurface> Client::createSurface(
|
||||||
ISurfaceComposerClient::surface_data_t* params,
|
ISurfaceComposerClient::surface_data_t* params,
|
||||||
const String8& name,
|
const String8& name,
|
||||||
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
|
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
|
||||||
uint32_t flags)
|
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) {
|
status_t Client::destroySurface(SurfaceID sid) {
|
||||||
return mFlinger->removeSurface(this, 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() {}
|
||||||
|
|
||||||
GraphicBufferAlloc::~GraphicBufferAlloc() {}
|
GraphicBufferAlloc::~GraphicBufferAlloc() {}
|
||||||
|
@ -2547,11 +2477,11 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h
|
||||||
PixelFormat format, uint32_t usage) {
|
PixelFormat format, uint32_t usage) {
|
||||||
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
|
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
|
||||||
status_t err = graphicBuffer->initCheck();
|
status_t err = graphicBuffer->initCheck();
|
||||||
if (err != 0) {
|
if (err != 0 || graphicBuffer->handle == 0) {
|
||||||
LOGE("createGraphicBuffer: init check failed: %d", err);
|
GraphicBuffer::dumpAllocationsToSystemLog();
|
||||||
return 0;
|
LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
|
||||||
} else if (graphicBuffer->handle == 0) {
|
"failed (%s), handle=%p",
|
||||||
LOGE("createGraphicBuffer: unable to create GraphicBuffer");
|
w, h, strerror(-err), graphicBuffer->handle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return graphicBuffer;
|
return graphicBuffer;
|
||||||
|
|
|
@ -50,6 +50,7 @@ class DisplayHardware;
|
||||||
class FreezeLock;
|
class FreezeLock;
|
||||||
class Layer;
|
class Layer;
|
||||||
class LayerDim;
|
class LayerDim;
|
||||||
|
struct surface_flinger_cblk_t;
|
||||||
|
|
||||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||||
|
@ -72,14 +73,14 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// ISurfaceComposerClient interface
|
// ISurfaceComposerClient interface
|
||||||
virtual sp<IMemoryHeap> getControlBlock() const;
|
|
||||||
virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
|
|
||||||
virtual sp<ISurface> createSurface(
|
virtual sp<ISurface> createSurface(
|
||||||
surface_data_t* params, const String8& name,
|
surface_data_t* params, const String8& name,
|
||||||
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
|
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
|
||||||
uint32_t flags);
|
uint32_t flags);
|
||||||
virtual status_t destroySurface(SurfaceID surfaceId);
|
virtual status_t destroySurface(SurfaceID surfaceId);
|
||||||
virtual status_t setState(int32_t count, const layer_state_t* states);
|
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
|
// constant
|
||||||
sp<SurfaceFlinger> mFlinger;
|
sp<SurfaceFlinger> mFlinger;
|
||||||
|
@ -92,40 +93,6 @@ private:
|
||||||
mutable Mutex mLock;
|
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
|
class GraphicBufferAlloc : public BnGraphicBufferAlloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -199,7 +166,6 @@ public:
|
||||||
|
|
||||||
// ISurfaceComposer interface
|
// ISurfaceComposer interface
|
||||||
virtual sp<ISurfaceComposerClient> createConnection();
|
virtual sp<ISurfaceComposerClient> createConnection();
|
||||||
virtual sp<ISurfaceComposerClient> createClientConnection();
|
|
||||||
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
|
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
|
||||||
virtual sp<IMemoryHeap> getCblk() const;
|
virtual sp<IMemoryHeap> getCblk() const;
|
||||||
virtual void bootFinished();
|
virtual void bootFinished();
|
||||||
|
@ -208,7 +174,6 @@ public:
|
||||||
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
|
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
|
||||||
virtual status_t unfreezeDisplay(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 int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
|
||||||
virtual void signal() const;
|
|
||||||
virtual bool authenticateSurface(const sp<ISurface>& surface) const;
|
virtual bool authenticateSurface(const sp<ISurface>& surface) const;
|
||||||
|
|
||||||
virtual status_t captureScreen(DisplayID dpy,
|
virtual status_t captureScreen(DisplayID dpy,
|
||||||
|
@ -235,7 +200,6 @@ private:
|
||||||
friend class Client;
|
friend class Client;
|
||||||
friend class LayerBase;
|
friend class LayerBase;
|
||||||
friend class LayerBaseClient;
|
friend class LayerBaseClient;
|
||||||
friend class LayerBaseClient::Surface;
|
|
||||||
friend class Layer;
|
friend class Layer;
|
||||||
friend class LayerDim;
|
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 {
|
namespace android {
|
||||||
|
|
||||||
int clz_impl(int32_t x);
|
int inline clz(int32_t x) {
|
||||||
|
|
||||||
int inline clz(int32_t x)
|
|
||||||
{
|
|
||||||
#if defined(__arm__) && !defined(__thumb__)
|
|
||||||
return __builtin_clz(x);
|
return __builtin_clz(x);
|
||||||
#else
|
|
||||||
return clz_impl(x);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|
||||||
#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
|
#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
|
||||||
|
|
Loading…
Reference in New Issue