summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/binder/Parcel.h11
-rw-r--r--include/private/ui/android_natives_priv.h4
-rw-r--r--include/ui/ISurfaceComposer.h2
-rw-r--r--include/ui/Surface.h52
-rw-r--r--include/ui/egl/android_natives.h16
-rw-r--r--include/utils/Debug.h2
-rw-r--r--libs/binder/Parcel.cpp158
-rw-r--r--libs/surfaceflinger/Layer.cpp10
-rw-r--r--libs/surfaceflinger/LayerBitmap.h2
-rw-r--r--libs/ui/Surface.cpp75
-rw-r--r--opengl/libs/EGL/egl.cpp198
-rw-r--r--opengl/libs/egl_impl.h1
-rw-r--r--opengl/libs/hooks.h6
13 files changed, 279 insertions, 258 deletions
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 58c2d9ad76..ba6c7111f5 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -74,6 +74,7 @@ public:
status_t writeInt64(int64_t val);
status_t writeFloat(float val);
status_t writeDouble(double val);
+ status_t writeIntPtr(intptr_t val);
status_t writeCString(const char* str);
status_t writeString8(const String8& str);
status_t writeString16(const String16& str);
@@ -109,6 +110,8 @@ public:
status_t readFloat(float *pArg) const;
double readDouble() const;
status_t readDouble(double *pArg) const;
+ intptr_t readIntPtr() const;
+ status_t readIntPtr(intptr_t *pArg) const;
const char* readCString() const;
String8 readString8() const;
@@ -163,6 +166,14 @@ private:
void initState();
void scanForFds() const;
+ template<class T>
+ status_t readAligned(T *pArg) const;
+
+ template<class T> T readAligned() const;
+
+ template<class T>
+ status_t writeAligned(T val);
+
status_t mError;
uint8_t* mData;
size_t mDataSize;
diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h
index ee843e9281..9c92af8845 100644
--- a/include/private/ui/android_natives_priv.h
+++ b/include/private/ui/android_natives_priv.h
@@ -25,7 +25,7 @@ extern "C" {
/*****************************************************************************/
-struct android_native_buffer_t
+typedef struct android_native_buffer_t
{
#ifdef __cplusplus
android_native_buffer_t() {
@@ -48,7 +48,7 @@ struct android_native_buffer_t
buffer_handle_t handle;
void* reserved_proc[8];
-};
+} android_native_buffer_t;
/*****************************************************************************/
diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h
index 1788265b58..25d954c3d3 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/ui/ISurfaceComposer.h
@@ -40,8 +40,6 @@ public:
enum { // (keep in sync with Surface.java)
eHidden = 0x00000004,
- eGPU = 0x00000008,
- eHardware = 0x00000010,
eDestroyBackbuffer = 0x00000020,
eSecure = 0x00000080,
eNonPremultiplied = 0x00000100,
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 4ff0e4abd8..30ab82f803 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -146,16 +146,16 @@ public:
static bool isValid(const sp<Surface>& surface) {
return (surface != 0) && surface->isValid();
}
- bool isValid() {
- return mToken>=0 && mClient!=0;
- }
+
static bool isSameSurface(
const sp<Surface>& lhs, const sp<Surface>& rhs);
- SurfaceID ID() const { return mToken; }
- uint32_t getFlags() const { return mFlags; }
- uint32_t getIdentity() const { return mIdentity; }
+ bool isValid();
+ SurfaceID ID() const { return mToken; }
+ uint32_t getFlags() const { return mFlags; }
+ uint32_t getIdentity() const { return mIdentity; }
+ // the lock/unlock APIs must be used from the same thread
status_t lock(SurfaceInfo* info, bool blocking = true);
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
status_t unlockAndPost();
@@ -175,14 +175,18 @@ private:
friend class SurfaceComposerClient;
friend class SurfaceControl;
+
// camera and camcorder need access to the ISurface binder interface for preview
friend class Camera;
friend class MediaRecorder;
// mediaplayer needs access to ISurface for display
friend class MediaPlayer;
- friend class Test;
friend class IOMX;
- const sp<ISurface>& getISurface() const { return mSurface; }
+ // this is just to be able to write some unit tests
+ friend class Test;
+
+ sp<SurfaceComposerClient> getClient() const;
+ sp<ISurface> getISurface() const;
status_t getBufferLocked(int index, int usage);
@@ -210,24 +214,38 @@ private:
status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
- alloc_device_t* mAllocDevice;
+ void setUsage(uint32_t reqUsage);
+
+ // constants
sp<SurfaceComposerClient> mClient;
sp<ISurface> mSurface;
- sp<SurfaceBuffer> mBuffers[2];
- sp<SurfaceBuffer> mLockedBuffer;
SurfaceID mToken;
uint32_t mIdentity;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mUsage;
PixelFormat mFormat;
uint32_t mFlags;
+ BufferMapper& mBufferMapper;
+
+ // protected by mSurfaceLock
+ Rect mSwapRectangle;
+ uint32_t mUsage;
+ bool mUsageChanged;
+
+ // protected by mSurfaceLock. These are also used from lock/unlock
+ // but in that case, they must be called form the same thread.
+ sp<SurfaceBuffer> mBuffers[2];
mutable Region mDirtyRegion;
- mutable Region mOldDirtyRegion;
mutable uint8_t mBackbufferIndex;
+
+ // must be used from the lock/unlock thread
+ sp<SurfaceBuffer> mLockedBuffer;
+ mutable Region mOldDirtyRegion;
+
+ // query() must be called from dequeueBuffer() thread
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ // Inherently thread-safe
mutable Mutex mSurfaceLock;
- Rect mSwapRectangle;
- BufferMapper& mBufferMapper;
};
}; // namespace android
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 4c58e474c6..3740db5d95 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -43,7 +43,7 @@ struct android_native_buffer_t;
// ---------------------------------------------------------------------------
-struct android_native_base_t
+typedef struct android_native_base_t
{
/* a magic value defined by the actual EGL native type */
int magic;
@@ -56,7 +56,7 @@ struct android_native_base_t
/* reference-counting interface */
void (*incRef)(struct android_native_base_t* base);
void (*decRef)(struct android_native_base_t* base);
-};
+} android_native_base_t;
// ---------------------------------------------------------------------------
@@ -72,7 +72,7 @@ enum {
NATIVE_WINDOW_SET_USAGE = 0
};
-struct android_native_window_t
+typedef struct android_native_window_t
{
#ifdef __cplusplus
android_native_window_t()
@@ -166,7 +166,7 @@ struct android_native_window_t
int operation, ... );
void* reserved_proc[3];
-};
+} android_native_window_t;
/*
@@ -179,8 +179,8 @@ struct android_native_window_t
* reallocated.
*/
-inline int native_window_set_usage(
- struct android_native_window_t* window, int usage)
+static inline int native_window_set_usage(
+ android_native_window_t* window, int usage)
{
return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
}
@@ -189,7 +189,7 @@ inline int native_window_set_usage(
// ---------------------------------------------------------------------------
/* FIXME: this is legacy for pixmaps */
-struct egl_native_pixmap_t
+typedef struct egl_native_pixmap_t
{
int32_t version; /* must be 32 */
int32_t width;
@@ -203,7 +203,7 @@ struct egl_native_pixmap_t
int32_t vstride;
};
int32_t reserved;
-};
+} egl_native_pixmap_t;
/*****************************************************************************/
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index 21d04bdcec..d9ed32d7df 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -29,6 +29,8 @@ template<> struct CompileTimeAssert<true> {};
#define COMPILE_TIME_ASSERT(_exp) \
template class CompileTimeAssert< (_exp) >;
#endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+ CompileTimeAssert<( _exp )>();
// ---------------------------------------------------------------------------
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 785a3c5ddb..e397bce1cf 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -562,54 +562,27 @@ restart_write:
status_t Parcel::writeInt32(int32_t val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<int32_t*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
-
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+ return writeAligned(val);
}
status_t Parcel::writeInt64(int64_t val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<int64_t*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
-
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+ return writeAligned(val);
}
status_t Parcel::writeFloat(float val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<float*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
-
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+ return writeAligned(val);
}
status_t Parcel::writeDouble(double val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<double*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
+ return writeAligned(val);
+}
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+status_t Parcel::writeIntPtr(intptr_t val)
+{
+ return writeAligned(val);
}
status_t Parcel::writeCString(const char* str)
@@ -768,103 +741,98 @@ const void* Parcel::readInplace(size_t len) const
return NULL;
}
-status_t Parcel::readInt32(int32_t *pArg) const
-{
- if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
+template<class T>
+status_t Parcel::readAligned(T *pArg) const {
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+ if ((mDataPos+sizeof(T)) <= mDataSize) {
const void* data = mData+mDataPos;
- mDataPos += sizeof(int32_t);
- *pArg = *reinterpret_cast<const int32_t*>(data);
+ mDataPos += sizeof(T);
+ *pArg = *reinterpret_cast<const T*>(data);
return NO_ERROR;
} else {
return NOT_ENOUGH_DATA;
}
}
+template<class T>
+T Parcel::readAligned() const {
+ T result;
+ if (readAligned(&result) != NO_ERROR) {
+ result = 0;
+ }
+
+ return result;
+}
+
+template<class T>
+status_t Parcel::writeAligned(T val) {
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+ if ((mDataPos+sizeof(val)) <= mDataCapacity) {
+restart_write:
+ *reinterpret_cast<T*>(mData+mDataPos) = val;
+ return finishWrite(sizeof(val));
+ }
+
+ status_t err = growData(sizeof(val));
+ if (err == NO_ERROR) goto restart_write;
+ return err;
+}
+
+status_t Parcel::readInt32(int32_t *pArg) const
+{
+ return readAligned(pArg);
+}
+
int32_t Parcel::readInt32() const
{
- if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(int32_t);
- LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const int32_t*>(data);
- }
- return 0;
+ return readAligned<int32_t>();
}
status_t Parcel::readInt64(int64_t *pArg) const
{
- if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(int64_t);
- *pArg = *reinterpret_cast<const int64_t*>(data);
- LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
- return NO_ERROR;
- } else {
- return NOT_ENOUGH_DATA;
- }
+ return readAligned(pArg);
}
int64_t Parcel::readInt64() const
{
- if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(int64_t);
- LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const int64_t*>(data);
- }
- return 0;
+ return readAligned<int64_t>();
}
status_t Parcel::readFloat(float *pArg) const
{
- if ((mDataPos+sizeof(float)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(float);
- LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
- *pArg = *reinterpret_cast<const float*>(data);
- return NO_ERROR;
- } else {
- return NOT_ENOUGH_DATA;
- }
+ return readAligned(pArg);
}
float Parcel::readFloat() const
{
- if ((mDataPos+sizeof(float)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(float);
- LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const float*>(data);
- }
- return 0;
+ return readAligned<float>();
}
status_t Parcel::readDouble(double *pArg) const
{
- if ((mDataPos+sizeof(double)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(double);
- LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
- *pArg = *reinterpret_cast<const double*>(data);
- return NO_ERROR;
- } else {
- return NOT_ENOUGH_DATA;
- }
+ return readAligned(pArg);
}
double Parcel::readDouble() const
{
- if ((mDataPos+sizeof(double)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(double);
- LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const double*>(data);
- }
- return 0;
+ return readAligned<double>();
+}
+
+status_t Parcel::readIntPtr(intptr_t *pArg) const
+{
+ return readAligned(pArg);
+}
+
+
+intptr_t Parcel::readIntPtr() const
+{
+ return readAligned<intptr_t>();
}
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 8c0b40d9e4..6f92515c32 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -109,9 +109,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
if (err) return err;
uint32_t bufferFlags = 0;
- if (flags & ISurfaceComposer::eGPU)
- bufferFlags |= Buffer::GPU;
-
if (flags & ISurfaceComposer::eSecure)
bufferFlags |= Buffer::SECURE;
@@ -599,7 +596,12 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
Point Layer::getPhysicalSize() const
{
sp<const Buffer> front(frontBuffer().getBuffer());
- return Point(front->getWidth(), front->getHeight());
+ Point size(front->getWidth(), front->getHeight());
+ if ((size.x | size.y) == 0) {
+ // if we don't have a buffer yet, just use the state's size.
+ size = LayerBase::getPhysicalSize();
+ }
+ return size;
}
void Layer::unlockPageFlip(
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 48ee553e52..87e8f42b14 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -53,7 +53,6 @@ class Buffer : public SurfaceBuffer
public:
enum {
DONT_CLEAR = 0x00000001,
- GPU = 0x00000002,
SECURE = 0x00000004
};
@@ -98,7 +97,6 @@ class LayerBitmap
public:
enum {
DONT_CLEAR = Buffer::DONT_CLEAR,
- GPU = Buffer::GPU,
SECURE = Buffer::SECURE
};
LayerBitmap();
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 2b6905f33f..f6792c4595 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -382,9 +382,9 @@ sp<Surface> SurfaceControl::getSurface() const
Surface::Surface(const sp<SurfaceControl>& surface)
: mClient(surface->mClient), mSurface(surface->mSurface),
mToken(surface->mToken), mIdentity(surface->mIdentity),
- mWidth(surface->mWidth), mHeight(surface->mHeight),
mFormat(surface->mFormat), mFlags(surface->mFlags),
- mBufferMapper(BufferMapper::get())
+ mBufferMapper(BufferMapper::get()),
+ mWidth(surface->mWidth), mHeight(surface->mHeight)
{
init();
}
@@ -426,9 +426,9 @@ void Surface::init()
const_cast<uint32_t&>(android_native_window_t::flags) = 0;
// be default we request a hardware surface
mUsage = GRALLOC_USAGE_HW_RENDER;
+ mUsageChanged = true;
}
-
Surface::~Surface()
{
// this is a client-side operation, the surface is destroyed, unmap
@@ -446,11 +446,24 @@ Surface::~Surface()
IPCThreadState::self()->flushCommands();
}
+sp<SurfaceComposerClient> Surface::getClient() const {
+ return mClient;
+}
+
+sp<ISurface> Surface::getISurface() const {
+ return mSurface;
+}
+
+bool Surface::isValid() {
+ return mToken>=0 && mClient!=0;
+}
+
status_t Surface::validate(per_client_cblk_t const* cblk) const
{
+ sp<SurfaceComposerClient> client(getClient());
if (mToken<0 || mClient==0) {
LOGE("invalid token (%d, identity=%u) or client (%p)",
- mToken, mIdentity, mClient.get());
+ mToken, mIdentity, client.get());
return NO_INIT;
}
if (cblk == 0) {
@@ -477,6 +490,7 @@ bool Surface::isSameSurface(
{
if (lhs == 0 || rhs == 0)
return false;
+
return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
}
@@ -532,10 +546,9 @@ status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
{
android_native_buffer_t* out;
status_t err = dequeueBuffer(&out);
- *buffer = SurfaceBuffer::getSelf(out);
- // reset the width/height with the what we get from the buffer
- mWidth = uint32_t(out->width);
- mHeight = uint32_t(out->height);
+ if (err == NO_ERROR) {
+ *buffer = SurfaceBuffer::getSelf(out);
+ }
return err;
}
@@ -557,7 +570,8 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
Mutex::Autolock _l(mSurfaceLock);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk);
if (err != NO_ERROR)
return err;
@@ -572,14 +586,17 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
mBackbufferIndex = backIdx;
layer_cblk_t* const lcblk = &(cblk->layers[index]);
-
volatile const surface_info_t* const back = lcblk->surface + backIdx;
- if (back->flags & surface_info_t::eNeedNewBuffer) {
+ if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
+ mUsageChanged = false;
err = getBufferLocked(backIdx, mUsage);
}
if (err == NO_ERROR) {
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+ // reset the width/height with the what we get from the buffer
+ mWidth = uint32_t(backBuffer->width);
+ mHeight = uint32_t(backBuffer->height);
mDirtyRegion.set(backBuffer->width, backBuffer->height);
*buffer = backBuffer.get();
}
@@ -591,7 +608,8 @@ int Surface::lockBuffer(android_native_buffer_t* buffer)
{
Mutex::Autolock _l(mSurfaceLock);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk);
if (err != NO_ERROR)
return err;
@@ -604,7 +622,8 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
{
Mutex::Autolock _l(mSurfaceLock);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk);
if (err != NO_ERROR)
return err;
@@ -620,7 +639,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
if (!(newstate & eNextFlipPending))
- mClient->signalServer();
+ client->signalServer();
return NO_ERROR;
}
@@ -646,7 +665,7 @@ int Surface::perform(int operation, va_list args)
int res = NO_ERROR;
switch (operation) {
case NATIVE_WINDOW_SET_USAGE:
- mUsage = va_arg(args, int);
+ setUsage( va_arg(args, int) );
break;
default:
res = NAME_NOT_FOUND;
@@ -655,6 +674,15 @@ int Surface::perform(int operation, va_list args)
return res;
}
+void Surface::setUsage(uint32_t reqUsage)
+{
+ Mutex::Autolock _l(mSurfaceLock);
+ if (mUsage != reqUsage) {
+ mUsageChanged = true;
+ mUsage = reqUsage;
+ }
+}
+
// ----------------------------------------------------------------------------
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -663,11 +691,9 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) {
status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
{
- // FIXME: needs some locking here
-
// we're intending to do software rendering from this point
- mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
-
+ setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
sp<SurfaceBuffer> backBuffer;
status_t err = dequeueBuffer(&backBuffer);
if (err == NO_ERROR) {
@@ -679,7 +705,8 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
Region scratch(bounds);
Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
if (back->flags & surface_info_t::eBufferDirty) {
@@ -725,8 +752,6 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
status_t Surface::unlockAndPost()
{
- // FIXME: needs some locking here
-
if (mLockedBuffer == 0)
return BAD_VALUE;
@@ -753,13 +778,17 @@ void Surface::_send_dirty_region(
}
void Surface::setSwapRectangle(const Rect& r) {
+ Mutex::Autolock _l(mSurfaceLock);
mSwapRectangle = r;
}
status_t Surface::getBufferLocked(int index, int usage)
{
+ sp<ISurface> s(mSurface);
+ if (s == 0) return NO_INIT;
+
status_t err = NO_MEMORY;
- sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
+ sp<SurfaceBuffer> buffer = s->getBuffer(usage);
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
if (buffer != 0) {
sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 64b82eb4bd..03e764cccf 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -50,7 +50,7 @@ namespace android {
#define VERSION_MAJOR 1
#define VERSION_MINOR 4
static char const * const gVendorString = "Android";
-static char const * const gVersionString = "1.31 Android META-EGL";
+static char const * const gVersionString = "1.4 Android META-EGL";
static char const * const gClientApiString = "OpenGL ES";
static char const * const gExtensionString =
"EGL_KHR_image "
@@ -326,32 +326,6 @@ static void(*findProcAddress(const char* name,
// ----------------------------------------------------------------------------
-/*
- * To "loose" the GPU, use something like
- * gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
- *
- */
-
-static int gl_context_lost() {
- setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
- return 0;
-}
-static int egl_context_lost() {
- setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
- return EGL_FALSE;
-}
-static EGLBoolean egl_context_lost_swap_buffers(void*, void*) {
- usleep(100000); // don't use all the CPU
- setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
- return EGL_FALSE;
-}
-static GLint egl_context_lost_get_error() {
- return EGL_CONTEXT_LOST;
-}
-static int ext_context_lost() {
- return 0;
-}
-
static void gl_no_context() {
tls_t* tls = getTLS();
if (tls->logCallWithNoContext == EGL_TRUE) {
@@ -471,87 +445,82 @@ EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
return i->images[c->impl];
}
+// ----------------------------------------------------------------------------
+
+// this mutex protects:
+// d->dpys[]
+// egl_init_drivers_locked()
+//
+static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
-EGLDisplay egl_init_displays(NativeDisplayType display)
+EGLBoolean egl_init_drivers_locked()
{
if (sEarlyInitState) {
- return EGL_NO_DISPLAY;
- }
-
- uint32_t index = uint32_t(display);
- if (index >= NUM_DISPLAYS) {
- return EGL_NO_DISPLAY;
+ // initialized by static ctor. should be set here.
+ return EGL_FALSE;
}
-
- EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
- egl_display_t* d = &gDisplay[index];
// get our driver loader
- Loader& loader(Loader::getInstance());
+ Loader& loader(Loader::getInstance());
- // dynamically load all our EGL implementations for that display
- // and call into the real eglGetGisplay()
- egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
+ // dynamically load all our EGL implementations for all displays
+ // and retrieve the corresponding EGLDisplay
+ // if that fails, don't use this driver.
+ // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+ egl_connection_t* cnx;
+ egl_display_t* d = &gDisplay[0];
+
+ cnx = &gEGLImpl[IMPL_SOFTWARE];
if (cnx->dso == 0) {
cnx->hooks = &gHooks[IMPL_SOFTWARE];
- cnx->dso = loader.open(display, 0, cnx->hooks);
- }
- if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) {
- d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display);
- LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY,
- "No EGLDisplay for software EGL!");
+ cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
+ if (cnx->dso) {
+ EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
+ d->dpys[IMPL_SOFTWARE] = dpy;
+ if (dpy == EGL_NO_DISPLAY) {
+ loader.close(cnx->dso);
+ cnx->dso = NULL;
+ }
+ }
}
cnx = &gEGLImpl[IMPL_HARDWARE];
- if (cnx->dso == 0 && cnx->unavailable == 0) {
+ if (cnx->dso == 0) {
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.hw", value, "1");
if (atoi(value) != 0) {
cnx->hooks = &gHooks[IMPL_HARDWARE];
- cnx->dso = loader.open(display, 1, cnx->hooks);
+ cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
+ if (cnx->dso) {
+ EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
+ d->dpys[IMPL_HARDWARE] = dpy;
+ if (dpy == EGL_NO_DISPLAY) {
+ loader.close(cnx->dso);
+ cnx->dso = NULL;
+ }
+ }
} else {
LOGD("3D hardware acceleration is disabled");
}
}
- if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) {
- android_memset32(
- (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl,
- (uint32_t)((void*)gl_context_lost),
- sizeof(gHooks[IMPL_CONTEXT_LOST].gl));
- android_memset32(
- (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl,
- (uint32_t)((void*)egl_context_lost),
- sizeof(gHooks[IMPL_CONTEXT_LOST].egl));
- android_memset32(
- (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext,
- (uint32_t)((void*)ext_context_lost),
- sizeof(gHooks[IMPL_CONTEXT_LOST].ext));
-
- gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers =
- egl_context_lost_swap_buffers;
-
- gHooks[IMPL_CONTEXT_LOST].egl.eglGetError =
- egl_context_lost_get_error;
-
- gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate =
- gHooks[IMPL_HARDWARE].egl.eglTerminate;
-
- d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display);
- if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) {
- LOGE("h/w accelerated eglGetDisplay() failed (%s)",
- egl_strerror(cnx->hooks->egl.eglGetError()));
-
- loader.close(cnx->dso);
- cnx->dso = 0;
- // in case of failure, we want to make sure we don't try again
- // as it's expensive.
- cnx->unavailable = 1;
- }
+
+ if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
+ return EGL_FALSE;
}
- return dpy;
+ return EGL_TRUE;
}
+EGLBoolean egl_init_drivers()
+{
+ EGLBoolean res;
+ pthread_mutex_lock(&gInitDriverMutex);
+ res = egl_init_drivers_locked();
+ pthread_mutex_unlock(&gInitDriverMutex);
+ return res;
+}
// ----------------------------------------------------------------------------
}; // namespace android
@@ -561,7 +530,17 @@ using namespace android;
EGLDisplay eglGetDisplay(NativeDisplayType display)
{
- return egl_init_displays(display);
+ uint32_t index = uint32_t(display);
+ if (index >= NUM_DISPLAYS) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+ }
+
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+ }
+
+ EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
+ return dpy;
}
// ----------------------------------------------------------------------------
@@ -648,31 +627,25 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
EGLBoolean eglTerminate(EGLDisplay dpy)
{
+ // NOTE: don't unload the drivers b/c some APIs can be called
+ // after eglTerminate() has been called. eglTerminate() only
+ // terminates an EGLDisplay, not a EGL itself.
+
egl_display_t* const dp = get_display(dpy);
if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
if (android_atomic_dec(&dp->refs) != 1)
return EGL_TRUE;
-
- Loader& loader(Loader::getInstance());
EGLBoolean res = EGL_FALSE;
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
cnx->hooks->egl.eglTerminate(dp->dpys[i]);
-
- /* REVISIT: it's unclear what to do if eglTerminate() fails,
- * on one end we shouldn't care, on the other end if it fails
- * it might not be safe to call dlclose() (there could be some
- * threads around). */
-
+ // REVISIT: it's unclear what to do if eglTerminate() fails
free(dp->configs[i]);
free((void*)dp->queryString[i].extensions);
dp->numConfigs[i] = 0;
dp->dpys[i] = EGL_NO_DISPLAY;
-
- loader.close(cnx->dso);
- cnx->dso = 0;
res = EGL_TRUE;
}
}
@@ -1022,12 +995,18 @@ EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
EGLContext eglGetCurrentContext(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would correctly return EGL_NO_CONTEXT.
+
EGLContext ctx = getContext();
return ctx;
}
EGLSurface eglGetCurrentSurface(EGLint readdraw)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would correctly return EGL_NO_SURFACE.
+
EGLContext ctx = getContext();
if (ctx) {
egl_context_t const * const c = get_context(ctx);
@@ -1043,6 +1022,9 @@ EGLSurface eglGetCurrentSurface(EGLint readdraw)
EGLDisplay eglGetCurrentDisplay(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would correctly return EGL_NO_DISPLAY.
+
EGLContext ctx = getContext();
if (ctx) {
egl_context_t const * const c = get_context(ctx);
@@ -1054,6 +1036,9 @@ EGLDisplay eglGetCurrentDisplay(void)
EGLBoolean eglWaitGL(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would return GL_TRUE, which isn't wrong.
+
EGLBoolean res = EGL_TRUE;
EGLContext ctx = getContext();
if (ctx) {
@@ -1071,6 +1056,9 @@ EGLBoolean eglWaitGL(void)
EGLBoolean eglWaitNative(EGLint engine)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would return GL_TRUE, which isn't wrong.
+
EGLBoolean res = EGL_TRUE;
EGLContext ctx = getContext();
if (ctx) {
@@ -1107,9 +1095,11 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
// eglGetProcAddress() could be the very first function called
// in which case we must make sure we've initialized ourselves, this
// happens the first time egl_get_display() is called.
-
- if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
- return NULL;
+
+ if (egl_init_drivers() == EGL_FALSE) {
+ setError(EGL_BAD_PARAMETER, NULL);
+ return NULL;
+ }
__eglMustCastToProperFunctionPointerType addr;
addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
@@ -1275,6 +1265,8 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
EGLBoolean eglWaitClient(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would return GL_TRUE, which isn't wrong.
EGLBoolean res = EGL_TRUE;
EGLContext ctx = getContext();
if (ctx) {
@@ -1296,6 +1288,10 @@ EGLBoolean eglWaitClient(void)
EGLBoolean eglBindAPI(EGLenum api)
{
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
// bind this API on all EGLs
EGLBoolean res = EGL_TRUE;
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
@@ -1313,6 +1309,10 @@ EGLBoolean eglBindAPI(EGLenum api)
EGLenum eglQueryAPI(void)
{
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index c5f753d56a..ac286cb21d 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -35,7 +35,6 @@ struct egl_connection_t
gl_hooks_t * hooks;
EGLint major;
EGLint minor;
- int unavailable;
};
EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 37292eef07..8c0357e87a 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -60,12 +60,8 @@ const unsigned int NUM_DISPLAYS = 1;
enum {
IMPL_HARDWARE = 0,
IMPL_SOFTWARE,
-
IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-
- IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
- IMPL_NO_CONTEXT,
-
+ IMPL_NO_CONTEXT = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
IMPL_NUM_IMPLEMENTATIONS
};