diff options
| -rw-r--r-- | include/binder/Parcel.h | 11 | ||||
| -rw-r--r-- | include/private/ui/android_natives_priv.h | 4 | ||||
| -rw-r--r-- | include/ui/ISurfaceComposer.h | 2 | ||||
| -rw-r--r-- | include/ui/Surface.h | 52 | ||||
| -rw-r--r-- | include/ui/egl/android_natives.h | 16 | ||||
| -rw-r--r-- | include/utils/Debug.h | 2 | ||||
| -rw-r--r-- | libs/binder/Parcel.cpp | 158 | ||||
| -rw-r--r-- | libs/surfaceflinger/Layer.cpp | 10 | ||||
| -rw-r--r-- | libs/surfaceflinger/LayerBitmap.h | 2 | ||||
| -rw-r--r-- | libs/ui/Surface.cpp | 75 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl.cpp | 198 | ||||
| -rw-r--r-- | opengl/libs/egl_impl.h | 1 | ||||
| -rw-r--r-- | opengl/libs/hooks.h | 6 |
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 }; |