diff options
author | Mathias Agopian <mathias@google.com> | 2009-04-10 14:24:30 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-04-10 14:24:30 -0700 |
commit | 076b1cc3a9b90aa5b381a1ed268ca0b548444c9b (patch) | |
tree | b87f7863623b37fa9a6cc4ef48934aab46f79986 | |
parent | 4ec21527096d0dcaa99634e6058aca3a415461af (diff) | |
download | frameworks_native-076b1cc3a9b90aa5b381a1ed268ca0b548444c9b.zip frameworks_native-076b1cc3a9b90aa5b381a1ed268ca0b548444c9b.tar.gz frameworks_native-076b1cc3a9b90aa5b381a1ed268ca0b548444c9b.tar.bz2 |
Integrate from //sandbox/mathias/donut/...@145728
SurfaceFlinger rework for new EGL driver model support.
79 files changed, 5702 insertions, 3129 deletions
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h index 0c7ad46..641961f 100644 --- a/include/private/opengles/gl_context.h +++ b/include/private/opengles/gl_context.h @@ -26,6 +26,7 @@ #endif #include <private/pixelflinger/ggl_context.h> +#include <hardware/copybit.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -39,7 +40,7 @@ class EGLSurfaceManager; class EGLBufferObjectManager; namespace gl { - + struct ogles_context_t; struct matrixx_t; struct transform_t; @@ -96,7 +97,7 @@ struct vec4_t { struct vertex_t { enum { - // these constant matter for our clipping + // these constant matter for our clipping CLIP_L = 0x0001, // clipping flags CLIP_R = 0x0002, CLIP_B = 0x0004, @@ -106,7 +107,7 @@ struct vertex_t { EYE = 0x0040, RESERVED = 0x0080, - + USER_CLIP_0 = 0x0100, // user clipping flags USER_CLIP_1 = 0x0200, USER_CLIP_2 = 0x0400, @@ -121,7 +122,7 @@ struct vertex_t { USER_CLIP_ALL = 0x3F00, CLIP_ALL = 0x3F3F, }; - + // the fields below are arranged to minimize d-cache usage // we group together, by cache-line, the fields most likely to be used @@ -130,7 +131,7 @@ struct vertex_t { vec4_t eye; }; vec4_t clip; - + uint32_t flags; size_t index; // cache tag, and vertex index GLfixed fog; @@ -142,7 +143,7 @@ struct vertex_t { vec4_t color; vec4_t texture[GGL_TEXTURE_UNIT_COUNT]; uint32_t reserved1[4]; - + inline void clear() { flags = index = locked = mru = 0; } @@ -199,7 +200,7 @@ struct array_machine_t { GLenum indicesType; buffer_t const* array_buffer; buffer_t const* element_array_buffer; - + void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei); void (*compileElement)(ogles_context_t*, vertex_t*, GLint); @@ -410,7 +411,7 @@ struct transform_t { matrixx_t matrix; uint32_t flags; uint32_t ops; - + union { struct { void (*point2)(transform_t const* t, vec4_t*, vec4_t const*); @@ -509,17 +510,17 @@ struct viewport_t { GLint x; GLint y; GLsizei w; - GLsizei h; + GLsizei h; struct { GLint x; GLint y; - } surfaceport; + } surfaceport; struct { GLint x; GLint y; GLsizei w; - GLsizei h; - } scissor; + GLsizei h; + } scissor; }; // ---------------------------------------------------------------------------- @@ -594,6 +595,16 @@ struct prims_t { void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*); }; +struct copybits_context_t { + // A handle to the blit engine, if it exists, else NULL. + copybit_device_t* blitEngine; + int32_t minScale; + int32_t maxScale; + // File descriptor of current drawing surface, if it's suitable for use as + // a copybits destination, else -1. + int drawSurfaceFd; +}; + struct ogles_context_t { context_t rasterizer; array_machine_t arrays __attribute__((aligned(32))); @@ -617,6 +628,14 @@ struct ogles_context_t { uint32_t transformTextures : 1; EGLSurfaceManager* surfaceManager; EGLBufferObjectManager* bufferObjectManager; + + // copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is + // defined, but it is always present because ogles_context_t is a public + // struct that is used by clients of libagl. We want the size and offsets + // to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined. + + copybits_context_t copybits; + GLenum error; static inline ogles_context_t* get() { diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h index 546d0ad..646cc10 100644 --- a/include/private/ui/SharedState.h +++ b/include/private/ui/SharedState.h @@ -32,16 +32,12 @@ namespace android { struct surface_info_t { // 4 longs, 16 bytes enum { - eBufferDirty = 0x01 + eBufferDirty = 0x01, + eNeedNewBuffer = 0x02 }; - uint16_t w; - uint16_t h; - uint16_t stride; - uint16_t bpr; - uint16_t reserved; - uint8_t format; + uint8_t reserved[11]; uint8_t flags; - ssize_t bits_offset; + status_t status; }; // --------------------------------------------------------------------------- @@ -110,8 +106,6 @@ struct per_client_cblk_t // 4KB max INSPECT = 0x00000002 }; - per_client_cblk_t(); - // these functions are used by the clients status_t validate(size_t i) const; int32_t lock_layer(size_t i, uint32_t flags); @@ -138,12 +132,9 @@ struct display_cblk_t struct surface_flinger_cblk_t // 4KB max { - surface_flinger_cblk_t(); - uint8_t connected; uint8_t reserved[3]; uint32_t pad[7]; - display_cblk_t displays[NUM_DISPLAY_MAX]; }; diff --git a/include/ui/BufferMapper.h b/include/ui/BufferMapper.h new file mode 100644 index 0000000..8a33b2e --- /dev/null +++ b/include/ui/BufferMapper.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef ANDROID_UI_BUFFER_MAPPER_H +#define ANDROID_UI_BUFFER_MAPPER_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/threads.h> +#include <utils/Singleton.h> + +#include <hardware/gralloc.h> + + +struct gralloc_module_t; + +namespace android { + +// --------------------------------------------------------------------------- + +class Rect; + +class BufferMapper : public Singleton<BufferMapper> +{ +public: + static inline BufferMapper& get() { return getInstance(); } + status_t map(buffer_handle_t handle, void** addr); + status_t unmap(buffer_handle_t handle); + status_t lock(buffer_handle_t handle, int usage, const Rect& bounds); + status_t unlock(buffer_handle_t handle); + +private: + friend class Singleton<BufferMapper>; + BufferMapper(); + mutable Mutex mLock; + gralloc_module_t const *mAllocMod; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_UI_BUFFER_MAPPER_H + diff --git a/include/ui/EGLNativeWindowSurface.h b/include/ui/EGLNativeWindowSurface.h index 3494234..4b25655 100644 --- a/include/ui/EGLNativeWindowSurface.h +++ b/include/ui/EGLNativeWindowSurface.h @@ -19,8 +19,17 @@ #include <stdint.h> #include <sys/types.h> -#include <ui/EGLNativeSurface.h> + #include <EGL/egl.h> +#include <EGL/android_natives.h> + +#include <utils/threads.h> +#include <ui/Rect.h> + +#include <pixelflinger/pixelflinger.h> + + +extern "C" EGLNativeWindowType android_createDisplaySurface(void); // --------------------------------------------------------------------------- namespace android { @@ -28,27 +37,84 @@ namespace android { class Surface; -class EGLNativeWindowSurface : public EGLNativeSurface<EGLNativeWindowSurface> + +class NativeBuffer + : public EGLNativeBase< + android_native_buffer_t, + NativeBuffer, + LightRefBase<NativeBuffer> > { public: - EGLNativeWindowSurface(const sp<Surface>& surface); - ~EGLNativeWindowSurface(); + NativeBuffer(int w, int h, int f, int u) : BASE() { + android_native_buffer_t::width = w; + android_native_buffer_t::height = h; + android_native_buffer_t::format = f; + android_native_buffer_t::usage = u; + android_native_buffer_t::getHandle = getHandle; + } +public: + buffer_handle_t handle; +private: + friend class LightRefBase<NativeBuffer>; + ~NativeBuffer() { }; // this class cannot be overloaded + static int getHandle(android_native_buffer_t const * base, buffer_handle_t* handle) { + *handle = getSelf(base)->handle; + return 0; + } +}; - void setSwapRectangle(int l, int t, int w, int h); +// --------------------------------------------------------------------------- + +class FramebufferNativeWindow + : public EGLNativeBase< + android_native_window_t, + FramebufferNativeWindow, + LightRefBase<FramebufferNativeWindow> > +{ +public: + FramebufferNativeWindow(); + + framebuffer_device_t const * getDevice() const { return fbDev; } private: - static void hook_incRef(NativeWindowType window); - static void hook_decRef(NativeWindowType window); - static uint32_t hook_swapBuffers(NativeWindowType window); - static void hook_connect(NativeWindowType window); - static void hook_disconnect(NativeWindowType window); - - uint32_t swapBuffers(); - void connect(); - void disconnect(); - - sp<Surface> mSurface; - bool mConnected; + friend class LightRefBase<FramebufferNativeWindow>; + ~FramebufferNativeWindow(); // this class cannot be overloaded + static void connect(android_native_window_t* window); + static void disconnect(android_native_window_t* window); + static int setSwapInterval(android_native_window_t* window, int interval); + static int setSwapRectangle(android_native_window_t* window, + int l, int t, int w, int h); + static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); + static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + + + static inline FramebufferNativeWindow* getSelf( + android_native_window_t* window) { + FramebufferNativeWindow* self = + static_cast<FramebufferNativeWindow*>(window); + return self; + } + + static inline FramebufferNativeWindow* getSelf( + android_native_base_t* window) { + return getSelf(reinterpret_cast<android_native_window_t*>(window)); + } + + + framebuffer_device_t* fbDev; + alloc_device_t* grDev; + + sp<NativeBuffer> buffers[2]; + sp<NativeBuffer> front; + + Rect mDirty; + + mutable Mutex mutex; + Condition mCondition; + int32_t mNumBuffers; + int32_t mNumFreeBuffers; + int32_t mBufferHead; }; // --------------------------------------------------------------------------- diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index 87b320f..1a78872 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -20,12 +20,15 @@ #include <stdint.h> #include <sys/types.h> +#include <EGL/android_natives.h> + #include <utils/Errors.h> #include <utils/IInterface.h> #include <utils/RefBase.h> #include <ui/PixelFormat.h> #include <hardware/hardware.h> +#include <hardware/gralloc.h> namespace android { @@ -33,6 +36,7 @@ typedef int32_t SurfaceID; class IMemoryHeap; class OverlayRef; +class SurfaceBuffer; class ISurface : public IInterface { @@ -42,11 +46,13 @@ protected: UNREGISTER_BUFFERS, POST_BUFFER, // one-way transaction CREATE_OVERLAY, + GET_BUFFER, }; public: DECLARE_META_INTERFACE(Surface); + virtual sp<SurfaceBuffer> getBuffer() = 0; class BufferHeap { public: @@ -78,9 +84,7 @@ public: }; virtual status_t registerBuffers(const BufferHeap& buffers) = 0; - virtual void postBuffer(ssize_t offset) = 0; // one-way - virtual void unregisterBuffers() = 0; virtual sp<OverlayRef> createOverlay( diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h index 5c64b22..fd5a473 100644 --- a/include/ui/ISurfaceComposer.h +++ b/include/ui/ISurfaceComposer.h @@ -32,7 +32,6 @@ namespace android { // ---------------------------------------------------------------------------- class DisplayInfo; -class IGPUCallback; class ISurfaceComposer : public IInterface { @@ -112,37 +111,12 @@ public: */ virtual void bootFinished() = 0; - /* get access to the GPU. Access is relinquished when releasing regs */ - struct gpu_info_t { - struct gpu_region_t { - sp<IMemory> region; - size_t reserved; - }; - sp<IMemory> regs; - size_t count; - gpu_region_t regions[2]; - }; - virtual status_t requestGPU( - const sp<IGPUCallback>& callback, - gpu_info_t* gpu) = 0; - - /* take the gpu back from any apps using it. They'll get a - * EGL_CONTEXT_LOST error */ - virtual status_t revokeGPU() = 0; - /* Signal surfaceflinger that there might be some work to do * This is an ASYNCHRONOUS call. */ virtual void signal() const = 0; }; -class IGPUCallback : public IInterface -{ -public: - DECLARE_META_INTERFACE(GPUCallback); - virtual void gpuLost() = 0; //one-way -}; - // ---------------------------------------------------------------------------- class BnSurfaceComposer : public BnInterface<ISurfaceComposer> @@ -159,8 +133,6 @@ public: SET_ORIENTATION, FREEZE_DISPLAY, UNFREEZE_DISPLAY, - REQUEST_GPU, - REVOKE_GPU, SIGNAL }; @@ -170,15 +142,6 @@ public: uint32_t flags = 0); }; -class BnGPUCallback : public BnInterface<IGPUCallback> -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h index 5b9361d..8515e2e 100644 --- a/include/ui/ISurfaceFlingerClient.h +++ b/include/ui/ISurfaceFlingerClient.h @@ -52,7 +52,6 @@ public: struct surface_data_t { int32_t token; int32_t identity; - sp<IMemoryHeap> heap[2]; status_t readFromParcel(const Parcel& parcel); status_t writeToParcel(Parcel* parcel) const; }; diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h index 14af823..6d87321b 100644 --- a/include/ui/PixelFormat.h +++ b/include/ui/PixelFormat.h @@ -84,6 +84,13 @@ typedef int32_t PixelFormat; struct PixelFormatInfo { + enum { + INDEX_ALPHA = 0, + INDEX_RED = 1, + INDEX_GREEN = 2, + INDEX_BLUE = 3 + }; + enum { // components ALPHA = 1, RGB = 2, @@ -95,20 +102,33 @@ struct PixelFormatInfo Y_CB_CR_I = 8, }; + struct szinfo { + uint8_t h; + uint8_t l; + }; + inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { } size_t getScanlineSize(unsigned int width) const; + size_t getSize(size_t ci) const { + return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0; + } size_t version; PixelFormat format; size_t bytesPerPixel; size_t bitsPerPixel; - uint8_t h_alpha; - uint8_t l_alpha; - uint8_t h_red; - uint8_t l_red; - uint8_t h_green; - uint8_t l_green; - uint8_t h_blue; - uint8_t l_blue; + union { + szinfo cinfo[4]; + struct { + uint8_t h_alpha; + uint8_t l_alpha; + uint8_t h_red; + uint8_t l_red; + uint8_t h_green; + uint8_t l_green; + uint8_t h_blue; + uint8_t l_blue; + }; + }; uint8_t components; uint8_t reserved0[3]; uint32_t reserved1; diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 33953a9..d92da49 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -28,24 +28,65 @@ #include <ui/Region.h> #include <ui/ISurfaceFlingerClient.h> +#include <EGL/android_natives.h> + namespace android { // --------------------------------------------------------------------------- class Rect; class SurfaceComposerClient; +struct per_client_cblk_t; +struct layer_cblk_t; + +// --------------------------------------------------------------------------- -class Surface : public RefBase +class SurfaceBuffer + : public EGLNativeBase< + android_native_buffer_t, + SurfaceBuffer, + LightRefBase<SurfaceBuffer> > { +public: + buffer_handle_t getHandle() const { + return handle; + } + +protected: + SurfaceBuffer(); + SurfaceBuffer(const Parcel& reply); + virtual ~SurfaceBuffer(); + buffer_handle_t handle; + bool mOwner; + +private: + friend class BpSurface; + friend class BnSurface; + friend class LightRefBase<SurfaceBuffer>; + + SurfaceBuffer& operator = (const SurfaceBuffer& rhs); + const SurfaceBuffer& operator = (const SurfaceBuffer& rhs) const; + + static status_t writeToParcel(Parcel* reply, + android_native_buffer_t const* buffer); + + static int getHandle(android_native_buffer_t const * base, + buffer_handle_t* handle); +}; +// --------------------------------------------------------------------------- + +class Surface + : public EGLNativeBase<android_native_window_t, Surface, RefBase> +{ public: struct SurfaceInfo { uint32_t w; uint32_t h; - uint32_t bpr; + uint32_t s; + uint32_t usage; PixelFormat format; void* bits; - void* base; uint32_t reserved[2]; }; @@ -55,15 +96,12 @@ public: status_t lock(SurfaceInfo* info, bool blocking = true); status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); status_t unlockAndPost(); - status_t unlock(); - - void* heapBase(int i) const; + uint32_t getFlags() const { return mFlags; } // setSwapRectangle() is mainly used by EGL void setSwapRectangle(const Rect& r); const Rect& swapRectangle() const; - status_t nextBuffer(SurfaceInfo* info); sp<Surface> dup() const; static sp<Surface> readFromParcel(Parcel* parcel); @@ -95,6 +133,8 @@ private: friend class Test; const sp<ISurface>& getISurface() const { return mSurface; } + status_t getBufferLocked(int index); + // can't be copied Surface& operator = (Surface& rhs); Surface(const Surface& rhs); @@ -108,23 +148,39 @@ private: Surface(Surface const* rhs); ~Surface(); - + Region dirtyRegion() const; void setDirtyRegion(const Region& region) const; - // this locks protects calls to lockSurface() / unlockSurface() - // and is called by SurfaceComposerClient. - Mutex& getLock() const { return mSurfaceLock; } - + + status_t validate(per_client_cblk_t const* cblk) const; + static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); + + + static void connect(android_native_window_t* window); + static void disconnect(android_native_window_t* window); + static int setSwapInterval(android_native_window_t* window, int interval); + static int setSwapRectangle(android_native_window_t* window, + int l, int t, int w, int h); + static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); + static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + + int dequeueBuffer(android_native_buffer_t** buffer); + int lockBuffer(android_native_buffer_t* buffer); + int queueBuffer(android_native_buffer_t* buffer); + + + alloc_device_t* mAllocDevice; sp<SurfaceComposerClient> mClient; sp<ISurface> mSurface; - sp<IMemoryHeap> mHeap[2]; + sp<SurfaceBuffer> mBuffers[2]; + android_native_buffer_t* mLockedBuffer; SurfaceID mToken; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; const bool mOwner; - mutable void* mSurfaceHeapBase[2]; mutable Region mDirtyRegion; mutable Rect mSwapRectangle; mutable uint8_t mBackbufferIndex; diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h index 76a3b55..86de6ea 100644 --- a/include/ui/SurfaceComposerClient.h +++ b/include/ui/SurfaceComposerClient.h @@ -128,34 +128,17 @@ private: status_t setPosition(Surface* surface, int32_t x, int32_t y); status_t setSize(Surface* surface, uint32_t w, uint32_t h); - //! Unlock the surface, and specify the dirty region if any - status_t unlockAndPostSurface(Surface* surface); - status_t unlockSurface(Surface* surface); - - status_t lockSurface(Surface* surface, - Surface::SurfaceInfo* info, - Region* dirty, - bool blocking = true); - - status_t nextBuffer(Surface* surface, - Surface::SurfaceInfo* info); + void signalServer(); status_t destroySurface(SurfaceID sid); void _init(const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn); - void _signal_server(); - static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); inline layer_state_t* _get_state_l(const sp<Surface>& surface); layer_state_t* _lockLayerState(const sp<Surface>& surface); inline void _unlockLayerState(); - status_t validateSurface( - per_client_cblk_t const* cblk, Surface const * surface); - - void pinHeap(const sp<IMemoryHeap>& heap); - mutable Mutex mLock; layer_state_t* mPrebuiltLayerState; SortedVector<layer_state_t> mStates; @@ -167,9 +150,6 @@ private: per_client_cblk_t* mControl; sp<IMemory> mControlMemory; sp<ISurfaceFlingerClient> mClient; - sp<IMemoryHeap> mSurfaceHeap; - uint8_t* mSurfaceHeapBase; - void* mGL; SurfaceFlingerSynchro* mSignalServer; }; diff --git a/include/utils/Parcel.h b/include/utils/Parcel.h index 9087c44..af1490a 100644 --- a/include/utils/Parcel.h +++ b/include/utils/Parcel.h @@ -80,8 +80,11 @@ public: status_t writeStrongBinder(const sp<IBinder>& val); status_t writeWeakBinder(const wp<IBinder>& val); - // doesn't take ownership of the native_handle - status_t writeNativeHandle(const native_handle& handle); + // Place a native_handle into the parcel (the native_handle's file- + // descriptors are dup'ed, so it is safe to delete the native_handle + // when this function returns). + // Doesn't take ownership of the native_handle. + status_t writeNativeHandle(const native_handle* handle); // Place a file descriptor into the parcel. The given fd must remain // valid for the lifetime of the parcel. @@ -114,12 +117,11 @@ public: wp<IBinder> readWeakBinder() const; - // if alloc is NULL, native_handle is allocated with malloc(), otherwise - // alloc is used. If the function fails, the effects of alloc() must be - // reverted by the caller. - native_handle* readNativeHandle( - native_handle* (*alloc)(void* cookie, int numFds, int ints), - void* cookie) const; + // Retrieve native_handle from the parcel. This returns a copy of the + // parcel's native_handle (the caller takes ownership). The caller + // must free the native_handle with native_handle_close() and + // native_handle_delete(). + native_handle* readNativeHandle() const; // Retrieve a file descriptor from the parcel. This returns the raw fd diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h new file mode 100644 index 0000000..776f93b --- /dev/null +++ b/include/utils/Singleton.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef ANDROID_UTILS_SINGLETON_H +#define ANDROID_UTILS_SINGLETON_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/threads.h> + +namespace android { +// --------------------------------------------------------------------------- + +template <typename TYPE> +class Singleton +{ +public: + static TYPE& getInstance() { + Mutex::Autolock _l(sLock); + TYPE* instance = sInstance; + if (instance == 0) { + instance = new TYPE(); + sInstance = instance; + } + return *instance; + } + +protected: + ~Singleton() { }; + Singleton() { }; + +private: + Singleton(const Singleton&); + Singleton& operator = (const Singleton&); + static Mutex sLock; + static TYPE* sInstance; +}; + +template<class TYPE> Mutex Singleton<TYPE>::sLock; +template<class TYPE> TYPE* Singleton<TYPE>::sInstance(0); + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_UTILS_SINGLETON_H + diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 2212436..ebd588b 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -5,9 +5,9 @@ LOCAL_SRC_FILES:= \ clz.cpp.arm \ DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ - GPUHardware/GPUHardware.cpp \ BootAnimation.cpp \ BlurFilter.cpp.arm \ + BufferAllocator.cpp \ CPUGauge.cpp \ Layer.cpp \ LayerBase.cpp \ @@ -20,9 +20,10 @@ LOCAL_SRC_FILES:= \ OrientationAnimation.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ - Transform.cpp \ - VRamHeap.cpp + Transform.cpp +LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES # need "-lrt" on Linux simulator to pick up clock_gettime ifeq ($(TARGET_SIMULATOR),true) diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp index db40385..4aa8c2c 100644 --- a/libs/surfaceflinger/BootAnimation.cpp +++ b/libs/surfaceflinger/BootAnimation.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "BootAnimation" - #include <stdint.h> #include <sys/types.h> #include <math.h> @@ -147,9 +145,7 @@ status_t BootAnimation::readyToRun() { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglChooseConfig(display, attribs, &config, 1, &numConfigs); - mNativeWindowSurface = new EGLNativeWindowSurface(s); - surface = eglCreateWindowSurface(display, config, - mNativeWindowSurface.get(), NULL); + surface = eglCreateWindowSurface(display, config, s.get(), NULL); context = eglCreateContext(display, config, NULL, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &w); @@ -180,7 +176,7 @@ bool BootAnimation::threadLoop() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); - mNativeWindowSurface.clear(); + mFlingerSurface.clear(); return r; } @@ -199,8 +195,7 @@ bool BootAnimation::android() { const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); // draw and update only what we need - mNativeWindowSurface->setSwapRectangle(updateRect.left, - updateRect.top, updateRect.width(), updateRect.height()); + mFlingerSurface->setSwapRectangle(updateRect); glEnable(GL_SCISSOR_TEST); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h index 3fb6670..8484623 100644 --- a/libs/surfaceflinger/BootAnimation.h +++ b/libs/surfaceflinger/BootAnimation.h @@ -72,7 +72,6 @@ private: EGLDisplay mContext; EGLDisplay mSurface; sp<Surface> mFlingerSurface; - sp<EGLNativeWindowSurface> mNativeWindowSurface; Barrier mBarrier; }; diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp new file mode 100644 index 0000000..ac32985 --- /dev/null +++ b/libs/surfaceflinger/BufferAllocator.cpp @@ -0,0 +1,162 @@ +/* +** +** Copyright 2009, 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 <sys/mman.h> +#include <utils/CallStack.h> +#include <cutils/ashmem.h> +#include <cutils/log.h> +#include <utils/String8.h> + +#include <ui/BufferMapper.h> + +#include "BufferAllocator.h" + +// FIXME: ANDROID_GRALLOC_DEBUG must only be used with *our* gralloc +#define ANDROID_GRALLOC_DEBUG 1 + + +namespace android { +// --------------------------------------------------------------------------- + +Mutex BufferAllocator::sLock; +KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList; + +BufferAllocator::BufferAllocator() + : mAllocDev(0) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + if (err == 0) { + gralloc_open(module, &mAllocDev); + } +} + +BufferAllocator::~BufferAllocator() +{ + gralloc_close(mAllocDev); +} + +void BufferAllocator::dump(String8& result) const +{ + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + size_t total = 0; + const size_t SIZE = 512; + char buffer[SIZE]; + snprintf(buffer, SIZE, "Allocated buffers:\n"); + result.append(buffer); + const size_t c = list.size(); + for (size_t i=0 ; i<c ; i++) { + const alloc_rec_t& rec(list.valueAt(i)); + snprintf(buffer, SIZE, "%10p: %10p | %7.2f KB | %4u x %4u | %2d | 0x%08x\n", + list.keyAt(i), rec.vaddr, rec.size/1024.0f, + rec.w, rec.h, rec.format, rec.usage); + result.append(buffer); + total += rec.size; + } + snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f); + result.append(buffer); +} + +status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, + int usage, buffer_handle_t* handle, int32_t* stride) +{ + Mutex::Autolock _l(mLock); + + // we have a h/w allocator and h/w buffer is requested + status_t err = mAllocDev->alloc(mAllocDev, + w, h, format, usage, handle, stride); + LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", + w, h, format, usage, err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + alloc_rec_t rec; + rec.w = w; + rec.h = h; + rec.format = format; + rec.usage = usage; + rec.vaddr = 0; + rec.size = h * stride[0] * bytesPerPixel(format); + list.add(*handle, rec); + } + + return err; +} + +status_t BufferAllocator::free(buffer_handle_t handle) +{ + Mutex::Autolock _l(mLock); + +#if ANDROID_GRALLOC_DEBUG + if (handle->data[2]) { + CallStack s; + s.update(); + s.dump(""); + } +#endif + + status_t err = mAllocDev->free(mAllocDev, handle); + LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + list.removeItem(handle); + } + + return err; +} + +status_t BufferAllocator::map(buffer_handle_t handle, void** addr) +{ + Mutex::Autolock _l(mLock); + status_t err = BufferMapper::get().map(handle, addr); + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + ssize_t idx = list.indexOfKey(handle); + if (idx >= 0) + list.editValueAt(idx).vaddr = addr; + } + + return err; +} + +status_t BufferAllocator::unmap(buffer_handle_t handle) +{ + Mutex::Autolock _l(mLock); + gralloc_module_t* mod = (gralloc_module_t*)mAllocDev->common.module; + status_t err = mod->unmap(mod, handle); + LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + ssize_t idx = list.indexOfKey(handle); + if (idx >= 0) + list.editValueAt(idx).vaddr = 0; + } + + return err; +} + + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/surfaceflinger/BufferAllocator.h b/libs/surfaceflinger/BufferAllocator.h new file mode 100644 index 0000000..0b69b8e --- /dev/null +++ b/libs/surfaceflinger/BufferAllocator.h @@ -0,0 +1,100 @@ +/* +** +** Copyright 2009, 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_BUFFER_ALLOCATOR_H +#define ANDROID_BUFFER_ALLOCATOR_H + +#include <stdint.h> + +#include <cutils/native_handle.h> + +#include <utils/Errors.h> +#include <utils/KeyedVector.h> +#include <utils/threads.h> +#include <utils/Singleton.h> + +#include <ui/PixelFormat.h> + +#include <hardware/gralloc.h> + + +namespace android { +// --------------------------------------------------------------------------- + +class String8; + +class BufferAllocator : public Singleton<BufferAllocator> +{ +public: + enum { + USAGE_SW_READ_NEVER = GRALLOC_USAGE_SW_READ_NEVER, + USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY, + USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN, + USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK, + + USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER, + USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY, + USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN, + USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK, + + USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK, + + USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE, + USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER, + USAGE_HW_2D = GRALLOC_USAGE_HW_2D, + USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK + }; + + static inline BufferAllocator& get() { return getInstance(); } + + + status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, + buffer_handle_t* handle, int32_t* stride); + + status_t free(buffer_handle_t handle); + + status_t map(buffer_handle_t handle, void** addr); + + status_t unmap(buffer_handle_t handle); + + void dump(String8& res) const; + +private: + struct alloc_rec_t { + uint32_t w; + uint32_t h; + PixelFormat format; + uint32_t usage; + void* vaddr; + size_t size; + }; + + static Mutex sLock; + static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList; + + friend class Singleton<BufferAllocator>; + BufferAllocator(); + ~BufferAllocator(); + + mutable Mutex mLock; + alloc_device_t *mAllocDev; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_BUFFER_ALLOCATOR_H diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp index 74a9270..91dd236 100644 --- a/libs/surfaceflinger/CPUGauge.cpp +++ b/libs/surfaceflinger/CPUGauge.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "CPUGauge" - #include <stdint.h> #include <limits.h> #include <sys/types.h> @@ -113,7 +111,7 @@ bool CPUGauge::threadLoop() fb.version = sizeof(GGLSurface); fb.width = info.w; fb.height = info.h; - fb.stride = info.w; + fb.stride = info.s; fb.format = info.format; fb.data = (GGLubyte*)info.bits; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f14d7e9..1f7211c 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -23,18 +21,24 @@ #include <cutils/properties.h> +#include <utils/RefBase.h> #include <utils/Log.h> -#include <ui/EGLDisplaySurface.h> +#include <ui/PixelFormat.h> +#include <ui/EGLNativeWindowSurface.h> #include <GLES/gl.h> +#include <EGL/egl.h> #include <EGL/eglext.h> +#include <EGL/android_natives.h> +#include <pixelflinger/pixelflinger.h> #include "DisplayHardware/DisplayHardware.h" #include <hardware/copybit.h> #include <hardware/overlay.h> +#include <hardware/gralloc.h> using namespace android; @@ -108,17 +112,28 @@ PixelFormat DisplayHardware::getFormat() const { return mFormat; } void DisplayHardware::init(uint32_t dpy) { + hw_module_t const* module; + + mNativeWindow = new FramebufferNativeWindow(); + + mOverlayEngine = NULL; + if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { + overlay_control_open(module, &mOverlayEngine); + } + + framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); + + PixelFormatInfo fbFormatInfo; + getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo); + // initialize EGL const EGLint attribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, + EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h, dummy; - EGLint numConfigs, n; - EGLConfig config; + EGLint numConfigs=0, n=0; EGLSurface surface; EGLContext context; mFlags = 0; @@ -129,7 +144,31 @@ void DisplayHardware::init(uint32_t dpy) EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); - eglChooseConfig(display, attribs, &config, 1, &n); + + // Get all the "potential match" configs... + EGLConfig* const configs = new EGLConfig[numConfigs]; + eglChooseConfig(display, attribs, configs, numConfigs, &n); + LOGE_IF(n<=0, "no EGLConfig available!"); + EGLConfig config = configs[0]; + if (n > 1) { + // if there is more than one candidate, go through the list + // and pick one that matches our framebuffer format + int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA); + int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED); + int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN); + int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); + for (int i=0 ; i<n ; i++) { + EGLint r,g,b,a; + eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a); + if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) { + config = configs[i]; + } + } + } + delete [] configs; /* * Gather EGL extensions @@ -145,11 +184,8 @@ void DisplayHardware::init(uint32_t dpy) LOGI("extensions: %s", egl_extensions); LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - // TODO: get this from the devfb driver (probably should be HAL module) - mFlags |= SWAP_RECTANGLE_EXTENSION; - // TODO: get the real "update_on_demand" behavior (probably should be HAL module) - mFlags |= UPDATE_ON_DEMAND; + // FIXME: mFlags |= UPDATE_ON_DEMAND; if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { if (dummy == EGL_SLOW_CONFIG) @@ -160,33 +196,20 @@ void DisplayHardware::init(uint32_t dpy) * Create our main surface */ - mDisplaySurface = new EGLDisplaySurface(); - - surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL); - //checkEGLErrors("eglCreateDisplaySurfaceANDROID"); + + surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); + checkEGLErrors("eglCreateDisplaySurfaceANDROID"); + if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { if (dummy == EGL_BUFFER_PRESERVED) { mFlags |= BUFFER_PRESERVED; } } - GLint value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiX = 160.0f; - } else { - mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING; - } - value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiY = 160.0f; - } else { - mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING; - } - mRefreshRate = 60.f; // TODO: get the real refresh rate - + mDpiX = mNativeWindow->xdpi; + mDpiX = mNativeWindow->ydpi; + mRefreshRate = mNativeWindow->getDevice()->fps; char property[PROPERTY_VALUE_MAX]; if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { @@ -225,7 +248,10 @@ void DisplayHardware::init(uint32_t dpy) if (strstr(gl_extensions, "GL_OES_draw_texture")) { mFlags |= DRAW_TEXTURE_EXTENSION; } - if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) { + if (strstr( gl_extensions, "GL_OES_EGL_image") && + (strstr(egl_extensions, "KHR_image_base") || + strstr(egl_extensions, "EGL_KHR_image")) && + strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { mFlags |= DIRECT_TEXTURE; } @@ -236,19 +262,8 @@ void DisplayHardware::init(uint32_t dpy) mConfig = config; mSurface = surface; mContext = context; - mFormat = GGL_PIXEL_FORMAT_RGB_565; - - hw_module_t const* module; - - mBlitEngine = NULL; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - mOverlayEngine = NULL; - if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - overlay_control_open(module, &mOverlayEngine); - } + mFormat = fbDev->format; + mPageFlipCount = 0; } /* @@ -262,7 +277,6 @@ void DisplayHardware::fini() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(mDisplay); - copybit_close(mBlitEngine); overlay_control_close(mOverlayEngine); } @@ -276,28 +290,8 @@ void DisplayHardware::acquireScreen() const DisplayHardwareBase::acquireScreen(); } -void DisplayHardware::getDisplaySurface(copybit_image_t* img) const -{ - img->w = mDisplaySurface->stride; - img->h = mDisplaySurface->height; - img->format = mDisplaySurface->format; - img->offset = mDisplaySurface->offset; - img->base = (void*)mDisplaySurface->base; - img->fd = mDisplaySurface->fd; -} - -void DisplayHardware::getDisplaySurface(GGLSurface* fb) const -{ - fb->version= sizeof(GGLSurface); - fb->width = mDisplaySurface->width; - fb->height = mDisplaySurface->height; - fb->stride = mDisplaySurface->stride; - fb->format = mDisplaySurface->format; - fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset; -} - uint32_t DisplayHardware::getPageFlipCount() const { - return mDisplaySurface->getPageFlipCount(); + return mPageFlipCount; } /* @@ -315,17 +309,14 @@ void DisplayHardware::flip(const Region& dirty) const newDirty.andSelf(Rect(mWidth, mHeight)); if (mFlags & BUFFER_PRESERVED) { - const Region copyback(mDirty.subtract(newDirty)); mDirty = newDirty; - mDisplaySurface->copyFrontToBack(copyback); } - if (mFlags & SWAP_RECTANGLE_EXTENSION) { - const Rect& b(newDirty.bounds()); - mDisplaySurface->setSwapRectangle( - b.left, b.top, b.width(), b.height()); - } + const Rect& b(newDirty.bounds()); + mNativeWindow->android_native_window_t::setSwapRectangle( + mNativeWindow.get(), b.left, b.top, b.width(), b.height()); + mPageFlipCount++; eglSwapBuffers(dpy, surface); checkEGLErrors("eglSwapBuffers"); @@ -345,9 +336,9 @@ void DisplayHardware::makeCurrent() const } void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { - mDisplaySurface->copyFrontToImage(front); + // FIXME: we need to get rid of this } void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { - mDisplaySurface->copyBackToImage(front); + // FIXME: we need to get rid of this } diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index 550a4d1..97a68a5 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -22,25 +22,28 @@ #include <ui/PixelFormat.h> #include <ui/Region.h> +#include <GLES/gl.h> +#include <GLES/glext.h> #include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <pixelflinger/pixelflinger.h> #include "DisplayHardware/DisplayHardwareBase.h" struct overlay_control_device_t; -struct copybit_device_t; +struct framebuffer_device_t; struct copybit_image_t; -struct copybit_t; namespace android { -class EGLDisplaySurface; +class FramebufferNativeWindow; class DisplayHardware : public DisplayHardwareBase { public: enum { DIRECT_TEXTURE = 0x00000002, - SWAP_RECTANGLE_EXTENSION= 0x00000004, COPY_BITS_EXTENSION = 0x00000008, NPOT_EXTENSION = 0x00000100, DRAW_TEXTURE_EXTENSION = 0x00000200, @@ -73,10 +76,7 @@ public: void makeCurrent() const; uint32_t getPageFlipCount() const; - void getDisplaySurface(copybit_image_t* img) const; - void getDisplaySurface(GGLSurface* fb) const; EGLDisplay getEGLDisplay() const { return mDisplay; } - copybit_device_t* getBlitEngine() const { return mBlitEngine; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } void copyFrontToImage(const copybit_image_t& front) const; @@ -103,8 +103,9 @@ private: PixelFormat mFormat; uint32_t mFlags; mutable Region mDirty; - sp<EGLDisplaySurface> mDisplaySurface; - copybit_device_t* mBlitEngine; + mutable uint32_t mPageFlipCount; + + sp<FramebufferNativeWindow> mNativeWindow; overlay_control_device_t* mOverlayEngine; }; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index f75e5c2..1d09f84 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <assert.h> #include <errno.h> #include <stdlib.h> diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index f65d669..980b78b 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -14,26 +14,25 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <cutils/properties.h> +#include <cutils/native_handle.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/StopWatch.h> +#include <utils/IMemory.h> #include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> +#include <ui/Surface.h> #include "clz.h" #include "Layer.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -54,8 +53,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) mSecure(false), mFrontBufferIndex(1), mNeedsBlending(true), - mResizeTransactionDone(false), - mTextureName(-1U), mTextureWidth(0), mTextureHeight(0) + mResizeTransactionDone(false) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. @@ -63,11 +61,16 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) Layer::~Layer() { - client->free(clientIndex()); - // this should always be called from the OpenGL thread - if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); + for (int i=0 ; i<NUM_BUFFERS ; i++) { + if (mTextures[i].name != -1U) { + // FIXME: this was originally to work-around a bug in the + // adreno driver. this should be fixed now. + deletedTextures.add(mTextures[i].name); + } + if (mTextures[i].image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTextures[i].image); + } } } @@ -79,7 +82,7 @@ void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) lcblk->flags |= eNoCopyBack; } -sp<LayerBaseClient::Surface> Layer::getSurface() const +sp<LayerBaseClient::Surface> Layer::createSurface() const { return mSurface; } @@ -92,25 +95,15 @@ status_t Layer::setBuffers( Client* client, status_t err = getPixelFormatInfo(format, &info); if (err) return err; - // TODO: if eHardware is explicitly requested, we should fail - // on systems where we can't allocate memory that can be used with - // DMA engines for instance. - - // FIXME: we always ask for hardware for now (this should come from copybit) - flags |= ISurfaceComposer::eHardware; + uint32_t bufferFlags = 0; + if (flags & ISurfaceComposer::eGPU) + bufferFlags |= Buffer::GPU; - const uint32_t memory_flags = flags & - (ISurfaceComposer::eGPU | - ISurfaceComposer::eHardware | - ISurfaceComposer::eSecure); - - // pixel-alignment. the final alignment may be bigger because - // we always force a 4-byte aligned bpr. - uint32_t alignment = 1; + if (flags & ISurfaceComposer::eSecure) + bufferFlags |= Buffer::SECURE; - if (flags & ISurfaceComposer::eGPU) { - // FIXME: this value should come from the h/w - alignment = 8; + + if (bufferFlags & Buffer::GPU) { // FIXME: this is msm7201A specific, as its GPU only supports // BGRA_8888. if (format == PIXEL_FORMAT_RGBA_8888) { @@ -118,45 +111,94 @@ status_t Layer::setBuffers( Client* client, } } - mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; + mSecure = (bufferFlags & Buffer::SECURE) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - sp<MemoryDealer> allocators[2]; for (int i=0 ; i<2 ; i++) { - allocators[i] = client->createAllocator(memory_flags); - if (allocators[i] == 0) - return NO_MEMORY; - mBuffers[i].init(allocators[i]); - int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS); - if (err != NO_ERROR) + err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags); + if (err != NO_ERROR) { return err; - mBuffers[i].clear(); // clear the bits for security - mBuffers[i].getInfo(lcblk->surface + i); + } } - - mSurface = new Surface(clientIndex(), - allocators[0]->getMemoryHeap(), - allocators[1]->getMemoryHeap(), - mIdentity); - + mSurface = new SurfaceLayer(clientIndex(), this); return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) { - if (UNLIKELY(mTextureName == -1U)) { - // create the texture name the first time - // can't do that in the ctor, because it runs in another thread. - mTextureName = createTexture(); + const sp<const Buffer>& buffer(frontBuffer().getBuffer()); + if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { + int index = mFrontBufferIndex; + if (LIKELY(!mTextures[index].dirty)) { + glBindTexture(GL_TEXTURE_2D, mTextures[index].name); + } else { + // we need to recreate the texture + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + + // create the new texture name if needed + if (UNLIKELY(mTextures[index].name == -1U)) { + mTextures[index].name = createTexture(); + } else { + glBindTexture(GL_TEXTURE_2D, mTextures[index].name); + } + + // free the previous image + if (mTextures[index].image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, mTextures[index].image); + mTextures[index].image = EGL_NO_IMAGE_KHR; + } + + // construct an EGL_NATIVE_BUFFER_ANDROID + android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); + + // create the new EGLImageKHR + const EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE, EGL_NONE + }; + mTextures[index].image = eglCreateImageKHR( + dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)clientBuf, attrs); + + LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR, + "eglCreateImageKHR() failed. err=0x%4x", + eglGetError()); + + if (mTextures[index].image != EGL_NO_IMAGE_KHR) { + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, + (GLeglImageOES)mTextures[index].image); + GLint error = glGetError(); + if (UNLIKELY(error != GL_NO_ERROR)) { + // this failed, for instance, because we don't support + // NPOT. + // FIXME: do something! + mFlags &= ~DisplayHardware::DIRECT_TEXTURE; + } else { + // Everything went okay! + mTextures[index].dirty = false; + } + } + } + } else { + GGLSurface t; + if (LIKELY(buffer->getBitmapSurface(&t) == NO_ERROR)) { + if (UNLIKELY(mTextures[0].name == -1U)) { + mTextures[0].name = createTexture(); + } + loadTexture(dirty, mTextures[0].name, t, + mTextures[0].width, mTextures[0].height); + } } - const GGLSurface& t(frontBuffer().surface()); - loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight); } void Layer::onDraw(const Region& clip) const { - if (UNLIKELY(mTextureName == -1LU)) { - //LOGW("Layer %p doesn't have a texture", this); + const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? + mFrontBufferIndex : 0; + GLuint textureName = mTextures[index].name; + + if (UNLIKELY(textureName == -1LU)) { + LOGW("Layer %p doesn't have a texture", this); // the texture has not been created yet, this Layer has // in fact never been drawn into. this happens frequently with // SurfaceView. @@ -164,63 +206,66 @@ void Layer::onDraw(const Region& clip) const return; } - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const LayerBitmap& front(frontBuffer()); - const GGLSurface& t(front.surface()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - const State& s(drawingState()); - - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - front.getBitmapSurface(&src); - copybit_rect_t srect = { 0, 0, t.width, t.height }; - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation()); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, - s.flags & ISurfaceComposer::eLayerDither ? - COPYBIT_ENABLE : COPYBIT_DISABLE); - - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - drawWithOpenGL(clip, mTextureName, t); - } + GGLSurface t; + sp<const Buffer> buffer(frontBuffer().getBuffer()); + buffer->getBitmapSurface(&t); + drawWithOpenGL(clip, textureName, t); } -status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h) +sp<SurfaceBuffer> Layer::peekBuffer() { + /* + * This is called from the client's Surface::lock(), after it locked + * the surface successfully. We're therefore guaranteed that the + * back-buffer is not in use by ourselves. + * Of course, we need to validate all this, which is not trivial. + * + * FIXME: A resize could happen at any time here. What to do about this? + * - resize() form post() + * - resize() from doTransaction() + * + * We'll probably need an internal lock for this. + * + * + * TODO: We need to make sure that post() doesn't swap + * the buffers under us. + */ + + // it's okay to read swapState for the purpose of figuring out the + // backbuffer index, which cannot change (since the app has locked it). + const uint32_t state = lcblk->swapState; + const int32_t backBufferIndex = layer_cblk_t::backBuffer(state); + + // get rid of the EGL image, since we shouldn't need it anymore + // (note that we're in a different thread than where it is being used) + if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image); + mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR; + } + + LayerBitmap& layerBitmap(mBuffers[backBufferIndex]); + sp<SurfaceBuffer> buffer = layerBitmap.allocate(); + LOGD_IF(DEBUG_RESIZE, - "reallocateBuffer (layer=%p), " - "requested (%dx%d), " - "index=%d, (%dx%d), (%dx%d)", - this, - int(w), int(h), - int(index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - status_t err = mBuffers[index].resize(w, h); - if (err == NO_ERROR) { - mBuffers[index].getInfo(lcblk->surface + index); + "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)", + this, backBufferIndex, + layerBitmap.getWidth(), + layerBitmap.getHeight(), + layerBitmap.getBuffer()->getWidth(), + layerBitmap.getBuffer()->getHeight()); + + if (UNLIKELY(buffer == 0)) { + // XXX: what to do, what to do? } else { - LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", - index, w, h, err, strerror(err)); - // XXX: what to do, what to do? We could try to free some - // hidden surfaces, instead of killing this one? + // texture is now dirty... + mTextures[backBufferIndex].dirty = true; + // ... so it the visible region (because we consider the surface's + // buffer size for visibility calculations) + forceVisibilityTransaction(); + mFlinger->setTransactionFlags(eTraversalNeeded); } - return err; + return buffer; } uint32_t Layer::doTransaction(uint32_t flags) @@ -232,7 +277,7 @@ uint32_t Layer::doTransaction(uint32_t flags) // that the size changed back to its previous value before the buffer // was resized (in the eLocked case below), in which case, we still // need to execute the code below so the clients have a chance to be - // release. resze() deals with the fact that the size can be the same. + // release. resize() deals with the fact that the size can be the same. /* * Various states we could be in... @@ -276,8 +321,8 @@ uint32_t Layer::doTransaction(uint32_t flags) int(temp.w), int(temp.h), int(drawingState().w), int(drawingState().h), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // if we get there we're pretty screwed. the only reasonable // thing to do is to pretend we should do the resize since // backbufferChanged is set (this also will give a chance to @@ -299,8 +344,8 @@ uint32_t Layer::doTransaction(uint32_t flags) int(temp.w), int(temp.h), int(drawingState().w), int(drawingState().h), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); if (state & eLocked) { // if the buffer is locked, we can't resize anything because @@ -314,7 +359,8 @@ uint32_t Layer::doTransaction(uint32_t flags) status_t err = resize(clientBackBufferIndex, temp.w, temp.h, "transaction"); if (err == NO_ERROR) { - const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; + const uint32_t mask = clientBackBufferIndex ? + eResizeBuffer1 : eResizeBuffer0; android_atomic_and(~mask, &(lcblk->swapState)); // since a buffer became available, we can let the client go... mFlinger->scheduleBroadcast(client); @@ -353,14 +399,15 @@ status_t Layer::resize( { /* * handle resize (backbuffer and frontbuffer reallocation) + * this is called from post() or from doTransaction() */ const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]); // if the new (transaction) size is != from the the backbuffer // then we need to reallocate the backbuffer - bool backbufferChanged = (clientBackBuffer.width() != width) || - (clientBackBuffer.height() != height); + bool backbufferChanged = (clientBackBuffer.getWidth() != width) || + (clientBackBuffer.getHeight() != height); LOGD_IF(!backbufferChanged, "(%s) eResizeRequested (layer=%p), but size not changed: " @@ -372,18 +419,28 @@ status_t Layer::resize( int(currentState().w), int(currentState().h), long(lcblk->swapState), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // this can happen when changing the size back and forth quickly status_t err = NO_ERROR; if (backbufferChanged) { - err = reallocateBuffer(clientBackBufferIndex, width, height); - } - if (UNLIKELY(err != NO_ERROR)) { - // couldn't reallocate the surface - android_atomic_write(eInvalidSurface, &lcblk->swapState); - memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t)); + + LOGD_IF(DEBUG_RESIZE, + "resize (layer=%p), requested (%dx%d), " + "index=%d, (%dx%d), (%dx%d)", + this, int(width), int(height), int(clientBackBufferIndex), + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); + + err = mBuffers[clientBackBufferIndex].setSize(width, height); + if (UNLIKELY(err != NO_ERROR)) { + // This really should never happen + LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", + clientBackBufferIndex, width, height, err, strerror(err)); + // couldn't reallocate the surface + android_atomic_write(eInvalidSurface, &lcblk->swapState); + } } return err; } @@ -457,15 +514,21 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); *previousSate = oldValue; - + const int32_t index = (newValue & eIndex) ^ 1; mFrontBufferIndex = index; + /* NOTE: it's safe to set this flag here because this is only touched + * from LayerBitmap::allocate(), which by construction cannot happen + * while we're in post(). + */ + lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty; + // ... post the new front-buffer Region dirty(lcblk->region + index); - dirty.andSelf(frontBuffer().bounds()); + dirty.andSelf(frontBuffer().getBounds()); - //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", + //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", // oldValue, newValue, mFrontBufferIndex); //dirty.dump("dirty"); @@ -476,8 +539,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) "index=%d, (%dx%d), (%dx%d)", this, newValue, int(1-index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // here, we just posted the surface and we have resolved // the front/back buffer indices. The client is blocked, so @@ -522,8 +585,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) Point Layer::getPhysicalSize() const { - const LayerBitmap& front(frontBuffer()); - return Point(front.width(), front.height()); + sp<const Buffer> front(frontBuffer().getBuffer()); + return Point(front->getWidth(), front->getHeight()); } void Layer::unlockPageFlip( @@ -561,6 +624,22 @@ void Layer::finishPageFlip() mFlinger->scheduleBroadcast(client); } +// --------------------------------------------------------------------------- + +Layer::SurfaceLayer::SurfaceLayer(SurfaceID id, const sp<Layer>& owner) + : Surface(id, owner->getIdentity(), owner) +{ +} + +sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer() +{ + sp<SurfaceBuffer> buffer = 0; + sp<Layer> owner(getOwner()); + if (owner != 0) { + buffer = owner->peekBuffer(); + } + return buffer; +} // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 2867f2b..dc03d35 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -27,6 +27,11 @@ #include <pixelflinger/pixelflinger.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + #include "LayerBitmap.h" #include "LayerBase.h" #include "Transform.h" @@ -42,6 +47,8 @@ class FreezeLock; // --------------------------------------------------------------------------- +const int NUM_BUFFERS = 2; + class Layer : public LayerBaseClient { public: @@ -56,7 +63,7 @@ public: virtual ~Layer(); inline PixelFormat pixelFormat() const { - return frontBuffer().pixelFormat(); + return frontBuffer().getPixelFormat(); } status_t setBuffers( Client* client, @@ -73,8 +80,7 @@ public: virtual void finishPageFlip(); virtual bool needsBlending() const { return mNeedsBlending; } virtual bool isSecure() const { return mSecure; } - virtual GLuint getTextureName() const { return mTextureName; } - virtual sp<Surface> getSurface() const; + virtual sp<Surface> createSurface() const; const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; } LayerBitmap& getBuffer(int i) { return mBuffers[i]; } @@ -96,21 +102,43 @@ private: status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what); Region post(uint32_t* oldState, bool& recomputeVisibleRegions); - status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h); - + sp<SurfaceBuffer> peekBuffer(); + + + class SurfaceLayer : public LayerBaseClient::Surface + { + public: + SurfaceLayer(SurfaceID id, const sp<Layer>& owner); + + private: + virtual sp<SurfaceBuffer> getBuffer(); + + sp<Layer> getOwner() const { + return static_cast<Layer*>(Surface::getOwner().get()); + } + }; + friend class SurfaceLayer; + + struct Texture { + Texture() : name(-1U), width(0), height(0), image(EGL_NO_IMAGE_KHR), + dirty(true) { } + GLuint name; + GLuint width; + GLuint height; + EGLImageKHR image; + bool dirty; + }; + sp<Surface> mSurface; bool mSecure; - LayerBitmap mBuffers[2]; + LayerBitmap mBuffers[NUM_BUFFERS]; + Texture mTextures[NUM_BUFFERS]; int32_t mFrontBufferIndex; bool mNeedsBlending; bool mResizeTransactionDone; Region mPostedDirtyRegion; sp<FreezeLock> mFreezeLock; - - GLuint mTextureName; - GLuint mTextureWidth; - GLuint mTextureHeight; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 0cf53f7..6da0bf7 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -14,14 +14,14 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <utils/Errors.h> #include <utils/Log.h> +#include <utils/IPCThreadState.h> +#include <utils/IServiceManager.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -62,7 +62,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mFlinger(flinger), mTransformed(false), mOrientation(0), - mCanUseCopyBit(false), mTransactionFlags(0), mPremultipliedAlpha(true), mIdentity(uint32_t(android_atomic_inc(&sIdentity))), @@ -265,43 +264,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform) mTransformed = transformed; mLeft = tr.tx(); mTop = tr.ty(); - - // see if we can/should use 2D h/w with the new configuration - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG); - const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS); - mCanUseCopyBit = true; - if ((mOrientation < 0) && (step > 1)) { - // arbitrary orientations not supported - mCanUseCopyBit = false; - } else if ((mOrientation > 0) && (step > 90)) { - // 90 deg rotations not supported - mCanUseCopyBit = false; - } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) { - // arbitrary scaling not supported - mCanUseCopyBit = false; - } -#if HONOR_PREMULTIPLIED_ALPHA - else if (needsBlending() && mPremultipliedAlpha) { - // pre-multiplied alpha not supported - mCanUseCopyBit = false; - } -#endif - else { - // here, we determined we can use copybit - if (tr.getType() & SkMatrix::kScale_Mask) { - // and we have scaling - if (!transparentRegionScreen.isRect()) { - // we punt because blending is cheap (h/w) and the region is - // complex, which may causes artifacts when copying - // scaled content - transparentRegionScreen.clear(); - } - } - } - } } void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) @@ -565,8 +527,7 @@ void LayerBase::loadTexture(const Region& dirty, /* * In OpenGL ES we can't specify a stride with glTexImage2D (however, - * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of - * stride). + * GL_UNPACK_ALIGNMENT is a limited form of stride). * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we * need to do something reasonable (here creating a bigger texture). * @@ -579,9 +540,11 @@ void LayerBase::loadTexture(const Region& dirty, * * This should never be a problem with POT textures */ - - tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4); - + + int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); + unpack = 1 << ((unpack > 3) ? 3 : unpack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + /* * round to POT if needed */ @@ -594,106 +557,78 @@ void LayerBase::loadTexture(const Region& dirty, texture_h = 1 << (31 - clz(t.height)); if (texture_w < t.width) texture_w <<= 1; if (texture_h < t.height) texture_h <<= 1; - if (texture_w != tw || texture_h != th) { - // we can't use DIRECT_TEXTURE since we changed the size - // of the texture - flags &= ~DisplayHardware::DIRECT_TEXTURE; - } } - - if (flags & DisplayHardware::DIRECT_TEXTURE) { - // here we're guaranteed that texture_{w|h} == t{w|h} - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGB, tw, th, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) { - // TODO: add GL_BGRA extension - } else { - // oops, we don't handle this format, try the regular path - goto regular; - } - textureWidth = tw; - textureHeight = th; - } else { + regular: - Rect bounds(dirty.bounds()); - GLvoid* data = 0; - if (texture_w!=textureWidth || texture_h!=textureHeight) { - // texture size changed, we need to create a new one - - if (!textureWidth || !textureHeight) { - // this is the first time, load the whole texture - if (texture_w==tw && texture_h==th) { - // we can do it one pass - data = t.data; - } else { - // we have to create the texture first because it - // doesn't match the size of the buffer - bounds.set(Rect(tw, th)); - } - } - - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, texture_w, texture_h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || - t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { - // just show the Y plane of YUV buffers + Rect bounds(dirty.bounds()); + GLvoid* data = 0; + if (texture_w!=textureWidth || texture_h!=textureHeight) { + // texture size changed, we need to create a new one + + if (!textureWidth || !textureHeight) { + // this is the first time, load the whole texture + if (texture_w==tw && texture_h==th) { + // we can do it one pass data = t.data; - glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, texture_w, texture_h, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); } else { - // oops, we don't handle this format! - LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, textureName, t.format); - textureName = -1; + // we have to create the texture first because it + // doesn't match the size of the buffer + bounds.set(Rect(tw, th)); } - textureWidth = texture_w; - textureHeight = texture_h; } - if (!data && textureName>=0) { - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - t.data + bounds.top*t.width*4); - } + + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, texture_w, texture_h, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || + t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { + // just show the Y plane of YUV buffers + glTexImage2D(GL_TEXTURE_2D, 0, + GL_LUMINANCE, texture_w, texture_h, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + // oops, we don't handle this format! + LOGE("layer %p, texture=%d, using format %d, which is not " + "supported by the GL", this, textureName, t.format); + textureName = -1; + } + textureWidth = texture_w; + textureHeight = texture_h; + } + if (!data && textureName>=0) { + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + t.data + bounds.top*t.stride*2); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, + t.data + bounds.top*t.stride*2); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride*4); + } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || + t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { + // just show the Y plane of YUV buffers + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_LUMINANCE, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride); } } -} - -bool LayerBase::canUseCopybit() const -{ - return mCanUseCopyBit; } // --------------------------------------------------------------------------- @@ -704,9 +639,12 @@ LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ), mIndex(i) { - if (client) { - client->bindLayer(this, i); +} +void LayerBaseClient::onFirstRef() +{ + if (client) { + client->bindLayer(this, mIndex); // Initialize this layer's control block memset(this->lcblk, 0, sizeof(layer_cblk_t)); this->lcblk->identity = mIdentity; @@ -729,11 +667,106 @@ int32_t LayerBaseClient::serverIndex() const { return 0xFFFF0000 | mIndex; } -sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const +sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() +{ + sp<Surface> s; + Mutex::Autolock _l(mLock); + s = mClientSurface.promote(); + if (s == 0) { + s = createSurface(); + mClientSurface = s; + } + return s; +} + +sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const +{ + return new Surface(clientIndex(), mIdentity, + const_cast<LayerBaseClient *>(this)); +} + +// --------------------------------------------------------------------------- + +LayerBaseClient::Surface::Surface(SurfaceID id, int identity, + const sp<LayerBaseClient>& owner) + : mToken(id), mIdentity(identity), mOwner(owner) +{ +} + + +LayerBaseClient::Surface::~Surface() { + // TODO: We now have a point here were we can clean-up the + // client's mess. + // This is also where surface id should be recycled. + //LOGD("Surface %d, heaps={%p, %p} destroyed", + // mId, mHeap[0].get(), mHeap[1].get()); +} + +sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { + sp<LayerBaseClient> owner(mOwner.promote()); + return owner; +} + + +void LayerBaseClient::Surface::getSurfaceData( + ISurfaceFlingerClient::surface_data_t* params) const { - return new Surface(clientIndex(), mIdentity); + params->token = mToken; + params->identity = mIdentity; } +status_t LayerBaseClient::Surface::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case REGISTER_BUFFERS: + case UNREGISTER_BUFFERS: + case CREATE_OVERLAY: + { + // codes that require permission check + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int self_pid = getpid(); + if (LIKELY(pid != self_pid)) { + // we're called from a different process, do the real check + if (!checkCallingPermission( + String16("android.permission.ACCESS_SURFACE_FLINGER"))) + { + const int uid = ipc->getCallingUid(); + LOGE("Permission Denial: " + "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + } + } + } + return BnSurface::onTransact(code, data, reply, flags); +} + +sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() +{ + return NULL; +} + +status_t LayerBaseClient::Surface::registerBuffers( + const ISurface::BufferHeap& buffers) +{ + return INVALID_OPERATION; +} + +void LayerBaseClient::Surface::postBuffer(ssize_t offset) +{ +} + +void LayerBaseClient::Surface::unregisterBuffers() +{ +} + +sp<OverlayRef> LayerBaseClient::Surface::createOverlay( + uint32_t w, uint32_t h, int32_t format) +{ + return NULL; +}; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index a020f44..2a4e133 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -22,6 +22,8 @@ #include <private/ui/LayerState.h> +#include <utils/RefBase.h> + #include <ui/Region.h> #include <ui/Overlay.h> @@ -37,10 +39,11 @@ class SurfaceFlinger; class DisplayHardware; class GraphicPlane; class Client; +class SurfaceBuffer; // --------------------------------------------------------------------------- -class LayerBase +class LayerBase : public RefBase { // poor man's dynamic_cast below template<typename T> @@ -72,7 +75,6 @@ public: static Vector<GLuint> deletedTextures; LayerBase(SurfaceFlinger* flinger, DisplayID display); - virtual ~LayerBase(); DisplayID dpy; mutable bool contentDirty; @@ -215,7 +217,9 @@ public: inline const State& currentState() const { return mCurrentState; } inline State& currentState() { return mCurrentState; } - static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) { + static int compareCurrentStateZ( + sp<LayerBase> const * layerA, + sp<LayerBase> const * layerB) { return layerA[0]->currentState().z - layerB[0]->currentState().z; } @@ -240,8 +244,6 @@ protected: GLint textureName, const GGLSurface& t, GLuint& textureWidth, GLuint& textureHeight) const; - bool canUseCopybit() const; - SurfaceFlinger* mFlinger; uint32_t mFlags; @@ -250,7 +252,6 @@ protected: int32_t mOrientation; GLfixed mVertices[4][2]; Rect mTransformedBounds; - bool mCanUseCopyBit; int mLeft; int mTop; @@ -269,9 +270,13 @@ protected: volatile int32_t mInvalidate; +protected: + virtual ~LayerBase(); + private: - void validateTexture(GLint textureName) const; - static int32_t sIdentity; + LayerBase(const LayerBase& rhs); + void validateTexture(GLint textureName) const; + static int32_t sIdentity; }; @@ -289,64 +294,55 @@ public: LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, Client* client, int32_t i); virtual ~LayerBaseClient(); - + virtual void onFirstRef(); Client* const client; layer_cblk_t* const lcblk; + inline uint32_t getIdentity() const { return mIdentity; } inline int32_t clientIndex() const { return mIndex; } int32_t serverIndex() const; - virtual sp<Surface> getSurface() const; - uint32_t getIdentity() const { return mIdentity; } + sp<Surface> getSurface(); + virtual sp<Surface> createSurface() const; + class Surface : public BnSurface { public: - Surface(SurfaceID id, int identity) { - mParams.token = id; - mParams.identity = identity; - } - Surface(SurfaceID id, - const sp<IMemoryHeap>& heap0, - const sp<IMemoryHeap>& heap1, - int identity) - { - mParams.token = id; - mParams.identity = identity; - mParams.heap[0] = heap0; - mParams.heap[1] = heap1; - } - virtual ~Surface() { - // TODO: We now have a point here were we can clean-up the - // client's mess. - // This is also where surface id should be recycled. - //LOGD("Surface %d, heaps={%p, %p} destroyed", - // mId, mHeap[0].get(), mHeap[1].get()); - } - + virtual void getSurfaceData( - ISurfaceFlingerClient::surface_data_t* params) const { - *params = mParams; - } - - virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) - { return INVALID_OPERATION; } - virtual void postBuffer(ssize_t offset) { } - virtual void unregisterBuffers() { }; - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format) { - return NULL; - }; + ISurfaceFlingerClient::surface_data_t* params) const; + + protected: + Surface(SurfaceID id, 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<SurfaceBuffer> getBuffer(); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); + virtual void postBuffer(ssize_t offset); + virtual void unregisterBuffers(); + virtual sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, + int32_t format); private: - ISurfaceFlingerClient::surface_data_t mParams; + friend class LayerBaseClient; + int32_t mToken; + int32_t mIdentity; + wp<LayerBaseClient> mOwner; }; -private: - int32_t mIndex; + friend class Surface; +private: + int32_t mIndex; + mutable Mutex mLock; + mutable wp<Surface> mClientSurface; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index e844350..d633a2d 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -14,170 +14,204 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> -#include <cutils/memory.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/MemoryDealer.h> +#include <utils/MemoryBase.h> #include <utils/IMemory.h> + #include <ui/PixelFormat.h> +#include <ui/Surface.h> #include <pixelflinger/pixelflinger.h> +#include "BufferAllocator.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" namespace android { -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== -LayerBitmap::LayerBitmap() - : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2) +Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), + mVStride(0) { - memset(&mSurface, 0, sizeof(mSurface)); + this->format = format; + if (w>0 && h>0) { + mInitCheck = initSize(w, h); + } } -LayerBitmap::~LayerBitmap() +Buffer::~Buffer() { - mSurface.data = 0; + if (handle) { + BufferAllocator& allocator = BufferAllocator::get(); + if (usage & BufferAllocator::USAGE_SW_READ_MASK) { + allocator.unmap(handle); + } + allocator.free(handle); + } } -status_t LayerBitmap::init(const sp<MemoryDealer>& allocator) -{ - if (mAllocator != NULL) - return BAD_VALUE; - mAllocator = allocator; - return NO_ERROR; +status_t Buffer::initCheck() const { + return mInitCheck; } -status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags) +android_native_buffer_t* Buffer::getNativeBuffer() const { - const sp<MemoryDealer>& allocator(mAllocator); - if (allocator == NULL) - return NO_INIT; - - if (UNLIKELY(w == mSurface.width && h == mSurface.height && - format == mSurface.format)) - { // same format and size, do nothing. - return NO_ERROR; - } - - PixelFormatInfo info; - getPixelFormatInfo(format, &info); - - uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED; - const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT - const uint32_t Bpp = info.bytesPerPixel; - uint32_t stride = (w + (alignment-1)) & ~(alignment-1); - stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = info.getScanlineSize(stride) * h; - if (allocFlags & MemoryDealer::PAGE_ALIGNED) { - size_t pagesize = getpagesize(); - size = (size + (pagesize-1)) & ~(pagesize-1); - } + return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this)); +} - /* FIXME: we should be able to have a h/v stride because the user of the - * surface might have stride limitation (for instance h/w codecs often do) +status_t Buffer::initSize(uint32_t w, uint32_t h) +{ + status_t err = NO_ERROR; + + BufferAllocator& allocator = BufferAllocator::get(); + + /* + * buffers used for software rendering, but h/w composition + * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE + * + * buffers used for h/w rendering and h/w composition + * are allocated with HW_RENDER | HW_TEXTURE + * + * buffers used with h/w rendering and either NPOT or no egl_image_ext + * are allocated with SW_READ_RARELY | HW_RENDER + * */ - int32_t vstride = 0; - - mAlignment = alignment; - mAllocFlags = allocFlags; - mOffset = 0; - if (mSize != size) { - // would be nice to have a reallocate() api - mBitsMemory.clear(); // free-memory - mBitsMemory = allocator->allocate(size, allocFlags); - mSize = size; + + if (mFlags & Buffer::SECURE) { + // secure buffer, don't store it into the GPU + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN; } else { - // don't erase memory if we didn't have to reallocate - flags &= ~SECURE_BITS; - } - if (mBitsMemory != 0) { - mOffset = mBitsMemory->offset(); - mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer()); - mSurface.version = sizeof(GGLSurface); - mSurface.width = w; - mSurface.height = h; - mSurface.stride = stride; - mSurface.vstride = vstride; - mSurface.format = format; - if (flags & SECURE_BITS) - clear(); + if (mFlags & Buffer::GPU) { + // the client wants to do GL rendering + usage = BufferAllocator::USAGE_HW_RENDER | + BufferAllocator::USAGE_HW_TEXTURE; + } else { + // software rendering-client, h/w composition + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN | + BufferAllocator::USAGE_HW_TEXTURE; + } } - if (mBitsMemory==0 || mSurface.data==0) { - LOGE("not enough memory for layer bitmap size=%u", size); - allocator->dump("LayerBitmap"); - mSurface.data = 0; - mSize = -1U; - return NO_MEMORY; + err = allocator.alloc(w, h, format, usage, &handle, &stride); + + if (err == NO_ERROR) { + if (usage & BufferAllocator::USAGE_SW_READ_MASK) { + err = allocator.map(handle, &bits); + } + if (err == NO_ERROR) { + width = w; + height = h; + mVStride = 0; + } } - return NO_ERROR; + + return err; } -void LayerBitmap::clear() +status_t Buffer::getBitmapSurface(copybit_image_t* img) const { - // NOTE: this memset should not be necessary, at least for - // opaque surface. However, for security reasons it's better to keep it - // (in the case of pmem, it's possible that the memory contains old - // data) - if (mSurface.data) { - memset(mSurface.data, 0, mSize); - //if (bytesPerPixel(mSurface.format) == 4) { - // android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize); - //} else { - // android_memset16((uint16_t*)mSurface.data, 0xF800, mSize); - //} - } + img->w = stride ?: width; + img->h = mVStride ?: height; + img->format = format; + + // FIXME: this should use a native_handle + img->offset = 0; + img->base = bits; + img->fd = getHandle()->data[0]; + + return NO_ERROR; } -status_t LayerBitmap::getInfo(surface_info_t* info) const +status_t Buffer::getBitmapSurface(GGLSurface* sur) const { - if (mSurface.data == 0) { - memset(info, 0, sizeof(surface_info_t)); - info->bits_offset = NO_MEMORY; - return NO_MEMORY; - } - info->w = uint16_t(width()); - info->h = uint16_t(height()); - info->stride= uint16_t(stride()); - info->bpr = uint16_t(stride() * bytesPerPixel(pixelFormat())); - info->format= uint8_t(pixelFormat()); - info->flags = surface_info_t::eBufferDirty; - info->bits_offset = ssize_t(mOffset); + sur->version = sizeof(GGLSurface); + sur->width = width; + sur->height = height; + sur->stride = stride; + sur->format = format; + sur->vstride = mVStride; + sur->data = static_cast<GGLubyte*>(bits); return NO_ERROR; } -status_t LayerBitmap::resize(uint32_t w, uint32_t h) +// =========================================================================== +// LayerBitmap +// =========================================================================== + + +LayerBitmap::LayerBitmap() + : mInfo(0), mWidth(0), mHeight(0) { - int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS); - return err; } -size_t LayerBitmap::size() const +LayerBitmap::~LayerBitmap() { - return mSize; } -void LayerBitmap::getBitmapSurface(copybit_image_t* img) const +status_t LayerBitmap::init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap()); - void* sbase = mh->base(); - const GGLSurface& t(surface()); - img->w = t.stride ?: t.width; - img->h = t.vstride ?: t.height; - img->format = t.format; - img->offset = intptr_t(t.data) - intptr_t(sbase); - img->base = sbase; - img->fd = mh->heapID(); + if (info == NULL) + return BAD_VALUE; + + mFormat = format; + mFlags = flags; + mWidth = w; + mHeight = h; + + mInfo = info; + memset(info, 0, sizeof(surface_info_t)); + info->flags = surface_info_t::eNeedNewBuffer; + + // init the buffer, but don't trigger an allocation + mBuffer = new Buffer(0, 0, format, flags); + return NO_ERROR; +} + +status_t LayerBitmap::setSize(uint32_t w, uint32_t h) +{ + Mutex::Autolock _l(mLock); + if ((w != mWidth) || (h != mHeight)) { + mWidth = w; + mHeight = h; + // this will signal the client that it needs to asks us for a new buffer + mInfo->flags = surface_info_t::eNeedNewBuffer; + } + return NO_ERROR; +} + +sp<Buffer> LayerBitmap::allocate() +{ + Mutex::Autolock _l(mLock); + sp<Buffer> buffer(mBuffer); + const uint32_t w = mWidth; + const uint32_t h = mHeight; + if (w != buffer->getWidth() || h != buffer->getHeight()) { + surface_info_t* info = mInfo; + buffer = new Buffer(w, h, mFormat, mFlags); + status_t err = buffer->initCheck(); + if (LIKELY(err == NO_ERROR)) { + info->flags = surface_info_t::eBufferDirty; + info->status = NO_ERROR; + } else { + memset(info, 0, sizeof(surface_info_t)); + info->status = NO_MEMORY; + } + mBuffer = buffer; + } + return buffer; } // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index 9ad64c4..d1f7802 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -20,63 +20,117 @@ #include <stdint.h> #include <sys/types.h> +#include <hardware/gralloc.h> + #include <utils/Atomic.h> + #include <ui/PixelFormat.h> #include <ui/Rect.h> -#include <private/ui/SharedState.h> +#include <ui/Surface.h> + +#include <EGL/android_natives.h> + #include <pixelflinger/pixelflinger.h> +#include <private/ui/SharedState.h> + + class copybit_image_t; +struct android_native_buffer_t; namespace android { // --------------------------------------------------------------------------- - class IMemory; class MemoryDealer; class LayerBitmap; -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer +// =========================================================================== -class LayerBitmap +class NativeBuffer; + +class Buffer : public SurfaceBuffer { public: - enum { - // erase memory to ensure security when necessary - SECURE_BITS = 0x00000001 + DONT_CLEAR = 0x00000001, + GPU = 0x00000002, + SECURE = 0x00000004 }; - LayerBitmap(); - ~LayerBitmap(); - status_t init(const sp<MemoryDealer>& allocator); + // creates w * h buffer + Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0); + + // return status + status_t initCheck() const; + + uint32_t getWidth() const { return width; } + uint32_t getHeight() const { return height; } + uint32_t getStride() const { return stride; } + uint32_t getUsage() const { return usage; } + PixelFormat getPixelFormat() const { return format; } + Rect getBounds() const { return Rect(width, height); } + + status_t getBitmapSurface(copybit_image_t* img) const; + status_t getBitmapSurface(GGLSurface* surface) const; + + android_native_buffer_t* getNativeBuffer() const; + +private: + friend class LightRefBase<Buffer>; + Buffer(const Buffer& rhs); + ~Buffer(); + Buffer& operator = (const Buffer& rhs); + const Buffer& operator = (const Buffer& rhs) const; + + status_t initSize(uint32_t w, uint32_t h); + + ssize_t mInitCheck; + uint32_t mFlags; + uint32_t mVStride; +}; + +// =========================================================================== +// LayerBitmap +// =========================================================================== + +class LayerBitmap +{ +public: + enum { + DONT_CLEAR = Buffer::DONT_CLEAR, + GPU = Buffer::GPU, + SECURE = Buffer::SECURE + }; + LayerBitmap(); + ~LayerBitmap(); - status_t setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags = 0); - void clear(); + status_t init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0); - status_t getInfo(surface_info_t* info) const; - status_t resize(uint32_t w, uint32_t h); + status_t setSize(uint32_t w, uint32_t h); - const GGLSurface& surface() const { return mSurface; } - Rect bounds() const { return Rect(width(), height()); } - uint32_t width() const { return surface().width; } - uint32_t height() const { return surface().height; } - uint32_t stride() const { return surface().stride; } - PixelFormat pixelFormat() const { return surface().format; } - void* serverBits() const { return surface().data; } - size_t size() const; - const sp<MemoryDealer>& getAllocator() const { return mAllocator; } - void getBitmapSurface(copybit_image_t* img) const; + sp<Buffer> allocate(); + sp<const Buffer> getBuffer() const { return mBuffer; } + sp<Buffer> getBuffer() { return mBuffer; } + + uint32_t getWidth() const { return mWidth; } + uint32_t getHeight() const { return mHeight; } + PixelFormat getPixelFormat() const { return mBuffer->getPixelFormat(); } + Rect getBounds() const { return mBuffer->getBounds(); } + private: - sp<MemoryDealer> mAllocator; - sp<IMemory> mBitsMemory; - uint32_t mAllocFlags; - ssize_t mOffset; - GGLSurface mSurface; - size_t mSize; - uint32_t mAlignment; + surface_info_t* mInfo; + sp<Buffer> mBuffer; + uint32_t mWidth; + uint32_t mHeight; + PixelFormat mFormat; + uint32_t mFlags; + // protects setSize() and allocate() + mutable Mutex mLock; }; }; // namespace android diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index d3e456f..54d5c52 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 00fab70..f22ff59 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <math.h> @@ -25,15 +23,10 @@ #include <utils/Log.h> #include <utils/StopWatch.h> -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> - #include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> #include "LayerBuffer.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -55,30 +48,12 @@ LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, LayerBuffer::~LayerBuffer() { - sp<SurfaceBuffer> s(getClientSurface()); - if (s != 0) { - s->disown(); - mClientSurface.clear(); - } -} - -sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const -{ - Mutex::Autolock _l(mLock); - return mClientSurface.promote(); } -sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const +sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const { - sp<SurfaceBuffer> s; - Mutex::Autolock _l(mLock); - s = mClientSurface.promote(); - if (s == 0) { - s = new SurfaceBuffer(clientIndex(), + return new SurfaceBuffer(clientIndex(), const_cast<LayerBuffer *>(this)); - mClientSurface = s; - } - return s; } bool LayerBuffer::needsBlending() const { @@ -192,82 +167,49 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() { // LayerBuffer::SurfaceBuffer // ============================================================================ -LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner) -: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner) +LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, + const sp<LayerBuffer>& owner) + : LayerBaseClient::Surface(id, owner->getIdentity(), owner) { } LayerBuffer::SurfaceBuffer::~SurfaceBuffer() { unregisterBuffers(); - mOwner = 0; -} - -status_t LayerBuffer::SurfaceBuffer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case REGISTER_BUFFERS: - case UNREGISTER_BUFFERS: - case CREATE_OVERLAY: - { - // codes that require permission check - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); - if (LIKELY(pid != self_pid)) { - // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) - { - const int uid = ipc->getCallingUid(); - LOGE("Permission Denial: " - "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - } - } - } - return LayerBaseClient::Surface::onTransact(code, data, reply, flags); } -status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers) +status_t LayerBuffer::SurfaceBuffer::registerBuffers( + const ISurface::BufferHeap& buffers) { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) return owner->registerBuffers(buffers); return NO_INIT; } void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset) { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) owner->postBuffer(offset); } void LayerBuffer::SurfaceBuffer::unregisterBuffers() { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) owner->unregisterBuffers(); } sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay( uint32_t w, uint32_t h, int32_t format) { sp<OverlayRef> result; - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) result = owner->createOverlay(w, h, format); return result; } -void LayerBuffer::SurfaceBuffer::disown() -{ - Mutex::Autolock _l(mLock); - mOwner = 0; -} - // ============================================================================ // LayerBuffer::Buffer // ============================================================================ @@ -437,115 +379,27 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const status_t err = NO_ERROR; NativeBuffer src(buffer->getBuffer()); const Rect& transformedBounds = mLayer.getTransformedBounds(); - const int can_use_copybit = mLayer.canUseCopybit(); - - if (can_use_copybit) { - const int src_width = src.crop.r - src.crop.l; - const int src_height = src.crop.b - src.crop.t; - int W = transformedBounds.width(); - int H = transformedBounds.height(); - if (mLayer.getOrientation() & Transform::ROT_90) { - int t(W); W=H; H=t; - } - - /* With LayerBuffer, it is likely that we'll have to rescale the - * surface, because this is often used for video playback or - * camera-preview. Since we want these operation as fast as possible - * we make sure we can use the 2D H/W even if it doesn't support - * the requested scale factor, in which case we perform the scaling - * in several passes. */ - - copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine(); - const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); - const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); - - float xscale = 1.0f; - if (src_width > W*min) xscale = 1.0f / min; - else if (src_width*mag < W) xscale = mag; - - float yscale = 1.0f; - if (src_height > H*min) yscale = 1.0f / min; - else if (src_height*mag < H) yscale = mag; - - if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) { - if (UNLIKELY(mTemporaryDealer == 0)) { - // allocate a memory-dealer for this the first time - mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - mTempBitmap.init(mTemporaryDealer); - } - - const int tmp_w = floorf(src_width * xscale); - const int tmp_h = floorf(src_height * yscale); - err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format); - - if (LIKELY(err == NO_ERROR)) { - NativeBuffer tmp; - mTempBitmap.getBitmapSurface(&tmp.img); - tmp.crop.l = 0; - tmp.crop.t = 0; - tmp.crop.r = tmp.img.w; - tmp.crop.b = tmp.img.h; - - region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - err = copybit->stretch(copybit, - &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it); - src = tmp; - } - } - - const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware()); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(transformedBounds); - const State& s(mLayer.drawingState()); - region_iterator it(clip); - - // pick the right orientation for this buffer - int orientation = mLayer.getOrientation(); - if (UNLIKELY(mBufferHeap.transform)) { - Transform rot90; - GraphicPlane::orientationToTransfrom( - ISurfaceComposer::eOrientation90, 0, 0, &rot90); - const Transform& planeTransform(mLayer.graphicPlane(0).transform()); - const Layer::State& s(mLayer.drawingState()); - Transform tr(planeTransform * s.transform * rot90); - orientation = tr.getOrientation(); - } - - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - err = copybit->stretch(copybit, - &dst, &src.img, &drect, &src.crop, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } - } - if (!can_use_copybit || err) { - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = mLayer.createTexture(); - } - GLuint w = 0; - GLuint h = 0; - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.crop.r; - t.height = src.crop.b; - t.stride = src.img.w; - t.vstride= src.img.h; - t.format = src.img.format; - t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); - const Region dirty(Rect(t.width, t.height)); - mLayer.loadTexture(dirty, mTextureName, t, w, h); - mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); + // FIXME: We should model this after the overlay stuff + + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = mLayer.createTexture(); } + GLuint w = 0; + GLuint h = 0; + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.crop.r; + t.height = src.crop.b; + t.stride = src.img.w; + t.vstride= src.img.h; + t.format = src.img.format; + t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); + const Region dirty(Rect(t.width, t.height)); + + // FIXME: Use EGLImage extension for this + mLayer.loadTexture(dirty, mTextureName, t, w, h); + mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); } diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 2dc77f1..2d44121 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -22,7 +22,6 @@ #include <utils/IMemory.h> #include <private/ui/LayerState.h> -#include <EGL/eglnatives.h> #include "LayerBase.h" #include "LayerBitmap.h" @@ -64,7 +63,7 @@ public: virtual bool needsBlending() const; - virtual sp<LayerBaseClient::Surface> getSurface() const; + virtual sp<LayerBaseClient::Surface> createSurface() const; virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); @@ -126,8 +125,7 @@ private: status_t mStatus; ISurface::BufferHeap mBufferHeap; size_t mBufferSize; - mutable sp<MemoryDealer> mTemporaryDealer; - mutable LayerBitmap mTempBitmap; + mutable sp<android::Buffer> mTempBitmap; mutable GLuint mTextureName; }; @@ -179,23 +177,19 @@ private: class SurfaceBuffer : public LayerBaseClient::Surface { public: - SurfaceBuffer(SurfaceID id, LayerBuffer* owner); + SurfaceBuffer(SurfaceID id, const sp<LayerBuffer>& owner); virtual ~SurfaceBuffer(); - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); + virtual sp<OverlayRef> createOverlay( uint32_t w, uint32_t h, int32_t format); - void disown(); private: - LayerBuffer* getOwner() const { - Mutex::Autolock _l(mLock); - return mOwner; + sp<LayerBuffer> getOwner() const { + return static_cast<LayerBuffer*>(Surface::getOwner().get()); } - mutable Mutex mLock; - LayerBuffer* mOwner; }; friend class SurfaceFlinger; @@ -203,10 +197,8 @@ private: mutable Mutex mLock; sp<Source> mSource; - bool mInvalidate; bool mNeedsBlending; - mutable wp<SurfaceBuffer> mClientSurface; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index 0c347cc..f2519c4 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> @@ -25,7 +23,6 @@ #include "LayerDim.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" namespace android { @@ -33,8 +30,6 @@ namespace android { const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; const char* const LayerDim::typeID = "LayerDim"; -sp<MemoryDealer> LayerDim::mDimmerDealer; -LayerBitmap LayerDim::mDimmerBitmap; // --------------------------------------------------------------------------- @@ -46,14 +41,6 @@ LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) { - // must only be called once. - mDimmerDealer = flinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - if (mDimmerDealer != 0) { - mDimmerBitmap.init(mDimmerDealer); - mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565); - mDimmerBitmap.clear(); - } } LayerDim::~LayerDim() @@ -62,48 +49,25 @@ LayerDim::~LayerDim() void LayerDim::onDraw(const Region& clip) const { + // FIXME: on some h/w (like msm7K, it will be faster to use a texture) + const State& s(drawingState()); - Region::iterator iterator(clip); if (s.alpha>0 && iterator) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - mDimmerBitmap.getBitmapSurface(&src); - const copybit_rect_t& srect(drect); - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - const GGLfixed alpha = (s.alpha << 16)/255; - const uint32_t fbHeight = hw.getHeight(); - glDisable(GL_TEXTURE_2D); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4x(0, 0, 0, alpha); - glVertexPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } + const GGLfixed alpha = (s.alpha << 16)/255; + const uint32_t fbHeight = hw.getHeight(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DITHER); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColor4x(0, 0, 0, alpha); + glVertexPointer(2, GL_FIXED, 0, mVertices); + Rect r; + while (iterator.iterate(&r)) { + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } } diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h index 3e37a47..0d5bb98 100644 --- a/libs/surfaceflinger/LayerDim.h +++ b/libs/surfaceflinger/LayerDim.h @@ -44,10 +44,6 @@ public: virtual bool isSecure() const { return false; } static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h); - -private: - static sp<MemoryDealer> mDimmerDealer; - static LayerBitmap mDimmerBitmap; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp index 3e4035e..095fed8 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ b/libs/surfaceflinger/LayerOrientationAnim.cpp @@ -24,10 +24,6 @@ #include <utils/Log.h> #include <utils/StopWatch.h> -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - #include "BlurFilter.h" #include "LayerBase.h" #include "LayerOrientationAnim.h" @@ -57,8 +53,8 @@ const float DIM_TARGET = 0.40f; LayerOrientationAnim::LayerOrientationAnim( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmapIn, - const LayerBitmap& bitmapOut) + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut) : LayerOrientationAnimBase(flinger, display), mAnim(anim), mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) @@ -108,11 +104,6 @@ void LayerOrientationAnim::validateVisibility(const Transform&) mTop = tr.ty(); transparentRegionScreen.clear(); mTransformed = true; - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - mCanUseCopyBit = true; - } } void LayerOrientationAnim::onOrientationCompleted() @@ -135,7 +126,7 @@ void LayerOrientationAnim::onDraw(const Region& clip) const // make a copy of what's on screen copybit_image_t image; - mBitmapOut.getBitmapSurface(&image); + mBitmapOut->getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -194,7 +185,7 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); + //hw.getDisplaySurface(&dst); // clear screen // TODO: with update on demand, we may be able @@ -212,10 +203,10 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut } copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); copybit_image_t srcOut; - mBitmapOut.getBitmapSurface(&srcOut); + mBitmapOut->getBitmapSurface(&srcOut); const int w = dst.w*scale; const int h = dst.h*scale; @@ -225,78 +216,54 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut const copybit_rect_t srect = { 0, 0, src.w, src.h }; const Region reg(Rect( drect.l, drect.t, drect.r, drect.b )); - int err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - if (alphaIn > 0) { - region_iterator it(reg); - copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255)); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (!err && alphaOut > 0.0f) { - region_iterator it(reg); - copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255)); - err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it); - } - LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); + Transform tr; + tr.set(scale,0,0,scale); + tr.set(xc, yc); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; } - if (!can_use_copybit || err) { - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.w; - t.height = src.h; - t.stride = src.w; - t.vstride= src.h; - t.format = src.format; - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - Transform tr; - tr.set(scale,0,0,scale); - tr.set(xc, yc); - - // FIXME: we should not access mVertices and mDrawingState like that, - // but since we control the animation, we know it's going to work okay. - // eventually we'd need a more formal way of doing things like this. - LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // Too slow to do this in software - self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; - } - - if (alphaIn > 0.0f) { - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureNameIn == -1LU)) { - mTextureNameIn = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureNameIn, t, w, h); - } - self.mDrawingState.alpha = int(alphaIn*255); - drawWithOpenGL(reg, mTextureNameIn, t); + if (alphaIn > 0.0f) { + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); } + self.mDrawingState.alpha = int(alphaIn*255); + drawWithOpenGL(reg, mTextureNameIn, t); + } - if (alphaOut > 0.0f) { - t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = int(alphaOut*255); - drawWithOpenGL(reg, mTextureName, t); + if (alphaOut > 0.0f) { + t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); } + self.mDrawingState.alpha = int(alphaOut*255); + drawWithOpenGL(reg, mTextureName, t); } } diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h index 365c6ae..472c45a 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ b/libs/surfaceflinger/LayerOrientationAnim.h @@ -52,8 +52,8 @@ public: LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmapIn, - const LayerBitmap& bitmapOut); + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut); virtual ~LayerOrientationAnim(); void onOrientationCompleted(); @@ -90,8 +90,8 @@ private: }; OrientationAnimation* mAnim; - LayerBitmap mBitmapIn; - LayerBitmap mBitmapOut; + sp<Buffer> mBitmapIn; + sp<Buffer> mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp index 89ffb19..a3bf014 100644 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp +++ b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp @@ -23,10 +23,6 @@ #include <utils/Errors.h> #include <utils/Log.h> -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - #include "LayerBase.h" #include "LayerOrientationAnim.h" #include "LayerOrientationAnimRotate.h" @@ -51,10 +47,10 @@ const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; LayerOrientationAnimRotate::LayerOrientationAnimRotate( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmap, - const LayerBitmap& bitmapIn) + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut) : LayerOrientationAnimBase(flinger, display), mAnim(anim), - mBitmap(bitmap), mBitmapIn(bitmapIn), + mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) { mStartTime = systemTime(); @@ -103,7 +99,6 @@ void LayerOrientationAnimRotate::validateVisibility(const Transform&) mTop = tr.ty(); transparentRegionScreen.clear(); mTransformed = true; - mCanUseCopyBit = false; } void LayerOrientationAnimRotate::onOrientationCompleted() @@ -126,7 +121,7 @@ void LayerOrientationAnimRotate::onDraw(const Region& clip) const if (mFirstRedraw) { // make a copy of what's on screen copybit_image_t image; - mBitmapIn.getBitmapSurface(&image); + mBitmapIn->getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -185,7 +180,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); + //hw.getDisplaySurface(&dst); // clear screen // TODO: with update on demand, we may be able @@ -200,7 +195,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const const int h = dst.h; copybit_image_t src; - mBitmap.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); const copybit_rect_t srect = { 0, 0, src.w, src.h }; @@ -255,7 +250,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const tr.transform(self.mVertices[3], src.w, 0); copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); if (UNLIKELY(mTextureNameIn == -1LU)) { mTextureNameIn = createTexture(); diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/LayerOrientationAnimRotate.h index 5fbbd42..a675c79 100644 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.h +++ b/libs/surfaceflinger/LayerOrientationAnimRotate.h @@ -40,8 +40,8 @@ public: LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& zoomOut, - const LayerBitmap& zoomIn); + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut); virtual ~LayerOrientationAnimRotate(); void onOrientationCompleted(); @@ -55,8 +55,8 @@ private: void drawScaled(float angle, float scale, float alpha) const; OrientationAnimation* mAnim; - LayerBitmap mBitmap; - LayerBitmap mBitmapIn; + sp<Buffer> mBitmapIn; + sp<Buffer> mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp index 70eec8d..a6c9c28 100644 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ b/libs/surfaceflinger/OrientationAnimation.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdint.h> #include <sys/types.h> #include <limits.h> @@ -24,7 +22,6 @@ #include "LayerOrientationAnimRotate.h" #include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -35,9 +32,6 @@ namespace android { OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) { - // allocate a memory-dealer for this the first time - mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap( - ISurfaceComposer::eHardware); } OrientationAnimation::~OrientationAnimation() @@ -98,19 +92,14 @@ bool OrientationAnimation::prepare() const uint32_t w = hw.getWidth(); const uint32_t h = hw.getHeight(); - LayerBitmap bitmap; - bitmap.init(mTemporaryDealer); - bitmap.setBits(w, h, 1, hw.getFormat()); - - LayerBitmap bitmapIn; - bitmapIn.init(mTemporaryDealer); - bitmapIn.setBits(w, h, 1, hw.getFormat()); + sp<Buffer> bitmap = new Buffer(w, h, hw.getFormat()); + sp<Buffer> bitmapIn = new Buffer(w, h, hw.getFormat()); copybit_image_t front; - bitmap.getBitmapSurface(&front); - hw.copyFrontToImage(front); + bitmap->getBitmapSurface(&front); + hw.copyFrontToImage(front); // FIXME: we need an extension to do this - LayerOrientationAnimBase* l; + sp<LayerOrientationAnimBase> l; if (mType & 0x80) { l = new LayerOrientationAnimRotate( @@ -152,7 +141,7 @@ bool OrientationAnimation::finished() { mState = DONE; mFlinger->removeLayer(mLayerOrientationAnim); - mLayerOrientationAnim = NULL; + mLayerOrientationAnim.clear(); return true; } diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h index cafa38d..8ba6621 100644 --- a/libs/surfaceflinger/OrientationAnimation.h +++ b/libs/surfaceflinger/OrientationAnimation.h @@ -72,8 +72,7 @@ private: bool finished(); sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mTemporaryDealer; - LayerOrientationAnimBase* mLayerOrientationAnim; + sp< LayerOrientationAnimBase > mLayerOrientationAnim; int mState; uint32_t mType; }; diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index de64f55..b4f443f 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdio.h> #include <stdint.h> @@ -40,12 +38,12 @@ #include <ui/PixelFormat.h> #include <ui/DisplayInfo.h> -#include <ui/EGLDisplaySurface.h> #include <pixelflinger/pixelflinger.h> #include <GLES/gl.h> #include "clz.h" +#include "BufferAllocator.h" #include "CPUGauge.h" #include "Layer.h" #include "LayerBlur.h" @@ -55,10 +53,8 @@ #include "LayerOrientationAnim.h" #include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" -#include "GPUHardware/GPUHardware.h" #define DISPLAY_COUNT 1 @@ -86,30 +82,30 @@ SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs) } ssize_t SurfaceFlinger::LayerVector::indexOf( - LayerBase* key, size_t guess) const + const sp<LayerBase>& key, size_t guess) const { if (guess<size() && lookup.keyAt(guess) == key) return guess; const ssize_t i = lookup.indexOfKey(key); if (i>=0) { const size_t idx = lookup.valueAt(i); - LOG_ASSERT(layers[idx]==key, + LOGE_IF(layers[idx]!=key, "LayerVector[%p]: layers[%d]=%p, key=%p", - this, int(idx), layers[idx], key); + this, int(idx), layers[idx].get(), key.get()); return idx; } return i; } ssize_t SurfaceFlinger::LayerVector::add( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) + const sp<LayerBase>& layer, + Vector< sp<LayerBase> >::compar_t cmp) { size_t count = layers.size(); ssize_t l = 0; ssize_t h = count-1; ssize_t mid; - LayerBase* const* a = layers.array(); + sp<LayerBase> const* a = layers.array(); while (l <= h) { mid = l + (h - l)/2; const int c = cmp(a+mid, &layer); @@ -132,14 +128,14 @@ ssize_t SurfaceFlinger::LayerVector::add( return order; } -ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) +ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer) { const ssize_t keyIndex = lookup.indexOfKey(layer); if (keyIndex >= 0) { const size_t index = lookup.valueAt(keyIndex); - LOG_ASSERT(layers[index]==layer, + LOGE_IF(layers[index]!=layer, "LayerVector[%p]: layers[%u]=%p, layer=%p", - this, int(index), layers[index], layer); + this, int(index), layers[index].get(), layer.get()); layers.removeItemsAt(index); lookup.removeItemsAt(keyIndex); const size_t count = lookup.size(); @@ -154,8 +150,8 @@ ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) } ssize_t SurfaceFlinger::LayerVector::reorder( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) + const sp<LayerBase>& layer, + Vector< sp<LayerBase> >::compar_t cmp) { // XXX: it's a little lame. but oh well... ssize_t err = remove(layer); @@ -173,6 +169,7 @@ SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransactionCount(0), + mLayersRemoved(false), mBootTime(systemTime()), mLastScheduledBroadcast(NULL), mVisibleRegionsDirty(false), @@ -223,11 +220,6 @@ SurfaceFlinger::~SurfaceFlinger() delete mOrientationAnimation; } -copybit_device_t* SurfaceFlinger::getBlitEngine() const -{ - return graphicPlane(0).displayHardware().getBlitEngine(); -} - overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const { return graphicPlane(0).displayHardware().getOverlayEngine(); @@ -238,20 +230,6 @@ sp<IMemory> SurfaceFlinger::getCblk() const return mServerCblkMemory; } -status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu) -{ - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - status_t err = mGPU->request(pid, callback, gpu); - return err; -} - -status_t SurfaceFlinger::revokeGPU() -{ - return mGPU->friendlyRevoke(); -} - sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection() { Mutex::Autolock _l(mStateLock); @@ -279,11 +257,13 @@ void SurfaceFlinger::destroyConnection(ClientID cid) Client* const client = mClientsMap.valueFor(cid); if (client) { // free all the layers this client owns - const Vector<LayerBaseClient*>& layers = client->getLayers(); + const Vector< wp<LayerBaseClient> >& layers = client->getLayers(); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - LayerBaseClient* const layer = layers[i]; - removeLayer_l(layer); + sp<LayerBaseClient> layer(layers[i].promote()); + if (layer != 0) { + removeLayer_l(layer); + } } // the resources associated with this client will be freed @@ -338,9 +318,6 @@ static inline uint16_t pack565(int r, int g, int b) { return (r<<11)|(g<<5)|b; } -// this is defined in libGLES_CM.so -extern ISurfaceComposer* GLES_localSurfaceManager; - status_t SurfaceFlinger::readyToRun() { LOGI( "SurfaceFlinger's main thread ready to run. " @@ -357,17 +334,6 @@ status_t SurfaceFlinger::readyToRun() LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); new(mServerCblk) surface_flinger_cblk_t; - // get a reference to the GPU if we have one - mGPU = GPUFactory::getGPU(); - - // create the surface Heap manager, which manages the heaps - // (be it in RAM or VRAM) where surfaces are allocated - // We give 8 MB per client. - mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20); - - - GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this); - // we only support one display currently int dpy = 0; @@ -597,13 +563,11 @@ void SurfaceFlinger::handleConsoleEvents() if (mDeferReleaseConsole && hw.canDraw()) { // We got the release signal before the aquire signal mDeferReleaseConsole = false; - revokeGPU(); hw.releaseScreen(); } if (what & eConsoleReleased) { if (hw.canDraw()) { - revokeGPU(); hw.releaseScreen(); } else { mDeferReleaseConsole = true; @@ -628,7 +592,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) const bool layersNeedTransaction = transactionFlags & eTraversalNeeded; if (layersNeedTransaction) { for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -685,8 +649,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // some layers might have been removed, so // we need to update the regions they're exposing. - size_t c = mRemovedLayers.size(); - if (c) { + if (mLayersRemoved) { mVisibleRegionsDirty = true; } @@ -723,7 +686,7 @@ void SurfaceFlinger::computeVisibleRegions( size_t i = currentLayers.size(); while (i--) { - LayerBase* const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; layer->validateVisibility(planeTransform); // start with the whole surface at its current location @@ -823,9 +786,9 @@ bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) { bool recomputeVisibleRegions = false; size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); + sp<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->lockPageFlip(recomputeVisibleRegions); } return recomputeVisibleRegions; @@ -836,9 +799,9 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) const GraphicPlane& plane(graphicPlane(0)); const Transform& planeTransform(plane.transform()); size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); + sp<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->unlockPageFlip(planeTransform, mDirtyRegion); } } @@ -889,9 +852,9 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) const SurfaceFlinger& flinger(*this); const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); - LayerBase const* const* const layers = drawingLayers.array(); + sp<LayerBase> const* const layers = drawingLayers.array(); for (size_t i=0 ; i<count ; ++i) { - LayerBase const * const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; const Region& visibleRegion(layer->visibleRegionScreen); if (!visibleRegion.isEmpty()) { const Region clip(dirty.intersect(visibleRegion)); @@ -906,9 +869,9 @@ void SurfaceFlinger::unlockClients() { const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); - LayerBase* const* const layers = drawingLayers.array(); + sp<LayerBase> const* const layers = drawingLayers.array(); for (size_t i=0 ; i<count ; ++i) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->finishPageFlip(); } } @@ -1051,7 +1014,7 @@ void SurfaceFlinger::debugShowFPS() const // XXX: mFPS has the value we want } -status_t SurfaceFlinger::addLayer(LayerBase* layer) +status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer) { Mutex::Autolock _l(mStateLock); addLayer_l(layer); @@ -1059,7 +1022,7 @@ status_t SurfaceFlinger::addLayer(LayerBase* layer) return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(LayerBase* layer) +status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) { Mutex::Autolock _l(mStateLock); removeLayer_l(layer); @@ -1067,32 +1030,31 @@ status_t SurfaceFlinger::removeLayer(LayerBase* layer) return NO_ERROR; } -status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer) +status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) { layer->forceVisibilityTransaction(); setTransactionFlags(eTraversalNeeded); return NO_ERROR; } -status_t SurfaceFlinger::addLayer_l(LayerBase* layer) +status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) { ssize_t i = mCurrentState.layersSortedByZ.add( layer, &LayerBase::compareCurrentStateZ); - LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer); - if (lbc) { + sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); + if (lbc != 0) { mLayerMap.add(lbc->serverIndex(), lbc); } - mRemovedLayers.remove(layer); return NO_ERROR; } -status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase) +status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) { ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); if (index >= 0) { - mRemovedLayers.add(layerBase); - LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase); - if (layer) { + mLayersRemoved = true; + sp<LayerBaseClient> layer = LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get()); + if (layer != 0) { mLayerMap.removeItem(layer->serverIndex()); } return NO_ERROR; @@ -1107,8 +1069,8 @@ status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase) void SurfaceFlinger::free_resources_l() { // Destroy layers that were removed - destroy_all_removed_layers_l(); - + mLayersRemoved = false; + // free resources associated with disconnected clients SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts); Vector<Client*>& disconnectedClients(mDisconnectedClients); @@ -1128,22 +1090,6 @@ void SurfaceFlinger::free_resources_l() disconnectedClients.clear(); } -void SurfaceFlinger::destroy_all_removed_layers_l() -{ - size_t c = mRemovedLayers.size(); - while (c--) { - LayerBase* const removed_layer = mRemovedLayers[c]; - - LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0, - "layer %p removed but still in the current state list", - removed_layer); - - delete removed_layer; - } - mRemovedLayers.clear(); -} - - uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { return android_atomic_and(~flags, &mTransactionFlags) & flags; @@ -1227,7 +1173,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - LayerBaseClient* layer = 0; + sp<LayerBaseClient> layer; sp<LayerBaseClient::Surface> surfaceHandle; Mutex::Autolock _l(mStateLock); Client* const c = mClientsMap.valueFor(clientId); @@ -1259,7 +1205,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, break; } - if (layer) { + if (layer != 0) { setTransactionFlags(eTransactionNeeded); surfaceHandle = layer->getSurface(); if (surfaceHandle != 0) @@ -1269,7 +1215,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, return surfaceHandle; } -LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { @@ -1284,44 +1230,43 @@ LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( break; } - Layer* layer = new Layer(this, display, client, id); + sp<Layer> layer = new Layer(this, display, client, id); status_t err = layer->setBuffers(client, w, h, format, flags); if (LIKELY(err == NO_ERROR)) { layer->initStates(w, h, flags); addLayer_l(layer); } else { LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); - delete layer; - return 0; + layer.clear(); } return layer; } -LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerBlur* layer = new LayerBlur(this, display, client, id); + sp<LayerBlur> layer = new LayerBlur(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerDim* layer = new LayerDim(this, display, client, id); + sp<LayerDim> layer = new LayerDim(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerBuffer* layer = new LayerBuffer(this, display, client, id); + sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; @@ -1330,7 +1275,7 @@ LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked( status_t SurfaceFlinger::destroySurface(SurfaceID index) { Mutex::Autolock _l(mStateLock); - LayerBaseClient* const layer = getLayerUser_l(index); + const sp<LayerBaseClient>& layer = getLayerUser_l(index); status_t err = removeLayer_l(layer); if (err < 0) return err; @@ -1348,8 +1293,8 @@ status_t SurfaceFlinger::setClientState( cid <<= 16; for (int i=0 ; i<count ; i++) { const layer_state_t& s = states[i]; - LayerBaseClient* layer = getLayerUser_l(s.surface | cid); - if (layer) { + const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid); + if (layer != 0) { const uint32_t what = s.what; // check if it has been destroyed first if (what & eDestroyed) { @@ -1401,9 +1346,10 @@ status_t SurfaceFlinger::setClientState( return NO_ERROR; } -LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const +sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const { - return mLayerMap.valueFor(s); + sp<LayerBaseClient> layer = mLayerMap.valueFor(s); + return layer; } void SurfaceFlinger::screenReleased(int dpy) @@ -1446,7 +1392,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { /*** LayerBase ***/ - LayerBase const * const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; const Layer::State& s = layer->drawingState(); snprintf(buffer, SIZE, "+ %s %p\n" @@ -1454,7 +1400,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " "needsBlending=%1d, invalidate=%1d, " "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - layer->getTypeID(), layer, + layer->getTypeID(), layer.get(), s.z, layer->tx(), layer->ty(), s.w, s.h, layer->needsBlending(), layer->contentDirty, s.alpha, s.flags, @@ -1463,9 +1409,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); buffer[0] = 0; /*** LayerBaseClient ***/ - LayerBaseClient* const lbc = - LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer); - if (lbc) { + sp<LayerBaseClient> lbc = + LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); + if (lbc != 0) { snprintf(buffer, SIZE, " " "id=0x%08x, client=0x%08x, identity=%u\n", @@ -1475,18 +1421,20 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); buffer[0] = 0; /*** Layer ***/ - Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer); - if (l) { + sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get()); + if (l != 0) { const LayerBitmap& buf0(l->getBuffer(0)); const LayerBitmap& buf1(l->getBuffer(1)); snprintf(buffer, SIZE, " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d," + "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," " freezeLock=%p, swapState=0x%08x\n", l->pixelFormat(), - buf0.width(), buf0.height(), buf0.stride(), - buf1.width(), buf1.height(), buf1.stride(), - l->getTextureName(), l->getFreezeLock().get(), + buf0.getWidth(), buf0.getHeight(), + buf0.getBuffer()->getStride(), + buf1.getWidth(), buf1.getHeight(), + buf1.getBuffer()->getStride(), + l->getFreezeLock().get(), l->lcblk->swapState); } result.append(buffer); @@ -1503,19 +1451,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) mCurrentState.orientation, hw.canDraw()); result.append(buffer); - sp<AllocatorInterface> allocator; - if (mGPU != 0) { - snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner()); - result.append(buffer); - allocator = mGPU->getAllocator(); - if (allocator != 0) { - allocator->dump(result, "GPU Allocator"); - } - } - allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM); - if (allocator != 0) { - allocator->dump(result, "PMEM Allocator"); - } + const BufferAllocator& alloc(BufferAllocator::get()); + alloc.dump(result); } write(fd, result.string(), result.size()); return NO_ERROR; @@ -1532,7 +1469,6 @@ status_t SurfaceFlinger::onTransact( case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: case BOOT_FINISHED: - case REVOKE_GPU: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); @@ -1599,12 +1535,6 @@ status_t SurfaceFlinger::onTransact( signalEvent(); } return NO_ERROR; - case 1005: // ask GPU revoke - mGPU->friendlyRevoke(); - return NO_ERROR; - case 1006: // revoke GPU - mGPU->unconditionalRevoke(); - return NO_ERROR; case 1007: // set mFreezeCount mFreezeCount = data.readInt32(); return NO_ERROR; @@ -1633,7 +1563,6 @@ status_t SurfaceFlinger::onTransact( Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) { - mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(); const int pgsize = getpagesize(); const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1)); mCblkHeap = new MemoryDealer(cblksize); @@ -1653,10 +1582,6 @@ Client::~Client() { } } -const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const { - return mFlinger->getSurfaceHeapManager(); -} - int32_t Client::generateId(int pid) { const uint32_t i = clz( ~mBitmap ); @@ -1668,13 +1593,15 @@ int32_t Client::generateId(int pid) mBitmap |= 1<<(31-i); return i; } -status_t Client::bindLayer(LayerBaseClient* layer, int32_t id) + +status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id) { ssize_t idx = mInUse.indexOf(id); if (idx < 0) return NAME_NOT_FOUND; return mLayers.insertAt(layer, idx); } + void Client::free(int32_t id) { ssize_t idx = mInUse.remove(uint8_t(id)); @@ -1684,27 +1611,18 @@ void Client::free(int32_t id) } } -sp<MemoryDealer> Client::createAllocator(uint32_t flags) -{ - sp<MemoryDealer> allocator; - allocator = getSurfaceHeapManager()->createHeap( - flags, getClientPid(), mSharedHeapAllocator); - return allocator; -} - bool Client::isValid(int32_t i) const { return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i))); } -const uint8_t* Client::inUseArray() const { - return mInUse.array(); -} -size_t Client::numActiveLayers() const { - return mInUse.size(); -} -LayerBaseClient* Client::getLayerUser(int32_t i) const { + +sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { + sp<LayerBaseClient> lbc; ssize_t idx = mInUse.indexOf(uint8_t(i)); - if (idx<0) return 0; - return mLayers[idx]; + if (idx >= 0) { + lbc = mLayers[idx].promote(); + LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx)); + } + return lbc; } void Client::dump(const char* what) @@ -1841,6 +1759,10 @@ const Transform& GraphicPlane::transform() const { return mGlobalTransform; } +EGLDisplay GraphicPlane::getEGLDisplay() const { + return mHw->getEGLDisplay(); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index e023182..57c6ca8 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -26,6 +26,7 @@ #include <utils/Atomic.h> #include <utils/Errors.h> #include <utils/MemoryDealer.h> +#include <utils/RefBase.h> #include <ui/PixelFormat.h> #include <ui/ISurfaceComposer.h> @@ -52,13 +53,10 @@ class Client; class BClient; class DisplayHardware; class FreezeLock; -class GPUHardwareInterface; -class IGPUCallback; class Layer; class LayerBuffer; class LayerOrientationAnim; class OrientationAnimation; -class SurfaceHeapManager; typedef int32_t ClientID; @@ -75,17 +73,13 @@ public: int32_t generateId(int pid); void free(int32_t id); - status_t bindLayer(LayerBaseClient* layer, int32_t id); - sp<MemoryDealer> createAllocator(uint32_t memory_type); + status_t bindLayer(const sp<LayerBaseClient>& layer, int32_t id); inline bool isValid(int32_t i) const; - inline const uint8_t* inUseArray() const; - inline size_t numActiveLayers() const; - LayerBaseClient* getLayerUser(int32_t i) const; - const Vector<LayerBaseClient*>& getLayers() const { return mLayers; } + sp<LayerBaseClient> getLayerUser(int32_t i) const; + const Vector< wp<LayerBaseClient> >& getLayers() const { return mLayers; } const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; } void dump(const char* what); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const; // pointer to this client's control block per_client_cblk_t* ctrlblk; @@ -95,15 +89,13 @@ public: private: int getClientPid() const { return mPid; } - int mPid; - uint32_t mBitmap; - SortedVector<uint8_t> mInUse; - Vector<LayerBaseClient*> mLayers; - sp<MemoryDealer> mCblkHeap; - sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mSharedHeapAllocator; - sp<MemoryDealer> mPMemAllocator; - sp<IMemory> mCblkMemory; + int mPid; + uint32_t mBitmap; + SortedVector<uint8_t> mInUse; + Vector< wp<LayerBaseClient> > mLayers; + sp<MemoryDealer> mCblkHeap; + sp<SurfaceFlinger> mFlinger; + sp<IMemory> mCblkMemory; }; // --------------------------------------------------------------------------- @@ -126,6 +118,8 @@ public: const DisplayHardware& displayHardware() const; const Transform& transform() const; + EGLDisplay getEGLDisplay() const; + private: GraphicPlane(const GraphicPlane&); GraphicPlane operator = (const GraphicPlane&); @@ -169,28 +163,16 @@ public: virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual void signal() const; - virtual status_t requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu); - virtual status_t revokeGPU(); void screenReleased(DisplayID dpy); void screenAcquired(DisplayID dpy); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { - return mSurfaceHeapManager; - } - - const sp<GPUHardwareInterface>& getGPU() const { - return mGPU; - } - - copybit_device_t* getBlitEngine() const; overlay_control_device_t* getOverlayEngine() const; - status_t removeLayer(LayerBase* layer); - status_t addLayer(LayerBase* layer); - status_t invalidateLayerVisibility(LayerBase* layer); + status_t removeLayer(const sp<LayerBase>& layer); + status_t addLayer(const sp<LayerBase>& layer); + status_t invalidateLayerVisibility(const sp<LayerBase>& layer); private: friend class BClient; @@ -205,20 +187,25 @@ private: DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + sp<LayerBaseClient> createNormalSurfaceLocked( + Client* client, DisplayID display, + int32_t id, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags); - LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createBlurSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createDimSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createPushBuffersSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - status_t destroySurface(SurfaceID surface_id); - status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); + status_t destroySurface(SurfaceID surface_id); + status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); class LayerVector { @@ -226,15 +213,15 @@ private: inline LayerVector() { } LayerVector(const LayerVector&); inline size_t size() const { return layers.size(); } - inline LayerBase*const* array() const { return layers.array(); } - ssize_t add(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t remove(LayerBase*); - ssize_t reorder(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t indexOf(LayerBase* key, size_t guess=0) const; - inline LayerBase* operator [] (size_t i) const { return layers[i]; } + inline sp<LayerBase> const* array() const { return layers.array(); } + ssize_t add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t); + ssize_t remove(const sp<LayerBase>&); + ssize_t reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t); + ssize_t indexOf(const sp<LayerBase>& key, size_t guess=0) const; + inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; } private: - KeyedVector<LayerBase*, size_t> lookup; - Vector<LayerBase*> layers; + KeyedVector< sp<LayerBase> , size_t> lookup; + Vector< sp<LayerBase> > layers; }; struct State { @@ -299,10 +286,9 @@ private: void destroyConnection(ClientID cid); - LayerBaseClient* getLayerUser_l(SurfaceID index) const; - status_t addLayer_l(LayerBase* layer); - status_t removeLayer_l(LayerBase* layer); - void destroy_all_removed_layers_l(); + sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const; + status_t addLayer_l(const sp<LayerBase>& layer); + status_t removeLayer_l(const sp<LayerBase>& layer); void free_resources_l(); uint32_t getTransactionFlags(uint32_t flags); @@ -335,17 +321,15 @@ private: // protected by mStateLock (but we could use another lock) Tokenizer mTokens; DefaultKeyedVector<ClientID, Client*> mClientsMap; - DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap; + DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap; GraphicPlane mGraphicPlanes[1]; - SortedVector<LayerBase*> mRemovedLayers; + bool mLayersRemoved; Vector<Client*> mDisconnectedClients; // constant members (no synchronization needed for access) sp<MemoryDealer> mServerHeap; sp<IMemory> mServerCblkMemory; surface_flinger_cblk_t* mServerCblk; - sp<SurfaceHeapManager> mSurfaceHeapManager; - sp<GPUHardwareInterface> mGPU; GLuint mWormholeTexName; sp<BootAnimation> mBootAnimation; nsecs_t mBootTime; diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp index ef51d6a..be3a239 100644 --- a/libs/surfaceflinger/Tokenizer.cpp +++ b/libs/surfaceflinger/Tokenizer.cpp @@ -162,9 +162,10 @@ void Tokenizer::dump() const { const run_t* ranges = mRanges.array(); const size_t c = mRanges.size(); - printf("Tokenizer (%p, size = %lu)\n", this, c); + printf("Tokenizer (%p, size = %d)\n", this, int(c)); for (size_t i=0 ; i<c ; i++) { - printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length); + printf("%u: (%u, %u)\n", i, + uint32_t(ranges[i].first), uint32_t(ranges[i].length)); } } diff --git a/libs/surfaceflinger/purgatory/VRamHeap.cpp b/libs/surfaceflinger/purgatory/VRamHeap.cpp new file mode 100644 index 0000000..f3ed790 --- /dev/null +++ b/libs/surfaceflinger/purgatory/VRamHeap.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2008 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 <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include <utils/MemoryDealer.h> +#include <utils/MemoryBase.h> +#include <utils/MemoryHeapPmem.h> +#include <utils/MemoryHeapBase.h> + +#include "GPUHardware/GPUHardware.h" +#include "SurfaceFlinger.h" +#include "VRamHeap.h" + +#if HAVE_ANDROID_OS +#include <linux/android_pmem.h> +#endif + + +namespace android { + +// --------------------------------------------------------------------------- + +/* + * Amount of memory we reserve for surface, per client in PMEM + * (PMEM is used for 2D acceleration) + * 8 MB of address space per client should be enough. + */ +static const int PMEM_SIZE = int(8 * 1024 * 1024); + +int SurfaceHeapManager::global_pmem_heap = 0; + +// --------------------------------------------------------------------------- + +SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, + size_t clientHeapSize) + : mFlinger(flinger), mClientHeapSize(clientHeapSize) +{ + SurfaceHeapManager::global_pmem_heap = 1; +} + +SurfaceHeapManager::~SurfaceHeapManager() +{ +} + +void SurfaceHeapManager::onFirstRef() +{ + if (global_pmem_heap) { + const char* device = "/dev/pmem"; + mPMemHeap = new PMemHeap(device, PMEM_SIZE); + if (mPMemHeap->base() == MAP_FAILED) { + mPMemHeap.clear(); + global_pmem_heap = 0; + } + } +} + +sp<MemoryDealer> SurfaceHeapManager::createHeap( + uint32_t flags, + pid_t client_pid, + const sp<MemoryDealer>& defaultAllocator) +{ + sp<MemoryDealer> dealer; + + if (flags & ISurfaceComposer::eGPU) { + // don't grant GPU memory if GPU is disabled + char value[PROPERTY_VALUE_MAX]; + property_get("debug.egl.hw", value, "1"); + if (atoi(value) == 0) { + flags &= ~ISurfaceComposer::eGPU; + } + } + + if (flags & ISurfaceComposer::eGPU) { + // FIXME: this is msm7201A specific, where gpu surfaces may not be secure + if (!(flags & ISurfaceComposer::eSecure)) { + // if GPU doesn't work, we try eHardware + flags |= ISurfaceComposer::eHardware; + // asked for GPU memory, try that first + dealer = mFlinger->getGPU()->request(client_pid); + } + } + + if (dealer == NULL) { + if (defaultAllocator != NULL) + // if a default allocator is given, use that + dealer = defaultAllocator; + } + + if (dealer == NULL) { + // always try h/w accelerated memory first + if (global_pmem_heap) { + const sp<PMemHeap>& heap(mPMemHeap); + if (dealer == NULL && heap != NULL) { + dealer = new MemoryDealer( + heap->createClientHeap(), + heap->getAllocator()); + } + } + } + + if (dealer == NULL) { + // return the ashmem allocator (software rendering) + dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap"); + } + return dealer; +} + +sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const +{ + Mutex::Autolock _l(mLock); + sp<SimpleBestFitAllocator> allocator; + + // this is only used for debugging + switch (type) { + case NATIVE_MEMORY_TYPE_PMEM: + if (mPMemHeap != 0) { + allocator = mPMemHeap->getAllocator(); + } + break; + } + return allocator; +} + +// --------------------------------------------------------------------------- + +PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved) + : MemoryHeapBase(device, size) +{ + //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); + if (base() != MAP_FAILED) { + //LOGD("%s, %u bytes", device, virtualSize()); + if (reserved == 0) + reserved = virtualSize(); + mAllocator = new SimpleBestFitAllocator(reserved); + } +} + +PMemHeap::~PMemHeap() { + //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); +} + +sp<MemoryHeapPmem> PMemHeap::createClientHeap() { + sp<MemoryHeapBase> parentHeap(this); + return new MemoryHeapPmem(parentHeap); +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/surfaceflinger/purgatory/VRamHeap.h b/libs/surfaceflinger/purgatory/VRamHeap.h new file mode 100644 index 0000000..9140167 --- /dev/null +++ b/libs/surfaceflinger/purgatory/VRamHeap.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 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_VRAM_HEAP_H +#define ANDROID_VRAM_HEAP_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/MemoryDealer.h> + +namespace android { + +// --------------------------------------------------------------------------- + +class PMemHeap; +class MemoryHeapPmem; +class SurfaceFlinger; + +// --------------------------------------------------------------------------- + +class SurfaceHeapManager : public RefBase +{ +public: + SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize); + virtual ~SurfaceHeapManager(); + virtual void onFirstRef(); + /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */ + sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0, + const sp<MemoryDealer>& defaultAllocator = 0); + + // used for debugging only... + sp<SimpleBestFitAllocator> getAllocator(int type) const; + +private: + sp<PMemHeap> getHeap(int type) const; + + sp<SurfaceFlinger> mFlinger; + mutable Mutex mLock; + size_t mClientHeapSize; + sp<PMemHeap> mPMemHeap; + static int global_pmem_heap; +}; + +// --------------------------------------------------------------------------- + +class PMemHeap : public MemoryHeapBase +{ +public: + PMemHeap(const char* const vram, + size_t size=0, size_t reserved=0); + virtual ~PMemHeap(); + + virtual const sp<SimpleBestFitAllocator>& getAllocator() const { + return mAllocator; + } + virtual sp<MemoryHeapPmem> createClientHeap(); + +private: + sp<SimpleBestFitAllocator> mAllocator; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_VRAM_HEAP_H diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/libs/surfaceflinger/tests/resize/Android.mk new file mode 100644 index 0000000..ef1532f --- /dev/null +++ b/libs/surfaceflinger/tests/resize/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + resize.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libui + +LOCAL_MODULE:= test-resize + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/libs/surfaceflinger/tests/resize/resize.cpp new file mode 100644 index 0000000..21c6ab6 --- /dev/null +++ b/libs/surfaceflinger/tests/resize/resize.cpp @@ -0,0 +1,60 @@ +#include <cutils/memory.h> + +#include <utils/IPCThreadState.h> +#include <utils/ProcessState.h> +#include <utils/IServiceManager.h> +#include <utils/Log.h> + +#include <ui/Surface.h> +#include <ui/ISurface.h> +#include <ui/Overlay.h> +#include <ui/SurfaceComposerClient.h> + +using namespace android; + +namespace android { +class Test { +public: + static const sp<ISurface>& getISurface(const sp<Surface>& s) { + return s->getISurface(); + } +}; +}; + +int main(int argc, char** argv) +{ + // set up the thread-pool + sp<ProcessState> proc(ProcessState::self()); + ProcessState::self()->startThreadPool(); + + // create a client to surfaceflinger + sp<SurfaceComposerClient> client = new SurfaceComposerClient(); + + // create pushbuffer surface + sp<Surface> surface = client->createSurface(getpid(), 0, 160, 240, + PIXEL_FORMAT_RGB_565); + + + client->openTransaction(); + surface->setLayer(100000); + client->closeTransaction(); + + Surface::SurfaceInfo info; + surface->lock(&info); + ssize_t bpr = info.s * bytesPerPixel(info.format); + android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h); + surface->unlockAndPost(); + + surface->lock(&info); + android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h); + surface->unlockAndPost(); + + client->openTransaction(); + surface->setSize(320, 240); + client->closeTransaction(); + + + IPCThreadState::self()->joinThreadPool(); + + return 0; +} diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index f944357..577dd4b 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -2,9 +2,9 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ + BufferMapper.cpp \ Camera.cpp \ CameraParameters.cpp \ - EGLDisplaySurface.cpp \ EGLNativeWindowSurface.cpp \ EventHub.cpp \ EventRecurrence.cpp \ diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp new file mode 100644 index 0000000..a97188e --- /dev/null +++ b/libs/ui/BufferMapper.cpp @@ -0,0 +1,83 @@ +/* + * 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 "BufferMapper" + +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <utils/Errors.h> +#include <utils/threads.h> +#include <utils/Log.h> + +#include <ui/BufferMapper.h> +#include <ui/Rect.h> + +#include <EGL/android_natives.h> + +#include <hardware/gralloc.h> + +namespace android { +// --------------------------------------------------------------------------- + +BufferMapper::BufferMapper() + : mAllocMod(0) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + if (err == 0) { + mAllocMod = (gralloc_module_t const *)module; + } +} + +status_t BufferMapper::map(buffer_handle_t handle, void** addr) +{ + Mutex::Autolock _l(mLock); + status_t err = mAllocMod->map(mAllocMod, handle, addr); + LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +status_t BufferMapper::unmap(buffer_handle_t handle) +{ + Mutex::Autolock _l(mLock); + status_t err = mAllocMod->unmap(mAllocMod, handle); + LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +status_t BufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds) +{ + status_t err = mAllocMod->lock(mAllocMod, handle, usage, + bounds.left, bounds.top, bounds.width(), bounds.height()); + LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +status_t BufferMapper::unlock(buffer_handle_t handle) +{ + status_t err = mAllocMod->unlock(mAllocMod, handle); + LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp deleted file mode 100644 index d06c98b..0000000 --- a/libs/ui/EGLDisplaySurface.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/* - ** - ** Copyright 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 "EGLDisplaySurface" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/mman.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> -#include <cutils/properties.h> - -#include <hardware/copybit.h> - -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/EGLDisplaySurface.h> - -#if HAVE_ANDROID_OS -#include <linux/msm_mdp.h> -#endif - -#include <EGL/egl.h> - -#include <pixelflinger/format.h> - - -// ---------------------------------------------------------------------------- - -egl_native_window_t* android_createDisplaySurface() -{ - egl_native_window_t* s = new android::EGLDisplaySurface(); - s->memory_type = NATIVE_MEMORY_TYPE_GPU; - return s; -} - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -EGLDisplaySurface::EGLDisplaySurface() - : EGLNativeSurface<EGLDisplaySurface>() -{ - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef; - egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers; - egl_native_window_t::connect = 0; - egl_native_window_t::disconnect = 0; - - mFb[0].data = 0; - mFb[1].data = 0; - mBlitEngine = 0; - egl_native_window_t::fd = mapFrameBuffer(); - if (egl_native_window_t::fd >= 0) { - - hw_module_t const* module; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - const float in2mm = 25.4f; - float refreshRate = 1000000000000000LLU / ( - float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres ) - * ( mInfo.left_margin + mInfo.right_margin + mInfo.xres ) - * mInfo.pixclock); - - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::width = buffer.width; - egl_native_window_t::height = buffer.height; - egl_native_window_t::stride = buffer.stride; - egl_native_window_t::format = buffer.format; - egl_native_window_t::base = intptr_t(mFb[0].data); - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - egl_native_window_t::flags = 0; - egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width; - egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height; - egl_native_window_t::fps = refreshRate; - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB; - // no error, set the magic word - egl_native_window_t::magic = 0x600913; - } - mSwapCount = -1; - mPageFlipCount = 0; -} - -EGLDisplaySurface::~EGLDisplaySurface() -{ - magic = 0; - copybit_close(mBlitEngine); - mBlitEngine = 0; - close(egl_native_window_t::fd); - munmap(mFb[0].data, mSize); - if (!(mFlags & PAGE_FLIP)) - free((void*)mFb[1].data); -} - -void EGLDisplaySurface::hook_incRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->incStrong(that); -} -void EGLDisplaySurface::hook_decRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->decStrong(that); -} -uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->swapBuffers(); -} - -void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h) -{ - mInfo.reserved[0] = 0x54445055; // "UPDT"; - mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); - mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); -} - -uint32_t EGLDisplaySurface::swapBuffers() -{ -#define SHOW_FPS 0 -#if SHOW_FPS - nsecs_t now = systemTime(); - if (mSwapCount == -1) { - mTime = now; - mSwapCount = 0; - mSleep = 0; - } else { - nsecs_t d = now-mTime; - if (d >= seconds(1)) { - double fps = (mSwapCount * double(seconds(1))) / double(d); - LOGD("%f fps, sleep=%d / frame", - fps, (int)ns2us(mSleep / mSwapCount)); - mSwapCount = 0; - mTime = now; - mSleep = 0; - } else { - mSwapCount++; - } - } -#endif - /* If we can't do the page_flip, just copy the back buffer to the front */ - if (!(mFlags & PAGE_FLIP)) { - memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2); - return 0; - } - - // do the actual flip - mIndex = 1 - mIndex; - mInfo.activate = FB_ACTIVATE_VBL; - mInfo.yoffset = mIndex ? mInfo.yres : 0; - if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) { - LOGE("FBIOPUT_VSCREENINFO failed"); - return 0; - } - - /* - * this is a monstrous hack: Because the h/w accelerator is not able - * to render directly into the framebuffer, we need to copy its - * internal framebuffer out to the fb. - * oem[0] is used to access the fd of internal fb. - * All this is needed only in standalone mode, in SurfaceFlinger mode - * we control where the GPU renders. - * We do this only if we have copybit, since this hack is needed only - * with msm7k. - */ - if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) { - copybit_device_t *copybit = mBlitEngine; - copybit_rect_t sdrect = { 0, 0, - egl_native_window_t::width, egl_native_window_t::height }; - copybit_image_t dst = { - egl_native_window_t::width, - egl_native_window_t::height, - egl_native_window_t::format, - egl_native_window_t::offset, - (void*)egl_native_window_t::base, - egl_native_window_t::fd - }; - copybit_image_t src = { - egl_native_window_t::width, - egl_native_window_t::height, - egl_native_window_t::format, // XXX: use proper format - egl_native_window_t::offset, - (void*)egl_native_window_t::base, // XXX: use proper base - egl_native_window_t::oem[0] - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it); - } - - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - -#if SHOW_FPS - mSleep += systemTime()-now; -#endif - - mPageFlipCount++; - - // We don't support screen-size changes for now - return 0; -} - -int32_t EGLDisplaySurface::getPageFlipCount() const -{ - return mPageFlipCount; -} - -void EGLDisplaySurface::copyFrontToBack(const Region& copyback) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t dst = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[1-mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(copyback); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - /* no extra copy needed since we copied back to front instead of - * flipping */ - if (!(mFlags & PAGE_FLIP)) { - return; - } - - Region::iterator iterator(copyback); - if (iterator) { - Rect r; - uint8_t* const screen_src = mFb[ mIndex].data; - uint8_t* const screen_dst = mFb[1-mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp; - uint8_t* s = screen_src + o; - uint8_t* d = screen_dst + o; - if (size == bpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += bpr; - s += bpr; - } while (--h > 0); - } - } - } - } -} - -void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - uint8_t* const screen_src = mFb[ mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - memcpy((char*)dst.base + dst.offset, screen_src, - bpr*egl_native_window_t::height); - } -} - -void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[1-mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - uint8_t* const screen_src = mFb[1-mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - memcpy((char*)dst.base + dst.offset, screen_src, - bpr*egl_native_window_t::height); - } -} - - -status_t EGLDisplaySurface::mapFrameBuffer() -{ - char const * const device_template[] = { - "/dev/graphics/fb%u", - "/dev/fb%u", - 0 }; - int fd = -1; - int i=0; - char name[64]; - while ((fd==-1) && device_template[i]) { - snprintf(name, 64, device_template[i], 0); - fd = open(name, O_RDWR, 0); - i++; - } - if (fd < 0) - return -errno; - - struct fb_fix_screeninfo finfo; - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - struct fb_var_screeninfo info; - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - info.reserved[0] = 0; - info.reserved[1] = 0; - info.reserved[2] = 0; - info.xoffset = 0; - info.yoffset = 0; - info.yres_virtual = info.yres * 2; - info.bits_per_pixel = 16; - /* Explicitly request 5/6/5 */ - info.red.offset = 11; - info.red.length = 5; - info.green.offset = 5; - info.green.length = 6; - info.blue.offset = 0; - info.blue.length = 5; - info.transp.offset = 0; - info.transp.length = 0; - info.activate = FB_ACTIVATE_NOW; - - uint32_t flags = PAGE_FLIP; - if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); - } - - if (info.yres_virtual < info.yres * 2) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", - info.yres_virtual, info.yres*2); - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - int refreshRate = 1000000000000000LLU / - ( - uint64_t( info.upper_margin + info.lower_margin + info.yres ) - * ( info.left_margin + info.right_margin + info.xres ) - * info.pixclock - ); - - if (refreshRate == 0) { - // bleagh, bad info from the driver - refreshRate = 60*1000; // 60 Hz - } - if (int(info.width) <= 0 || int(info.height) <= 0) { - // the driver doesn't return that information - // default to 160 dpi - info.width = ((info.xres * 25.4f)/160.0f + 0.5f); - info.height = ((info.yres * 25.4f)/160.0f + 0.5f); - } - - float xdpi = (info.xres * 25.4f) / info.width; - float ydpi = (info.yres * 25.4f) / info.height; - float fps = refreshRate / 1000.0f; - - LOGI( "using (fd=%d)\n" - "id = %s\n" - "xres = %d px\n" - "yres = %d px\n" - "xres_virtual = %d px\n" - "yres_virtual = %d px\n" - "bpp = %d\n" - "r = %2u:%u\n" - "g = %2u:%u\n" - "b = %2u:%u\n", - fd, - finfo.id, - info.xres, - info.yres, - info.xres_virtual, - info.yres_virtual, - info.bits_per_pixel, - info.red.offset, info.red.length, - info.green.offset, info.green.length, - info.blue.offset, info.blue.length - ); - - LOGI( "width = %d mm (%f dpi)\n" - "height = %d mm (%f dpi)\n" - "refresh rate = %.2f Hz\n", - info.width, xdpi, - info.height, ydpi, - fps - ); - - - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - if (finfo.smem_len <= 0) - return -errno; - - /* - * Open and map the display. - */ - - void* buffer = (uint16_t*) mmap( - 0, finfo.smem_len, - PROT_READ | PROT_WRITE, - MAP_SHARED, - fd, 0); - - if (buffer == MAP_FAILED) - return -errno; - - // at least for now, always clear the fb - memset(buffer, 0, finfo.smem_len); - - uint8_t* offscreen[2]; - offscreen[0] = (uint8_t*)buffer; - if (flags & PAGE_FLIP) { - offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres; - } else { - offscreen[1] = (uint8_t*)malloc(finfo.smem_len); - if (offscreen[1] == 0) { - munmap(buffer, finfo.smem_len); - return NO_MEMORY; - } - } - - mFlags = flags; - mInfo = info; - mFinfo = finfo; - mSize = finfo.smem_len; - mIndex = 0; - for (int i=0 ; i<2 ; i++) { - mFb[i].version = sizeof(GGLSurface); - mFb[i].width = info.xres; - mFb[i].height = info.yres; - mFb[i].stride = finfo.line_length / (info.bits_per_pixel >> 3); - mFb[i].data = (GGLubyte*)(offscreen[i]); - mFb[i].format = GGL_PIXEL_FORMAT_RGB_565; - } - return fd; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp index f1071cf..5d9d6a4 100644 --- a/libs/ui/EGLNativeWindowSurface.cpp +++ b/libs/ui/EGLNativeWindowSurface.cpp @@ -20,142 +20,225 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <errno.h> #include <cutils/log.h> #include <cutils/atomic.h> +#include <utils/threads.h> #include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> #include <ui/Rect.h> +#include <ui/EGLNativeWindowSurface.h> #include <EGL/egl.h> #include <pixelflinger/format.h> +#include <pixelflinger/pixelflinger.h> -#include <ui/EGLNativeWindowSurface.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- -EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface) - : EGLNativeSurface<EGLNativeWindowSurface>(), - mSurface(surface), mConnected(false) +/* + * This implements the (main) framebuffer management. This class is used + * mostly by SurfaceFlinger, but also by command line GL application. + * + * In fact this is an implementation of android_native_window_t on top of + * the framebuffer. + * + * Currently it is pretty simple, it manages only two buffers (the front and + * back buffer). + * + */ + +FramebufferNativeWindow::FramebufferNativeWindow() + : BASE(), fbDev(0), grDev(0) { - egl_native_window_t::magic = 0x600913; - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef; - egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers; - egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect; - egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect; + hw_module_t const* module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + int stride; + framebuffer_open(module, &fbDev); + gralloc_open(module, &grDev); + int err; + + + // initialize the buffer FIFO + mNumBuffers = 2; + mNumFreeBuffers = 2; + mBufferHead = mNumBuffers-1; + buffers[0] = new NativeBuffer( + fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + buffers[1] = new NativeBuffer( + fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + + err = grDev->alloc(grDev, + fbDev->width, fbDev->height, fbDev->format, + GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); + + LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", + fbDev->width, fbDev->height, strerror(-err)); + + err = grDev->alloc(grDev, + fbDev->width, fbDev->height, fbDev->format, + GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); + + LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", + fbDev->width, fbDev->height, strerror(-err)); + + gralloc_module_t* m = + reinterpret_cast<gralloc_module_t*>(grDev->common.module); + + // FIXME: do we actually need to map the framebuffer? + m->map(m, buffers[0]->handle, &buffers[0]->bits); + m->map(m, buffers[1]->handle, &buffers[1]->bits); + } + + uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED; + + /* + * FIXME: SURFACE_FLAG_PRESERVE_CONTENT + * how to implement this, there is no concept of preserve content in + * the framebuffer, which just "posts" buffer. + * + * It looks like what we need is a way to know if the posted buffer can + * be reused. But if so, why allocating 2 buffers?... + * + * should the lock/unlock calls take care of the copy-back? + * + * + * In the end, the client wants to know if the backbuffer is preserved + * though... it's complicated. + * + */ + + //flags |= SURFACE_FLAG_PRESERVE_CONTENT; - DisplayInfo dinfo; - SurfaceComposerClient::getDisplayInfo(0, &dinfo); - egl_native_window_t::xdpi = dinfo.xdpi; - egl_native_window_t::ydpi = dinfo.ydpi; - egl_native_window_t::fps = dinfo.fps; - egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER; -} -EGLNativeWindowSurface::~EGLNativeWindowSurface() -{ - disconnect(); - mSurface.clear(); - magic = 0; + const_cast<uint32_t&>(android_native_window_t::flags) = flags; + const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi; + const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi; + const_cast<int&>(android_native_window_t::minSwapInterval) = + fbDev->minSwapInterval; + const_cast<int&>(android_native_window_t::maxSwapInterval) = + fbDev->maxSwapInterval; + + android_native_window_t::connect = connect; + android_native_window_t::disconnect = disconnect; + android_native_window_t::setSwapInterval = setSwapInterval; + android_native_window_t::setSwapRectangle = setSwapRectangle; + android_native_window_t::dequeueBuffer = dequeueBuffer; + android_native_window_t::lockBuffer = lockBuffer; + android_native_window_t::queueBuffer = queueBuffer; } -void EGLNativeWindowSurface::hook_incRef(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->incStrong(that); +FramebufferNativeWindow::~FramebufferNativeWindow() { + grDev->free(grDev, buffers[0]->handle); + grDev->free(grDev, buffers[1]->handle); + gralloc_module_t* m = + reinterpret_cast<gralloc_module_t*>(grDev->common.module); + m->unmap(m, buffers[0]->handle); + m->unmap(m, buffers[1]->handle); + gralloc_close(grDev); + framebuffer_close(fbDev); } -void EGLNativeWindowSurface::hook_decRef(NativeWindowType window) +void FramebufferNativeWindow::connect(android_native_window_t* window) { - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->decStrong(that); } -void EGLNativeWindowSurface::hook_connect(NativeWindowType window) +void FramebufferNativeWindow::disconnect(android_native_window_t* window) { - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->connect(); } -void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window) +int FramebufferNativeWindow::setSwapInterval( + android_native_window_t* window, int interval) { - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->disconnect(); + framebuffer_device_t* fb = getSelf(window)->fbDev; + return fb->setSwapInterval(fb, interval); } -uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window) +int FramebufferNativeWindow::setSwapRectangle(android_native_window_t* window, + int l, int t, int w, int h) { - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - return that->swapBuffers(); + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + self->mDirty = Rect(l, t, l+w, t+h); + return 0; } -void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h) +int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, + android_native_buffer_t** buffer) { - mSurface->setSwapRectangle(Rect(l, t, l+w, t+h)); -} + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; -uint32_t EGLNativeWindowSurface::swapBuffers() -{ - const int w = egl_native_window_t::width; - const int h = egl_native_window_t::height; - const sp<Surface>& surface(mSurface); - Surface::SurfaceInfo info; - surface->unlockAndPost(); - surface->lock(&info); - // update the address of the buffer to draw to next - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - - // update size if it changed - if (w != int(info.w) || h != int(info.h)) { - egl_native_window_t::width = info.w; - egl_native_window_t::height = info.h; - egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format); - egl_native_window_t::format = info.format; - return EGL_NATIVES_FLAG_SIZE_CHANGED; + // wait for a free buffer + while (!self->mNumFreeBuffers) { + self->mCondition.wait(self->mutex); } + // get this buffer + self->mNumFreeBuffers--; + int index = self->mBufferHead++; + if (self->mBufferHead >= self->mNumBuffers) + self->mBufferHead = 0; + + *buffer = self->buffers[index].get(); + return 0; } -void EGLNativeWindowSurface::connect() -{ - if (!mConnected) { - Surface::SurfaceInfo info; - mSurface->lock(&info); - mSurface->setSwapRectangle(Rect(info.w, info.h)); - mConnected = true; - - egl_native_window_t::width = info.w; - egl_native_window_t::height = info.h; - egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format); - egl_native_window_t::format = info.format; - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - // FIXME: egl_native_window_t::memory_type used to be set from - // mSurface, but we wanted to break this dependency. We set it to - // GPU because the software rendered doesn't care, but the h/w - // accelerator needs it. Eventually, this value should go away - // completely, since memory will be managed by OpenGL. - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; - egl_native_window_t::fd = 0; +int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + + // wait that the buffer we're locking is not front anymore + while (self->front == buffer) { + self->mCondition.wait(self->mutex); } + + gralloc_module_t* m = + reinterpret_cast<gralloc_module_t*>(self->grDev->common.module); + const Rect& dirty(self->mDirty); + + buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; + int res = m->lock(m, handle, GRALLOC_USAGE_HW_FB, + dirty.left, dirty.right, dirty.width(), dirty.height()); + + return res; } -void EGLNativeWindowSurface::disconnect() +int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) { - if (mConnected) { - mSurface->unlock(); - mConnected = false; - } + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; + gralloc_module_t* m = + reinterpret_cast<gralloc_module_t*>(self->grDev->common.module); + + buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; + m->unlock(m, handle); + int res = fb->post(fb, handle); + + self->front = static_cast<NativeBuffer*>(buffer); + self->mNumFreeBuffers++; + self->mCondition.broadcast(); + return res; } // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- + + +EGLNativeWindowType android_createDisplaySurface(void) +{ + return new android::FramebufferNativeWindow(); +} + diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index d5e9f81..fcea8ec 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "ISurface" + #include <stdio.h> #include <stdint.h> #include <sys/types.h> @@ -23,10 +25,13 @@ #include <ui/ISurface.h> #include <ui/Overlay.h> +#include <ui/Surface.h> namespace android { +// ---------------------------------------------------------------------- + ISurface::BufferHeap::BufferHeap() : w(0), h(0), hor_stride(0), ver_stride(0), format(0), transform(0), flags(0) @@ -55,6 +60,8 @@ ISurface::BufferHeap::~BufferHeap() { } +// ---------------------------------------------------------------------- + class BpSurface : public BpInterface<ISurface> { public: @@ -63,6 +70,15 @@ public: { } + virtual sp<SurfaceBuffer> getBuffer() + { + Parcel data, reply; + data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); + remote()->transact(GET_BUFFER, data, &reply); + sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply); + return buffer; + } + virtual status_t registerBuffers(const BufferHeap& buffers) { Parcel data, reply; @@ -122,6 +138,11 @@ status_t BnSurface::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { + case GET_BUFFER: { + CHECK_INTERFACE(ISurface, data, reply); + sp<SurfaceBuffer> buffer(getBuffer()); + return SurfaceBuffer::writeToParcel(reply, buffer.get()); + } case REGISTER_BUFFERS: { CHECK_INTERFACE(ISurface, data, reply); BufferHeap buffer; diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp index 76597e1..1932bf9 100644 --- a/libs/ui/ISurfaceComposer.cpp +++ b/libs/ui/ISurfaceComposer.cpp @@ -114,36 +114,6 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t requestGPU( - const sp<IGPUCallback>& callback, gpu_info_t* gpu) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(callback->asBinder()); - remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply); - gpu->regs = interface_cast<IMemory>(reply.readStrongBinder()); - gpu->count = reply.readInt32(); - - // FIXME: for now, we don't dynamically allocate the regions array - size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions); - if (gpu->count > maxCount) - return BAD_VALUE; - - for (size_t i=0 ; i<gpu->count ; i++) { - gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder()); - gpu->regions[i].reserved = reply.readInt32(); - } - return reply.readInt32(); - } - - virtual status_t revokeGPU() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply); - return reply.readInt32(); - } - virtual void signal() const { Parcel data, reply; @@ -201,9 +171,6 @@ status_t BnSurfaceComposer::onTransact( case BOOT_FINISHED: { bootFinished(); } break; - case REVOKE_GPU: { - reply->writeInt32( revokeGPU() ); - } break; case SIGNAL: { signal(); } break; @@ -211,26 +178,6 @@ status_t BnSurfaceComposer::onTransact( sp<IBinder> b = getCblk()->asBinder(); reply->writeStrongBinder(b); } break; - case REQUEST_GPU: { - // TODO: this should be protected by a permission - gpu_info_t info; - sp<IGPUCallback> callback - = interface_cast<IGPUCallback>(data.readStrongBinder()); - status_t res = requestGPU(callback, &info); - - // FIXME: for now, we don't dynamically allocate the regions array - size_t maxCount = sizeof(info.regions)/sizeof(*info.regions); - if (info.count > maxCount) - return BAD_VALUE; - - reply->writeStrongBinder(info.regs->asBinder()); - reply->writeInt32(info.count); - for (size_t i=0 ; i<info.count ; i++) { - reply->writeStrongBinder(info.regions[i].region->asBinder()); - reply->writeInt32(info.regions[i].reserved); - } - reply->writeInt32(res); - } break; default: return UNKNOWN_TRANSACTION; } @@ -239,41 +186,4 @@ status_t BnSurfaceComposer::onTransact( // ---------------------------------------------------------------------------- -enum { - // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService. - GPU_LOST = IBinder::FIRST_CALL_TRANSACTION -}; - -class BpGPUCallback : public BpInterface<IGPUCallback> -{ -public: - BpGPUCallback(const sp<IBinder>& impl) - : BpInterface<IGPUCallback>(impl) - { - } - - virtual void gpuLost() - { - Parcel data, reply; - data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor()); - remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback"); - -status_t BnGPUCallback::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GPU_LOST: { - CHECK_INTERFACE(IGPUCallback, data, reply); - gpuLost(); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - }; diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp index dd6a798..597b87e 100644 --- a/libs/ui/ISurfaceFlingerClient.cpp +++ b/libs/ui/ISurfaceFlingerClient.cpp @@ -191,8 +191,6 @@ status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& par { token = parcel.readInt32(); identity = parcel.readInt32(); - heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder()); - heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder()); return NO_ERROR; } @@ -200,8 +198,6 @@ status_t ISurfaceFlingerClient::surface_data_t::writeToParcel(Parcel* parcel) co { parcel->writeInt32(token); parcel->writeInt32(identity); - parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); - parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); return NO_ERROR; } diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp index b236edc..59c6514 100644 --- a/libs/ui/Overlay.cpp +++ b/libs/ui/Overlay.cpp @@ -129,12 +129,8 @@ OverlayRef::OverlayRef(overlay_handle_t handle, const sp<IOverlay>& channel, OverlayRef::~OverlayRef() { if (mOwnHandle) { - /* FIXME: handles should be promoted to "real" API and be handled by - * the framework */ - for (int i=0 ; i<mOverlayHandle->numFds ; i++) { - close(mOverlayHandle->data[i]); - } - free((void*)mOverlayHandle); + native_handle_close(mOverlayHandle); + native_handle_delete(const_cast<native_handle*>(mOverlayHandle)); } } @@ -147,7 +143,7 @@ sp<OverlayRef> OverlayRef::readFromParcel(const Parcel& data) { uint32_t f = data.readInt32(); uint32_t ws = data.readInt32(); uint32_t hs = data.readInt32(); - native_handle* handle = data.readNativeHandle(NULL, NULL); + native_handle* handle = data.readNativeHandle(); result = new OverlayRef(); result->mOverlayHandle = handle; @@ -169,7 +165,7 @@ status_t OverlayRef::writeToParcel(Parcel* reply, const sp<OverlayRef>& o) { reply->writeInt32(o->mFormat); reply->writeInt32(o->mWidthStride); reply->writeInt32(o->mHeightStride); - reply->writeNativeHandle(*(o->mOverlayHandle)); + reply->writeNativeHandle(o->mOverlayHandle); } else { reply->writeStrongBinder(NULL); } diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 4ea9ae2..357e4d0 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -23,24 +23,126 @@ #include <sys/types.h> #include <sys/stat.h> -#include <utils/Atomic.h> #include <utils/Errors.h> #include <utils/threads.h> #include <utils/IPCThreadState.h> #include <utils/IMemory.h> #include <utils/Log.h> +#include <ui/DisplayInfo.h> +#include <ui/BufferMapper.h> +#include <ui/EGLNativeWindowSurface.h> #include <ui/ISurface.h> #include <ui/Surface.h> #include <ui/SurfaceComposerClient.h> #include <ui/Rect.h> +#include <EGL/android_natives.h> + #include <private/ui/SharedState.h> #include <private/ui/LayerState.h> +#include <pixelflinger/pixelflinger.h> + namespace android { -// --------------------------------------------------------------------------- +// ============================================================================ +// SurfaceBuffer +// ============================================================================ + +SurfaceBuffer::SurfaceBuffer() + : BASE(), handle(0), mOwner(false) +{ + width = + height = + stride = + format = + usage = 0; + android_native_buffer_t::getHandle = getHandle; +} + +SurfaceBuffer::SurfaceBuffer(const Parcel& data) + : BASE(), handle(0), mOwner(true) +{ + // we own the handle in this case + width = data.readInt32(); + height = data.readInt32(); + stride = data.readInt32(); + format = data.readInt32(); + usage = data.readInt32(); + handle = data.readNativeHandle(); + android_native_buffer_t::getHandle = getHandle; +} + +SurfaceBuffer::~SurfaceBuffer() +{ + if (handle && mOwner) { + native_handle_close(handle); + native_handle_delete(const_cast<native_handle*>(handle)); + } +} + +int SurfaceBuffer::getHandle(android_native_buffer_t const * base, + buffer_handle_t* handle) +{ + *handle = getSelf(base)->handle; + return 0; +} + +status_t SurfaceBuffer::writeToParcel(Parcel* reply, + android_native_buffer_t const* buffer) +{ + buffer_handle_t handle; + status_t err = buffer->getHandle(buffer, &handle); + if (err < 0) { + return err; + } + reply->writeInt32(buffer->width); + reply->writeInt32(buffer->height); + reply->writeInt32(buffer->stride); + reply->writeInt32(buffer->format); + reply->writeInt32(buffer->usage); + reply->writeNativeHandle(handle); + return NO_ERROR; +} + +// ---------------------------------------------------------------------- + +static void copyBlt(const android_native_buffer_t* dst, + const android_native_buffer_t* src, const Region& reg) +{ + Region::iterator iterator(reg); + if (iterator) { + // NOTE: dst and src must be the same format + Rect r; + const size_t bpp = bytesPerPixel(src->format); + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + while (iterator.iterate(&r)) { + ssize_t h = r.bottom - r.top; + if (h) { + size_t size = (r.right - r.left) * bpp; + uint8_t* s = (GGLubyte*)src->bits + + (r.left + src->stride * r.top) * bpp; + uint8_t* d = (GGLubyte*)dst->bits + + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; + } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); + } + } + } +} + +// ============================================================================ +// Surface +// ============================================================================ Surface::Surface(const sp<SurfaceComposerClient>& client, const sp<ISurface>& surface, @@ -51,26 +153,44 @@ Surface::Surface(const sp<SurfaceComposerClient>& client, mToken(data.token), mIdentity(data.identity), mFormat(format), mFlags(flags), mOwner(owner) { + android_native_window_t::connect = connect; + android_native_window_t::disconnect = disconnect; + android_native_window_t::setSwapInterval = setSwapInterval; + android_native_window_t::setSwapRectangle = setSwapRectangle; + android_native_window_t::dequeueBuffer = dequeueBuffer; + android_native_window_t::lockBuffer = lockBuffer; + android_native_window_t::queueBuffer = queueBuffer; + mSwapRectangle.makeInvalid(); - mSurfaceHeapBase[0] = 0; - mSurfaceHeapBase[1] = 0; - mHeap[0] = data.heap[0]; - mHeap[1] = data.heap[1]; + + DisplayInfo dinfo; + SurfaceComposerClient::getDisplayInfo(0, &dinfo); + const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi; + const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi; + // FIXME: set real values here + const_cast<int&>(android_native_window_t::minSwapInterval) = 1; + const_cast<int&>(android_native_window_t::maxSwapInterval) = 1; + const_cast<uint32_t&>(android_native_window_t::flags) = 0; } Surface::Surface(Surface const* rhs) : mOwner(false) { - mToken = rhs->mToken; - mIdentity= rhs->mIdentity; - mClient = rhs->mClient; - mSurface = rhs->mSurface; - mHeap[0] = rhs->mHeap[0]; - mHeap[1] = rhs->mHeap[1]; - mFormat = rhs->mFormat; - mFlags = rhs->mFlags; - mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0]; - mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1]; + // FIXME: we really should get rid of this ctor. the memcpy below + //should be safe for now, but android_native_window_t is not supposed + // to be clonable. + memcpy( static_cast<android_native_window_t*>(this), + static_cast<android_native_window_t const *>(rhs), + sizeof(android_native_window_t)); + + mToken = rhs->mToken; + mIdentity = rhs->mIdentity; + mClient = rhs->mClient; + mSurface = rhs->mSurface; + mBuffers[0] = rhs->mBuffers[0]; + mBuffers[1] = rhs->mBuffers[1]; + mFormat = rhs->mFormat; + mFlags = rhs->mFlags; mSwapRectangle.makeInvalid(); } @@ -78,21 +198,26 @@ Surface::~Surface() { if (mOwner && mToken>=0 && mClient!=0) { mClient->destroySurface(mToken); + if (mBuffers[0] != 0) { + BufferMapper::get().unmap(mBuffers[0]->getHandle()); + } + if (mBuffers[1] != 0) { + BufferMapper::get().unmap(mBuffers[1]->getHandle()); + } } mClient.clear(); mSurface.clear(); - mHeap[0].clear(); - mHeap[1].clear(); IPCThreadState::self()->flushCommands(); } sp<Surface> Surface::dup() const { + // FIXME: we should get rid of Surface::dup() Surface const * r = this; if (this && mOwner) { // the only reason we need to do this is because of Java's garbage // collector: because we're creating a copy of the Surface - // instead of a reference, we can garantee that when our last + // instead of a reference, we can guarantee that when our last // reference goes away, the real surface will be deleted. // Without this hack (the code is correct too), we'd have to // wait for a GC for the surface to go away. @@ -101,32 +226,245 @@ sp<Surface> Surface::dup() const return const_cast<Surface*>(r); } -status_t Surface::nextBuffer(SurfaceInfo* info) { - return mClient->nextBuffer(this, info); +status_t Surface::validate(per_client_cblk_t const* cblk) const +{ + if (cblk == 0) { + LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); + return NO_INIT; + } + status_t err = cblk->validate(mToken); + if (err != NO_ERROR) { + LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", + mToken, mIdentity, err, strerror(-err)); + return err; + } + if (mIdentity != uint32_t(cblk->layers[mToken].identity)) { + LOGE("using an invalid surface id=%d, identity=%u should be %d", + mToken, mIdentity, cblk->layers[mToken].identity); + return NO_INIT; + } + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +int Surface::setSwapRectangle(android_native_window_t* window, + int l, int t, int w, int h) +{ + Surface* self = getSelf(window); + self->setSwapRectangle(Rect(l, t, l+w, t+h)); + return 0; +} + +void Surface::connect(android_native_window_t* window) +{ +} + +void Surface::disconnect(android_native_window_t* window) +{ +} + +int Surface::setSwapInterval(android_native_window_t* window, int interval) +{ + return 0; +} + +int Surface::dequeueBuffer(android_native_window_t* window, + android_native_buffer_t** buffer) +{ + Surface* self = getSelf(window); + return self->dequeueBuffer(buffer); +} + +int Surface::lockBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + Surface* self = getSelf(window); + return self->lockBuffer(buffer); +} + +int Surface::queueBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + Surface* self = getSelf(window); + return self->queueBuffer(buffer); +} + +// ---------------------------------------------------------------------------- + +int Surface::dequeueBuffer(android_native_buffer_t** buffer) +{ + // FIXME: dequeueBuffer() needs proper implementation + + Mutex::Autolock _l(mSurfaceLock); + + per_client_cblk_t* const cblk = mClient->mControl; + status_t err = validate(cblk); + if (err != NO_ERROR) + return err; + + SurfaceID index(mToken); + + int32_t backIdx = cblk->lock_layer(size_t(index), + per_client_cblk_t::BLOCKING); + + if (backIdx < 0) + return status_t(backIdx); + + 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) { + getBufferLocked(backIdx); + } + + const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]); + *buffer = backBuffer.get(); + + return NO_ERROR; +} + +int Surface::lockBuffer(android_native_buffer_t* buffer) +{ + // FIXME: lockBuffer() needs proper implementation + return 0; } +int Surface::queueBuffer(android_native_buffer_t* buffer) +{ + Mutex::Autolock _l(mSurfaceLock); + + per_client_cblk_t* const cblk = mClient->mControl; + status_t err = validate(cblk); + if (err != NO_ERROR) + return err; + + // transmit the dirty region + const Region dirty(swapRectangle()); + SurfaceID index(mToken); + layer_cblk_t* const lcblk = &(cblk->layers[index]); + _send_dirty_region(lcblk, dirty); + + uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); + if (!(newstate & eNextFlipPending)) + mClient->signalServer(); + + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + status_t Surface::lock(SurfaceInfo* info, bool blocking) { return Surface::lock(info, NULL, blocking); } -status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->lockSurface(this, info, dirty, blocking); +status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking) +{ + // FIXME: needs some locking here + android_native_buffer_t* backBuffer; + status_t err = dequeueBuffer(&backBuffer); + if (err == NO_ERROR) { + err = lockBuffer(backBuffer); + if (err == NO_ERROR) { + backBuffer->common.incRef(&backBuffer->common); + mLockedBuffer = backBuffer; + other->w = backBuffer->width; + other->h = backBuffer->height; + other->s = backBuffer->stride; + other->usage = backBuffer->usage; + other->format = backBuffer->format; + other->bits = backBuffer->bits; + + // we handle copy-back here... + + const Rect bounds(backBuffer->width, backBuffer->height); + Region newDirtyRegion; + + per_client_cblk_t* const cblk = mClient->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) { + // content is meaningless in this case and the whole surface + // needs to be redrawn. + newDirtyRegion.set(bounds); + if (dirty) { + *dirty = newDirtyRegion; + } + } else + { + if (dirty) { + dirty->andSelf(Region(bounds)); + newDirtyRegion = *dirty; + } else { + newDirtyRegion.set(bounds); + } + Region copyback; + if (!(lcblk->flags & eNoCopyBack)) { + const Region previousDirtyRegion(dirtyRegion()); + copyback = previousDirtyRegion.subtract(newDirtyRegion); + } + const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]); + if (!copyback.isEmpty() && frontBuffer!=0) { + // copy front to back + copyBlt(backBuffer, frontBuffer.get(), copyback); + } + } + setDirtyRegion(newDirtyRegion); + + + Rect lockBounds(backBuffer->width, backBuffer->height); + if (dirty) { + lockBounds = dirty->bounds(); + } + buffer_handle_t handle; + backBuffer->getHandle(backBuffer, &handle); + status_t res = BufferMapper::get().lock(handle, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + lockBounds); + LOGW_IF(res, "failed locking buffer %d (%p)", + mBackbufferIndex, handle); + setSwapRectangle(lockBounds); + } + } + return err; } + +status_t Surface::unlockAndPost() +{ + // FIXME: needs some locking here + + if (mLockedBuffer == 0) + return BAD_VALUE; -status_t Surface::unlockAndPost() { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->unlockAndPostSurface(this); + buffer_handle_t handle; + mLockedBuffer->getHandle(mLockedBuffer, &handle); + status_t res = BufferMapper::get().unlock(handle); + LOGW_IF(res, "failed unlocking buffer %d (%p)", + mBackbufferIndex, handle); + + const Rect dirty(dirtyRegion().bounds()); + setSwapRectangle(dirty); + status_t err = queueBuffer(mLockedBuffer); + mLockedBuffer->common.decRef(&mLockedBuffer->common); + mLockedBuffer = 0; + return err; } -status_t Surface::unlock() { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->unlockSurface(this); +void Surface::_send_dirty_region( + layer_cblk_t* lcblk, const Region& dirty) +{ + const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift; + flat_region_t* flat_region = lcblk->region + index; + status_t err = dirty.write(flat_region, sizeof(flat_region_t)); + if (err < NO_ERROR) { + // region doesn't fit, use the bounds + const Region reg(dirty.bounds()); + reg.write(flat_region, sizeof(flat_region_t)); + } } + status_t Surface::setLayer(int32_t layer) { return mClient->setLayer(this, layer); } @@ -183,8 +521,6 @@ sp<Surface> Surface::readFromParcel(Parcel* parcel) ISurfaceFlingerClient::surface_data_t data; sp<IBinder> clientBinder= parcel->readStrongBinder(); sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder()); - data.heap[0] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); - data.heap[1] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); data.token = parcel->readInt32(); data.identity = parcel->readInt32(); PixelFormat format = parcel->readInt32(); @@ -204,21 +540,16 @@ status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel) uint32_t identity = 0; sp<SurfaceComposerClient> client; sp<ISurface> sur; - sp<IMemoryHeap> heap[2]; if (surface->isValid()) { token = surface->mToken; identity = surface->mIdentity; client = surface->mClient; sur = surface->mSurface; - heap[0] = surface->mHeap[0]; - heap[1] = surface->mHeap[1]; format = surface->mFormat; flags = surface->mFlags; } parcel->writeStrongBinder(client!=0 ? client->connection() : NULL); parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); - parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); - parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); parcel->writeInt32(token); parcel->writeInt32(identity); parcel->writeInt32(format); @@ -233,23 +564,24 @@ bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); } -void* Surface::heapBase(int i) const +status_t Surface::getBufferLocked(int index) { - void* heapBase = mSurfaceHeapBase[i]; - // map lazily so it doesn't get mapped in clients that don't need it - if (heapBase == 0) { - const sp<IMemoryHeap>& heap(mHeap[i]); - if (heap != 0) { - heapBase = static_cast<uint8_t*>(heap->base()); - if (heapBase == MAP_FAILED) { - heapBase = NULL; - LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)", - heap->asBinder().get(), heap.get()); - } - mSurfaceHeapBase[i] = heapBase; + status_t err = NO_MEMORY; + sp<SurfaceBuffer> buffer = mSurface->getBuffer(); + LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL"); + if (buffer != 0) { + sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); + if (currentBuffer != 0) { + BufferMapper::get().unmap(currentBuffer->getHandle()); + currentBuffer.clear(); + } + err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits); + LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); + if (err == NO_ERROR) { + currentBuffer = buffer; } } - return heapBase; + return err; } }; // namespace android diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp index fe803ff..e1b13c7 100644 --- a/libs/ui/SurfaceComposerClient.cpp +++ b/libs/ui/SurfaceComposerClient.cpp @@ -29,27 +29,21 @@ #include <utils/Errors.h> #include <utils/threads.h> #include <utils/KeyedVector.h> -#include <utils/IPCThreadState.h> #include <utils/IServiceManager.h> #include <utils/IMemory.h> #include <utils/Log.h> +#include <ui/DisplayInfo.h> #include <ui/ISurfaceComposer.h> #include <ui/ISurfaceFlingerClient.h> #include <ui/ISurface.h> #include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> #include <ui/Rect.h> -#include <ui/Point.h> #include <private/ui/SharedState.h> #include <private/ui/LayerState.h> #include <private/ui/SurfaceFlingerSynchro.h> -#include <pixelflinger/pixelflinger.h> - -#include <utils/BpBinder.h> - #define VERBOSE(...) ((void)0) //#define VERBOSE LOGD @@ -109,50 +103,8 @@ static volatile surface_flinger_cblk_t const * get_cblk() // --------------------------------------------------------------------------- -static void copyBlt(const GGLSurface& dst, - const GGLSurface& src, const Region& reg) -{ - Region::iterator iterator(reg); - if (iterator) { - // NOTE: dst and src must be the same format - Rect r; - const size_t bpp = bytesPerPixel(src.format); - const size_t dbpr = dst.stride * bpp; - const size_t sbpr = src.stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp; - uint8_t* d = dst.data + (r.left + dst.stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); - } - } - } -} - -// --------------------------------------------------------------------------- - -surface_flinger_cblk_t::surface_flinger_cblk_t() -{ -} - -// --------------------------------------------------------------------------- - -per_client_cblk_t::per_client_cblk_t() -{ -} - // these functions are used by the clients -inline status_t per_client_cblk_t::validate(size_t i) const { +status_t per_client_cblk_t::validate(size_t i) const { if (uint32_t(i) >= NUM_LAYERS_MAX) return BAD_INDEX; if (layers[i].swapState & eInvalidSurface) @@ -248,8 +200,9 @@ int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags) index = (state&eIndex) ^ ((state&eFlipRequested)>>1); // make sure this buffer is valid - if (layer->surface[index].bits_offset < 0) { - return status_t(layer->surface[index].bits_offset); + status_t err = layer->surface[index].status; + if (err < 0) { + return err; } if (inspect) { @@ -273,7 +226,7 @@ done: uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) { - // atomically set eFlipRequested and clear eLocked and optionnaly + // atomically set eFlipRequested and clear eLocked and optionally // set eNextFlipPending if eFlipRequested was already set layer_cblk_t * const layer = layers + i; @@ -290,7 +243,7 @@ uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) if (oldvalue & eFlipRequested) newvalue |= eNextFlipPending; - // if eFlipRequested was alread set, set eNextFlipPending + // if eFlipRequested was already set, set eNextFlipPending } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState))); @@ -298,9 +251,9 @@ uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift), int(newvalue)); - // from this point, the server can kick in at anytime and use the first + // from this point, the server can kick in at any time and use the first // buffer, so we cannot use it anymore, and we must use the 'other' - // buffer instead (or wait if it is not availlable yet, see lock_layer). + // buffer instead (or wait if it is not available yet, see lock_layer). return newvalue; } @@ -376,32 +329,6 @@ status_t SurfaceComposerClient::initCheck() const return mStatus; } -status_t SurfaceComposerClient::validateSurface( - per_client_cblk_t const* cblk, Surface const * surface) -{ - SurfaceID index = surface->ID(); - if (cblk == 0) { - LOGE("cblk is null (surface id=%d, identity=%u)", - index, surface->getIdentity()); - return NO_INIT; - } - - status_t err = cblk->validate(index); - if (err != NO_ERROR) { - LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", - index, surface->getIdentity(), err, strerror(-err)); - return err; - } - - if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) { - LOGE("using an invalid surface id=%d, identity=%u should be %d", - index, surface->getIdentity(), cblk->layers[index].identity); - return NO_INIT; - } - - return NO_ERROR; -} - sp<IBinder> SurfaceComposerClient::connection() const { return (mClient != 0) ? mClient->asBinder() : 0; @@ -439,7 +366,6 @@ void SurfaceComposerClient::dispose() sp<IMemory> controlMemory; sp<ISurfaceFlingerClient> client; - sp<IMemoryHeap> surfaceHeap; { Mutex::Autolock _lg(gLock); @@ -462,9 +388,7 @@ void SurfaceComposerClient::dispose() delete mPrebuiltLayerState; mPrebuiltLayerState = 0; controlMemory = mControlMemory; - surfaceHeap = mSurfaceHeap; mControlMemory.clear(); - mSurfaceHeap.clear(); mControl = 0; mStatus = NO_INIT; } @@ -528,6 +452,12 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays() return n; } + +void SurfaceComposerClient::signalServer() +{ + mSignalServer->signal(); +} + sp<Surface> SurfaceComposerClient::createSurface( int pid, DisplayID display, @@ -568,186 +498,6 @@ status_t SurfaceComposerClient::destroySurface(SurfaceID sid) return err; } -status_t SurfaceComposerClient::nextBuffer(Surface* surface, - Surface::SurfaceInfo* info) -{ - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = surface->mBackbufferIndex; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const front = lcblk->surface + (1-backIdx); - info->w = front->w; - info->h = front->h; - info->format = front->format; - info->base = surface->heapBase(1-backIdx); - info->bits = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset); - info->bpr = front->bpr; - - return 0; -} - -status_t SurfaceComposerClient::lockSurface( - Surface* surface, - Surface::SurfaceInfo* other, - Region* dirty, - bool blocking) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = cblk->lock_layer(size_t(index), - per_client_cblk_t::BLOCKING); - if (backIdx >= 0) { - surface->mBackbufferIndex = backIdx; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const back = lcblk->surface + backIdx; - const surface_info_t* const front = lcblk->surface + (1-backIdx); - other->w = back->w; - other->h = back->h; - other->format = back->format; - other->base = surface->heapBase(backIdx); - other->bits = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset); - other->bpr = back->bpr; - - const Rect bounds(other->w, other->h); - Region newDirtyRegion; - - if (back->flags & surface_info_t::eBufferDirty) { - /* it is safe to write *back here, because we're guaranteed - * SurfaceFlinger is not touching it (since it just granted - * access to us) */ - const_cast<surface_info_t*>(back)->flags &= - ~surface_info_t::eBufferDirty; - - // content is meaningless in this case and the whole surface - // needs to be redrawn. - - newDirtyRegion.set(bounds); - if (dirty) { - *dirty = newDirtyRegion; - } - - //if (bytesPerPixel(other->format) == 4) { - // android_memset32( - // (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr); - //} else { - // android_memset16( // fill with green - // (uint16_t*)other->bits, 0x7E0, other->h * other->bpr); - //} - } - else - { - if (dirty) { - dirty->andSelf(Region(bounds)); - newDirtyRegion = *dirty; - } else { - newDirtyRegion.set(bounds); - } - - Region copyback; - if (!(lcblk->flags & eNoCopyBack)) { - const Region previousDirtyRegion(surface->dirtyRegion()); - copyback = previousDirtyRegion.subtract(newDirtyRegion); - } - - if (!copyback.isEmpty()) { - // copy front to back - GGLSurface cb; - cb.version = sizeof(GGLSurface); - cb.width = back->w; - cb.height = back->h; - cb.stride = back->stride; - cb.data = (GGLubyte*)surface->heapBase(backIdx); - cb.data += back->bits_offset; - cb.format = back->format; - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = front->w; - t.height = front->h; - t.stride = front->stride; - t.data = (GGLubyte*)surface->heapBase(1-backIdx); - t.data += front->bits_offset; - t.format = front->format; - - //const Region copyback(lcblk->region + 1-backIdx); - copyBlt(cb, t, copyback); - } - } - - // update dirty region - surface->setDirtyRegion(newDirtyRegion); - } - return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR); -} - -void SurfaceComposerClient::_signal_server() -{ - mSignalServer->signal(); -} - -void SurfaceComposerClient::_send_dirty_region( - layer_cblk_t* lcblk, const Region& dirty) -{ - const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift; - flat_region_t* flat_region = lcblk->region + index; - status_t err = dirty.write(flat_region, sizeof(flat_region_t)); - if (err < NO_ERROR) { - // region doesn't fit, use the bounds - const Region reg(dirty.bounds()); - reg.write(flat_region, sizeof(flat_region_t)); - } -} - -status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - Region dirty(surface->dirtyRegion()); - const Rect& swapRect(surface->swapRectangle()); - if (swapRect.isValid()) { - dirty.set(swapRect); - } - - // transmit the dirty region - layer_cblk_t* const lcblk = &(cblk->layers[index]); - _send_dirty_region(lcblk, dirty); - uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); - if (!(newstate & eNextFlipPending)) - _signal_server(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::unlockSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - layer_cblk_t* const lcblk = &(cblk->layers[index]); - cblk->unlock_layer(size_t(index)); - return NO_ERROR; -} - void SurfaceComposerClient::openGlobalTransaction() { Mutex::Autolock _l(gLock); @@ -870,7 +620,7 @@ layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) { SurfaceID index = surface->ID(); per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface.get()); + status_t err = surface->validate(cblk); if (err != NO_ERROR) return 0; @@ -973,7 +723,6 @@ status_t SurfaceComposerClient::setFlags(Surface* surface, return NO_ERROR; } - status_t SurfaceComposerClient::setTransparentRegionHint( Surface* surface, const Region& transparentRegion) { diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp index 0f4b647..e74ad4a 100644 --- a/libs/utils/Parcel.cpp +++ b/libs/utils/Parcel.cpp @@ -650,28 +650,26 @@ status_t Parcel::writeWeakBinder(const wp<IBinder>& val) return flatten_binder(ProcessState::self(), val, this); } -status_t Parcel::writeNativeHandle(const native_handle& handle) +status_t Parcel::writeNativeHandle(const native_handle* handle) { - if (handle.version != sizeof(native_handle)) + if (handle->version != sizeof(native_handle)) return BAD_TYPE; status_t err; - err = writeInt32(handle.numFds); + err = writeInt32(handle->numFds); if (err != NO_ERROR) return err; - err = writeInt32(handle.numInts); + err = writeInt32(handle->numInts); if (err != NO_ERROR) return err; - for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++) - err = writeDupFileDescriptor(handle.data[i]); + for (int i=0 ; err==NO_ERROR && i<handle->numFds ; i++) + err = writeDupFileDescriptor(handle->data[i]); if (err != NO_ERROR) { LOGD("write native handle, write dup fd failed"); return err; } - - err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts); - + err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts); return err; } @@ -928,7 +926,7 @@ wp<IBinder> Parcel::readWeakBinder() const } -native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int), void* cookie) const +native_handle* Parcel::readNativeHandle() const { int numFds, numInts; status_t err; @@ -937,31 +935,15 @@ native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int) err = readInt32(&numInts); if (err != NO_ERROR) return 0; - native_handle* h; - if (alloc == 0) { - size_t size = sizeof(native_handle) + sizeof(int)*(numFds + numInts); - h = (native_handle*)malloc(size); - h->version = sizeof(native_handle); - h->numFds = numFds; - h->numInts = numInts; - } else { - h = alloc(cookie, numFds, numInts); - if (h->version != sizeof(native_handle)) { - return 0; - } - } - + native_handle* h = native_handle_create(numFds, numInts); for (int i=0 ; err==NO_ERROR && i<numFds ; i++) { h->data[i] = dup(readFileDescriptor()); if (h->data[i] < 0) err = BAD_VALUE; } - err = read(h->data + numFds, sizeof(int)*numInts); - if (err != NO_ERROR) { - if (alloc == 0) { - free(h); - } + native_handle_close(h); + native_handle_delete(h); h = 0; } return h; diff --git a/opengl/include/EGL/android_natives.h b/opengl/include/EGL/android_natives.h new file mode 100644 index 0000000..e3c3b86 --- /dev/null +++ b/opengl/include/EGL/android_natives.h @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2009 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_ANDROID_NATIVES_H +#define ANDROID_ANDROID_NATIVES_H + +#include <sys/types.h> +#include <string.h> + +#include <hardware/gralloc.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \ + (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d)) + +#define ANDROID_NATIVE_WINDOW_MAGIC \ + ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d') + +#define ANDROID_NATIVE_BUFFER_MAGIC \ + ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r') + +// --------------------------------------------------------------------------- + +struct android_native_buffer_t; + +enum { + /* attributes of this surface or its updater */ + SURFACE_FLAG_PRESERVE_CONTENT = FRAMEBUFFER_RESERVED0, + SURFACE_FLAG_MAPPED = FRAMEBUFFER_FLAG_MAPPED, +}; + + +// --------------------------------------------------------------------------- + +struct android_native_base_t +{ + /* a magic value defined by the actual EGL native type */ + int magic; + + /* the sizeof() of the actual EGL native type */ + int version; + + void* reserved[4]; + + /* reference-counting interface */ + void (*incRef)(struct android_native_base_t* base); + void (*decRef)(struct android_native_base_t* base); +}; + + +struct android_native_window_t +{ +#ifdef __cplusplus + android_native_window_t() + : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) + { + common.magic = ANDROID_NATIVE_WINDOW_MAGIC; + common.version = sizeof(android_native_window_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + /* flags describing some attributes of this surface or its updater */ + const uint32_t flags; + + /* min swap interval supported by this updated */ + const int minSwapInterval; + + /* max swap interval supported by this updated */ + const int maxSwapInterval; + + /* horizontal and vertical resolution in DPI */ + const float xdpi; + const float ydpi; + + /* Some storage reserved for the OEM's driver. */ + intptr_t oem[4]; + + /* + * hook called by EGL when the native surface is made current + * (eglMakeCurrent()). This hook can be NULL. + */ + void (*connect)(struct android_native_window_t* window); + + /* + * hook called by EGL when the native surface in not current any-longer. + * This hook can be NULL. + */ + void (*disconnect)(struct android_native_window_t* window); + + + /* + * Set the swap interval for this surface. + * + * Returns 0 on success or -errno on error. + */ + int (*setSwapInterval)(struct android_native_window_t* window, + int interval); + + + /* + * FIXME: needs documentation for setSwapRectangle + * tentative: rect used during queueBuffer to indicate which part of + * the screen needs updating. + */ + int (*setSwapRectangle)(struct android_native_window_t* window, + int left, int top, int width, int height); + + + /* + * hook called by EGL to acquire a buffer. After this call, the buffer + * is not locked, so its content cannot be modified. + * this call may block if no buffers are availlable. + * + * Returns 0 on success or -errno on error. + */ + int (*dequeueBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t** buffer); + + /* + * hook called by EGL to lock a buffer. This MUST be called before modifying + * the content of a buffer. The buffer must have been acquired with + * dequeueBuffer first. + * + * Returns 0 on success or -errno on error. + */ + int (*lockBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t* buffer); + /* + * hook called by EGL when modifications to the render buffer are done. + * This unlocks and post the buffer. + * + * Buffers MUST be queued in the same order than they were dequeued. + * + * Returns 0 on success or -errno on error. + */ + int (*queueBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t* buffer); + + + void* reserved_proc[5]; +}; + + +struct android_native_buffer_t +{ +#ifdef __cplusplus + android_native_buffer_t() { + common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + common.version = sizeof(android_native_buffer_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + int width; + int height; + int stride; + int format; + int usage; + void* bits; // non-zero if buffer is mmaped + + void* reserved[2]; + + int (*getHandle)(struct android_native_buffer_t const * base, + buffer_handle_t* handle); + + void* reserved_proc[7]; +}; + + +/* FIXME: this is legacy for pixmaps */ +struct egl_native_pixmap_t +{ + int32_t version; /* must be 32 */ + int32_t width; + int32_t height; + int32_t stride; + uint8_t* data; + uint8_t format; + uint8_t rfu[3]; + union { + uint32_t compressedFormat; + int32_t vstride; + }; + int32_t reserved; +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +/*****************************************************************************/ + +#ifdef __cplusplus + +#include <utils/RefBase.h> + +namespace android { + +/* + * This helper class turns an EGL android_native_xxx type into a C++ + * reference-counted object; with proper type conversions. + */ +template <typename NATIVE_TYPE, typename TYPE, typename REF> +class EGLNativeBase : public NATIVE_TYPE, public REF +{ +protected: + typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE; + EGLNativeBase() : NATIVE_TYPE(), REF() { + NATIVE_TYPE::common.incRef = incRef; + NATIVE_TYPE::common.decRef = decRef; + } + static inline TYPE* getSelf(NATIVE_TYPE* self) { + return static_cast<TYPE*>(self); + } + static inline TYPE const* getSelf(NATIVE_TYPE const* self) { + return static_cast<TYPE const *>(self); + } + static inline TYPE* getSelf(android_native_base_t* base) { + return getSelf(reinterpret_cast<NATIVE_TYPE*>(base)); + } + static inline TYPE const * getSelf(android_native_base_t const* base) { + return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base)); + } + static void incRef(android_native_base_t* base) { + EGLNativeBase* self = getSelf(base); + self->incStrong(self); + } + static void decRef(android_native_base_t* base) { + EGLNativeBase* self = getSelf(base); + self->decStrong(self); + } +}; + +} // namespace android +#endif // __cplusplus + +/*****************************************************************************/ + +#endif /* ANDROID_ANDROID_NATIVES_H */ diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h index ac00901..d428087 100644 --- a/opengl/include/EGL/eglplatform.h +++ b/opengl/include/EGL/eglplatform.h @@ -89,12 +89,17 @@ typedef Window EGLNativeWindowType; #elif defined(ANDROID) -#include <EGL/eglnatives.h> +#include <EGL/android_natives.h> -typedef struct egl_native_window_t* EGLNativeWindowType; +typedef struct android_native_window_t* EGLNativeWindowType; typedef struct egl_native_pixmap_t* EGLNativePixmapType; typedef void* EGLNativeDisplayType; +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_ANDROID 0x6000 /* eglCreateImageKHR target */ +#endif + #else #error "Platform not recognized" #endif diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h index 0924cae..198e679 100644 --- a/opengl/include/GLES/glplatform.h +++ b/opengl/include/GLES/glplatform.h @@ -28,12 +28,6 @@ #define GL_APIENTRY KHRONOS_APIENTRY -// XXX: this should probably not be here -#define GL_DIRECT_TEXTURE_2D_QUALCOMM 0x7E80 - -// XXX: not sure how this is intended to be used -#define GL_GLEXT_PROTOTYPES - #endif #endif /* __glplatform_h_ */ diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 99efe4c..af5a700 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -6,6 +6,9 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +# Set to 1 to use gralloc and copybits +LIBAGL_USE_GRALLOC_COPYBITS := 1 + LOCAL_SRC_FILES:= \ egl.cpp \ state.cpp \ @@ -32,7 +35,15 @@ ifneq ($(TARGET_SIMULATOR),true) LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private endif -LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger +ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1) + LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS -I$(LOCAL_PATH)/../../../../hardware/libhardware/modules/gralloc + LOCAL_SRC_FILES += copybit.cpp +endif + +LOCAL_CFLAGS += -DLOG_TAG=\"libagl\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + +LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libagl diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp index ce31854..f927de9 100644 --- a/opengl/libagl/TextureObjectManager.cpp +++ b/opengl/libagl/TextureObjectManager.cpp @@ -1,16 +1,16 @@ /* ** Copyright 2006, 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 + ** 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 + ** 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 + ** 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. */ @@ -53,6 +53,9 @@ void EGLTextureObject::init() memset(crop_rect, 0, sizeof(crop_rect)); generate_mipmap = GL_FALSE; direct = GL_FALSE; +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + copybits_fd = -1; +#endif // LIBAGL_USE_GRALLOC_COPYBITS } void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old) @@ -146,7 +149,7 @@ status_t EGLTextureObject::reallocate( int format, int compressedFormat, int bpr) { const size_t size = h * bpr; - if (level == 0) + if (level == 0) { if (size!=mSize || !surface.data) { if (mSize && surface.data) { @@ -177,9 +180,9 @@ status_t EGLTextureObject::reallocate( return NO_MEMORY; } - LOGW_IF(level-1 >= mNumExtraLod, + LOGW_IF(level-1 >= mNumExtraLod, "specifying mipmap level %d, but # of level is %d", - level, mNumExtraLod+1); + level, mNumExtraLod+1); GGLSurface& mipmap = editMip(level); if (mipmap.data) diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h index 74ed1a4..497528c 100644 --- a/opengl/libagl/TextureObjectManager.h +++ b/opengl/libagl/TextureObjectManager.h @@ -1,16 +1,16 @@ /* ** Copyright 2006, 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 +** 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 +** 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 +** 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. */ @@ -81,6 +81,9 @@ public: GLint crop_rect[4]; GLint generate_mipmap; GLint direct; +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + int copybits_fd; +#endif // LIBAGL_USE_GRALLOC_COPYBITS }; void EGLTextureObject::incStrong(const void* id) const { diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index 8fa7566..eefe614 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -1,16 +1,16 @@ -/* +/* ** Copyright 2006, 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 +** 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 +** 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 +** 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. */ @@ -26,6 +26,9 @@ #include "primitives.h" #include "texture.h" #include "BufferObjectManager.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "copybit.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS // ---------------------------------------------------------------------------- @@ -250,7 +253,7 @@ static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) { v[2] = GGL_S_TO_X(p[2]); } -typedef array_t::fetcher_t fn_t; +typedef array_t::fetcher_t fn_t; static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x} { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, @@ -334,7 +337,7 @@ void array_t::init( this->bounds = count; } -inline void array_t::resolve() +inline void array_t::resolve() { physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer; } @@ -465,7 +468,7 @@ vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index) // We compute directly the index of a "free" entry from the locked // state of v[2] and v[3]. v = c->vc.vBuffer + 2; - v += v[0].locked | (v[1].locked<<1); + v += v[0].locked | (v[1].locked<<1); } // note: compileElement clears v->flags c->arrays.compileElement(c, v, index); @@ -480,7 +483,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index) #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED - vertex_t* const v = c->vc.vCache + + vertex_t* const v = c->vc.vCache + (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1)); if (ggl_likely(v->index == index)) { @@ -491,7 +494,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index) #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU - vertex_t* v = c->vc.vCache + + vertex_t* v = c->vc.vCache + (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2; // always record LRU in v[0] @@ -532,12 +535,12 @@ void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 1 - const GLsizei vcs = + const GLsizei vcs = (vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE); do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -569,13 +572,13 @@ void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count) count -= 1; // vertex cache size must be multiple of 1 - const GLsizei vcs = + const GLsizei vcs = (vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE - 1); do { - v0 = c->vc.vBuffer + 0; + v0 = c->vc.vBuffer + 0; v = c->vc.vBuffer + 1; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.compileElements(c, v, first, num); first += num; count -= num; @@ -602,7 +605,7 @@ void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count) return; drawPrimitivesLineStrip(c, first, count); if (ggl_likely(count >= 3)) { - vertex_t* v0 = c->vc.vBuffer; + vertex_t* v0 = c->vc.vBuffer; vertex_t* v1 = c->vc.vBuffer + 1; c->arrays.compileElement(c, v1, first); const uint32_t cc = v0->flags & v1->flags; @@ -617,12 +620,12 @@ void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 2 - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2; do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -662,14 +665,14 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, // because it allows us to preserve the same winding when the whole // batch is culled. We also need 2 extra vertices in the array, because // we always keep the two first ones. - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2; do { - v0 = c->vc.vBuffer + 0; - v1 = c->vc.vBuffer + 1; + v0 = c->vc.vBuffer + 0; + v1 = c->vc.vBuffer + 1; v = c->vc.vBuffer + 2; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.compileElements(c, v, first, num); first += num; count -= num; @@ -697,13 +700,19 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, } while (count > 0); } -void drawPrimitivesTriangleStrip(ogles_context_t* c, +void drawPrimitivesTriangleStrip(ogles_context_t* c, GLint first, GLsizei count) { drawPrimitivesTriangleFanOrStrip(c, first, count, 1); } void drawPrimitivesTriangleFan(ogles_context_t* c, GLint first, GLsizei count) { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTrangleFanWithCopybit(c, first, count)) { + return; + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS + drawPrimitivesTriangleFanOrStrip(c, first, count, 2); } @@ -713,12 +722,12 @@ void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 3 - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3; do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -779,11 +788,11 @@ void drawIndexedPrimitivesLineStrip(ogles_context_t* c, { if (ggl_unlikely(count < 2)) return; - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1; - + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); c->arrays.compileElement(c, v0, read_index(type, indices)); count -= 1; @@ -806,11 +815,11 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c, drawIndexedPrimitivesLines(c, count, indices); return; } - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1; - + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); c->arrays.compileElement(c, v0, read_index(type, indices)); count -= 1; @@ -825,7 +834,7 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c, } while (count); v1->locked = 0; - v1 = c->vc.vBuffer; + v1 = c->vc.vBuffer; const uint32_t cc = v0->flags & v1->flags; if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) c->prims.renderLine(c, v0, v1); @@ -861,7 +870,7 @@ static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c, if (ggl_unlikely(count < 3)) return; - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1 = v+1; @@ -981,17 +990,17 @@ void compileElements__3x_full(ogles_context_t* c, const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first); const size_t stride = c->arrays.vertex.stride / 4; // const GLfixed* const& m = c->transforms.mvp.matrix.m; - + GLfixed m[16]; memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m)); - + do { const GLfixed rx = vp[0]; const GLfixed ry = vp[1]; const GLfixed rz = vp[2]; vp += stride; v->index = first++; - v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); + v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); @@ -1019,7 +1028,7 @@ void compileElements__3x_full(ogles_context_t* c, #pragma mark clippers #endif -static void clipVec4(vec4_t& nv, +static void clipVec4(vec4_t& nv, GLfixed t, const vec4_t& s, const vec4_t& p) { for (int i=0; i<4 ; i++) @@ -1082,10 +1091,10 @@ void validate_arrays(ogles_context_t* c, GLenum mode) // automatically turn it off (in fact we could when the 4th coordinate // is not spcified in the vertex array). // W interpolation is never needed for points. - GLboolean perspective = + GLboolean perspective = c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS); c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective); - + // set anti-aliasing GLboolean smooth = GL_FALSE; switch (mode) { @@ -1116,7 +1125,7 @@ void validate_arrays(ogles_context_t* c, GLenum mode) if (enables & GGL_ENABLE_TMUS) { // needs texture transforms want |= transform_state_t::TEXTURE; } - if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { + if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { want |= transform_state_t::MODELVIEW; // needs eye coords } ogles_validate_transform(c, want); @@ -1135,18 +1144,18 @@ void validate_arrays(ogles_context_t* c, GLenum mode) c->arrays.mv_transform = c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2]; - + /* * *********************************************************************** * pick fetchers * *********************************************************************** */ - + array_machine_t& am = c->arrays; am.vertex.fetch = fetchNop; am.normal.fetch = currentNormal; am.color.fetch = currentColor; - + if (am.vertex.enable) { am.vertex.resolve(); if (am.vertex.bo || am.vertex.pointer) { @@ -1409,7 +1418,7 @@ void glDrawElements( // clear the vertex-cache c->vc.clear(); validate_arrays(c, mode); - + // if indices are in a buffer object, the pointer is treated as an // offset in that buffer. if (c->arrays.element_array_buffer) { @@ -1444,7 +1453,7 @@ void glBindBuffer(GLenum target, GLuint buffer) return; } } - ((target == GL_ARRAY_BUFFER) ? + ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer) = bo; } @@ -1463,7 +1472,7 @@ void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usa ogles_error(c, GL_INVALID_ENUM); return; } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer); if (bo == 0) { @@ -1493,7 +1502,7 @@ void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvo ogles_error(c, GL_INVALID_VALUE); return; } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer); if (bo == 0) { @@ -1541,7 +1550,7 @@ void glDeleteBuffers(GLsizei n, const GLuint* buffers) } } } - } + } c->bufferObjectManager->deleteBuffers(n, buffers); c->bufferObjectManager->recycleTokens(n, buffers); } diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp new file mode 100644 index 0000000..427e42a --- /dev/null +++ b/opengl/libagl/copybit.cpp @@ -0,0 +1,370 @@ +/* +** +** Copyright 2009, 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 <stdio.h> + +#include "context.h" +#include "fp.h" +#include "state.h" +#include "matrix.h" +#include "vertex.h" +#include "light.h" +#include "primitives.h" +#include "texture.h" +#include "BufferObjectManager.h" + +#include "TextureObjectManager.h" +#include <hardware/gralloc.h> +#include <hardware/copybit.h> +#include "gralloc_priv.h" + +// ---------------------------------------------------------------------------- + +namespace android { + +static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) { + img->w = surface->stride; + img->h = surface->height; + img->format = surface->format; + img->offset = 0; + img->base = surface->data; + img->fd = fd; +} + +struct clipRectRegion : public copybit_region_t { + clipRectRegion(ogles_context_t* c) { + next = iterate; + int x = c->viewport.scissor.x; + int y = c->viewport.scissor.y; + r.l = x; + r.t = y; + r.r = x + c->viewport.scissor.w; + r.b = y + c->viewport.scissor.h; + firstTime = true; + } +private: + static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { + clipRectRegion* myself = (clipRectRegion*) self; + if (myself->firstTime) { + myself->firstTime = false; + *rect = myself->r; + return 1; + } + return 0; + } + mutable copybit_rect_t r; + mutable bool firstTime; +}; + +static bool supportedCopybitsFormat(int format) { + switch (format) { + case COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_RGB_565: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + case COPYBIT_FORMAT_YCbCr_422_SP: + case COPYBIT_FORMAT_YCbCr_420_SP: + return true; + default: + return false; + } +} + +static bool hasAlpha(int format) { + switch (format) { + case COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + return true; + default: + return false; + } +} + +static inline int fixedToByte(GGLfixed val) { + return (val - (val >> 8)) >> 8; +} + +/** + * Performs a quick check of the rendering state. If this function returns + * false we cannot use the copybit driver. + */ + +static bool checkContext(ogles_context_t* c) { + + // By convenction copybitQuickCheckContext() has already returned true. + // avoid checking the same information again. + + if (c->copybits.blitEngine == NULL + || (c->rasterizer.state.enables + & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) { + return false; + } + + // Note: The drawSurfaceFd is only set for destination + // surfaces types that are supported by the hardware and + // do not have an alpha channel. So we don't have to re-check that here. + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + if (!supportedCopybitsFormat(textureObject->surface.format)) { + return false; + } + return true; +} + + +static bool copybit(GLint x, GLint y, + GLint w, GLint h, + EGLTextureObject* textureObject, + const GLint* crop_rect, + int transform, + ogles_context_t* c) +{ + // We assume checkContext has already been called and has already + // returned true. + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + + y = cbSurface.height - (y + h); + + const GLint Ucr = crop_rect[0]; + const GLint Vcr = crop_rect[1]; + const GLint Wcr = crop_rect[2]; + const GLint Hcr = crop_rect[3]; + + int32_t dsdx = (Wcr << 16) / w; // dsdx = ((Wcr/w)/Wt)*Wt + int32_t dtdy = ((-Hcr) << 16) / h; // dtdy = -((Hcr/h)/Ht)*Ht + + if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale + || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { + // The requested scale is out of the range the hardware + // can support. + return false; + } + + int32_t texelArea = gglMulx(dtdy, dsdx); + if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) { + // Non-linear filtering on a texture enlargement. + return false; + } + + if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) { + // Non-linear filtering on an texture shrink. + return false; + } + + const uint32_t enables = c->rasterizer.state.enables; + int planeAlpha = 255; + static const int tmu = 0; + texture_t& tev(c->rasterizer.state.texture[tmu]); + bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format); + switch (tev.env) { + + case GGL_REPLACE: + if (!srcTextureHasAlpha) { + planeAlpha = fixedToByte(c->currentColorClamped.a); + } + break; + + case GGL_MODULATE: + if (! (c->currentColorClamped.r == FIXED_ONE + && c->currentColorClamped.g == FIXED_ONE + && c->currentColorClamped.b == FIXED_ONE)) { + return false; + } + planeAlpha = fixedToByte(c->currentColorClamped.a); + break; + + default: + // Incompatible texture environment. + return false; + } + + bool blending = false; + + if ((enables & GGL_ENABLE_BLENDING) + && !(c->rasterizer.state.blend.src == GL_ONE + && c->rasterizer.state.blend.dst == GL_ZERO)) { + // Blending is OK if it is + // the exact kind of blending that the copybits hardware supports. + // Note: The hardware only supports + // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA, + // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA. + // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case, + // because the performance is worth it, even if the results are + // not correct. + if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA + || c->rasterizer.state.blend.src == GL_ONE) + && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA + && c->rasterizer.state.blend.alpha_separate == 0)) { + // Incompatible blend mode. + return false; + } + blending = true; + } else { + // No blending is OK if we are not using alpha. + if (srcTextureHasAlpha || planeAlpha != 255) { + // Incompatible alpha + return false; + } + } + + if (srcTextureHasAlpha && planeAlpha != 255) { + // Can't do two types of alpha at once. + return false; + } + + // LOGW("calling copybits"); + + copybit_device_t* copybit = c->copybits.blitEngine; + copybit_image_t dst; + textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst); + copybit_rect_t drect = {x, y, x+w, y+h}; + + copybit_image_t src; + textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd, + &src); + copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr }; + + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); + + copybit->set_parameter(copybit, COPYBIT_DITHER, + (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE); + + clipRectRegion it(c); + copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + return true; +} + +/* + * Try to draw a triangle fan with copybit, return false if we fail. + */ +bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) { + if (! checkContext(c)) { + return false; + } + + c->arrays.compileElements(c, c->vc.vBuffer, 0, 4); + // Is the result a screen aligned rectangle? + int sx[4]; + int sy[4]; + for (int i = 0; i < 4; i++) { + GLfixed x = c->vc.vBuffer[i].window.x; + GLfixed y = c->vc.vBuffer[i].window.y; + if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) { + return false; + } + sx[i] = x >> 4; + sy[i] = y >> 4; + } + + /* + * This is the pattern we're looking for: + * (2)--(3) + * |\ | + * | \ | + * | \ | + * | \| + * (1)--(0) + * + */ + int dx[4]; + int dy[4]; + for (int i = 0; i < 4; i++) { + int i1 = (i + 1) & 3; + dx[i] = sx[i] - sx[i1]; + dy[i] = sy[i] - sy[i1]; + } + if (dx[1] | dx[3] | dy[0] | dy[2]) { + return false; + } + if (dx[0] != -dx[2] || dy[1] != -dy[3]) { + return false; + } + + int x = sx[1]; + int y = sy[1]; + int w = dx[0]; + int h = dy[3]; + + // We expect the texture coordinates to always be the unit square: + + static const GLfixed kExpectedUV[8] = { + 0, 0, + 0, FIXED_ONE, + FIXED_ONE, FIXED_ONE, + FIXED_ONE, 0 + }; + { + const GLfixed* pExpected = &kExpectedUV[0]; + for (int i = 0; i < 4; i++) { + GLfixed u = c->vc.vBuffer[i].texture[0].x; + GLfixed v = c->vc.vBuffer[i].texture[0].y; + if (u != *pExpected++ || v != *pExpected++) { + return false; + } + } + } + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + GLint tWidth = textureObject->surface.width; + GLint tHeight = textureObject->surface.height; + GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight}; + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + y = cbSurface.height - (y + h); + + return copybit(x, y, w, h, textureObject, crop_rect, + COPYBIT_TRANSFORM_ROT_90, c); +} + +/* + * Try to drawTexiOESWithCopybit, return false if we fail. + */ + +bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c) +{ + // quickly process empty rects + if ((w|h) <= 0) { + return true; + } + + if (! checkContext(c)) { + return false; + } + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + return copybit(x, y, w, h, textureObject, textureObject->crop_rect, + 0, c); +} + +} // namespace android + diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h new file mode 100644 index 0000000..1888aee --- /dev/null +++ b/opengl/libagl/copybit.h @@ -0,0 +1,75 @@ +/* +** +** Copyright 2009, 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_OPENGLES_COPYBIT_H +#define ANDROID_OPENGLES_COPYBIT_H + +#include <stdlib.h> + +#include <GLES/gl.h> + +#include "TextureObjectManager.h" +namespace android { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + +bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c); +bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, + GLsizei count); + +inline bool copybitQuickCheckContext(ogles_context_t* c) { + return c->copybits.drawSurfaceFd >= 0 + && c->rasterizer.state.enabled_tmu == 1 + && c->textures.tmu[0].texture->copybits_fd >= 0; +} + +/* + * Tries to draw a drawTexiOES using copybit hardware. + * Returns true if successful. + */ +inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c) { + if (!copybitQuickCheckContext(c)) { + return false; + } + + return drawTexiOESWithCopybit_impl(x, y, z, w, h, c); +} + +/* + * Tries to draw a triangle fan using copybit hardware. + * Returns true if successful. + */ +inline bool drawTrangleFanWithCopybit(ogles_context_t* c, GLint first, + GLsizei count) { + /* + * We are looking for the glDrawArrays call made by SurfaceFlinger. + */ + + if (!(copybitQuickCheckContext(c) && first == 0 && count == 4)) { + return false; + } + + return drawTrangleFanWithCopybit_impl(c, first, count); +} + + +#endif // LIBAGL_USE_GRALLOC_COPYBITS + +} // namespace android + +#endif // ANDROID_OPENGLES_COPYBIT_H diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 3b4c041..5c91c92 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1,22 +1,20 @@ -/* +/* ** ** Copyright 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 +** 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 +** 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 +** 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 "EGL" - #include <assert.h> #include <errno.h> #include <stdlib.h> @@ -35,6 +33,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> +#include <EGL/android_natives.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -46,6 +45,10 @@ #include "texture.h" #include "matrix.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "gralloc_priv.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS + #undef NELEM #define NELEM(x) (sizeof(x)/sizeof(*(x))) @@ -89,9 +92,9 @@ static GLint getError() { struct egl_display_t { egl_display_t() : type(0), initialized(0) { } - + static egl_display_t& get_display(EGLDisplay dpy); - + static EGLBoolean is_valid(EGLDisplay dpy) { return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; } @@ -140,7 +143,7 @@ struct egl_surface_t egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); virtual ~egl_surface_t(); virtual bool isValid() const = 0; - + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; virtual EGLint getWidth() const = 0; @@ -188,39 +191,48 @@ EGLint egl_surface_t::getSwapBehavior() const { // ---------------------------------------------------------------------------- -struct egl_window_surface_t : public egl_surface_t +struct egl_window_surface_v2_t : public egl_surface_t { - egl_window_surface_t( + egl_window_surface_v2_t( EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - egl_native_window_t* window); + android_native_window_t* window); - ~egl_window_surface_t(); + ~egl_window_surface_v2_t(); - virtual bool isValid() const { return nativeWindow->magic == 0x600913; } + virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; } virtual EGLBoolean swapBuffers(); virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); - virtual EGLint getWidth() const { return nativeWindow->width; } - virtual EGLint getHeight() const { return nativeWindow->height; } + virtual EGLint getWidth() const { return buffer->width; } + virtual EGLint getHeight() const { return buffer->height; } virtual void* getBits() const; virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; private: - egl_native_window_t* nativeWindow; + android_native_window_t* nativeWindow; + android_native_buffer_t* buffer; + int width; + int height; }; -egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, +egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - egl_native_window_t* window) - : egl_surface_t(dpy, config, depthFormat), nativeWindow(window) + android_native_window_t* window) + : egl_surface_t(dpy, config, depthFormat), nativeWindow(window), buffer(0) { + nativeWindow->common.incRef(&nativeWindow->common); + + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + + width = buffer->width; + height = buffer->height; if (depthFormat) { - depth.width = window->width; - depth.height = window->height; + depth.width = width; + depth.height = height; depth.stride = depth.width; // use the width here depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { @@ -228,23 +240,56 @@ egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, return; } } - nativeWindow->incRef(nativeWindow); + + // TODO: lockBuffer should rather be executed when the very first + // direct rendering occurs. + buffer->common.incRef(&buffer->common); + nativeWindow->lockBuffer(nativeWindow, buffer); + + // FIXME: we need to gralloc lock the buffer + // FIXME: we need to handle the copy-back if needed, but + // for now we're a "non preserving" implementation. } -egl_window_surface_t::~egl_window_surface_t() { - nativeWindow->decRef(nativeWindow); + +egl_window_surface_v2_t::~egl_window_surface_v2_t() { + if (buffer) { + buffer->common.decRef(&buffer->common); + } + nativeWindow->common.decRef(&nativeWindow->common); } -EGLBoolean egl_window_surface_t::swapBuffers() +EGLBoolean egl_window_surface_v2_t::swapBuffers() { - uint32_t flags = nativeWindow->swapBuffers(nativeWindow); - if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) { + // TODO: this is roughly the code needed for preserving the back buffer + // efficiently. dirty is the area that has been modified. + //Region newDirty(dirty); + //newDirty.andSelf(Rect(nativeWindow->width, nativeWindow->height)); + //mDirty = newDirty; + //const Region copyback(mDirty.subtract(newDirty)); + //mDisplaySurface->copyFrontToBack(copyback); + + + nativeWindow->queueBuffer(nativeWindow, buffer); + buffer->common.decRef(&buffer->common); buffer = 0; + + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + buffer->common.incRef(&buffer->common); + + // TODO: lockBuffer should rather be executed when the very first + // direct rendering occurs. + nativeWindow->lockBuffer(nativeWindow, buffer); + + + if ((width != buffer->width) || (height != buffer->height)) { // TODO: we probably should reset the swap rect here // if the window size has changed + width = buffer->width; + height = buffer->height; if (depth.data) { free(depth.data); - depth.width = nativeWindow->width; - depth.height = nativeWindow->height; - depth.stride = nativeWindow->stride; + depth.width = width; + depth.height = height; + depth.stride = buffer->stride; depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); @@ -255,49 +300,81 @@ EGLBoolean egl_window_surface_t::swapBuffers() return EGL_TRUE; } -EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl) +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + +static bool supportedCopybitsDestinationFormat(int format) { + // Hardware supported and no destination alpha + switch (format) { + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return true; + default: + return false; + } +} +#endif + +EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) { GGLSurface buffer; buffer.version = sizeof(GGLSurface); - buffer.width = nativeWindow->width; - buffer.height = nativeWindow->height; - buffer.stride = nativeWindow->stride; - buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; - buffer.format = nativeWindow->format; + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)this->buffer->bits; + buffer.format = this->buffer->format; gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) gl->rasterizer.procs.depthBuffer(gl, &depth); +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + gl->copybits.drawSurfaceFd = -1; + if (supportedCopybitsDestinationFormat(buffer.format)) { + buffer_handle_t handle; + this->buffer->getHandle(this->buffer, &handle); + if (handle != NULL) { + private_handle_t* hand = private_handle_t::dynamicCast(handle); + if (hand != NULL) { + if (hand->usesPhysicallyContiguousMemory()) { + gl->copybits.drawSurfaceFd = hand->fd; + } + } + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS return EGL_TRUE; } -EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl) +EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) { GGLSurface buffer; buffer.version = sizeof(GGLSurface); - buffer.width = nativeWindow->width; - buffer.height = nativeWindow->height; - buffer.stride = nativeWindow->stride; - buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; - buffer.format = nativeWindow->format; + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)this->buffer->bits; + buffer.format = this->buffer->format; gl->rasterizer.procs.readBuffer(gl, &buffer); return EGL_TRUE; } -void* egl_window_surface_t::getBits() const { - return (GGLubyte*)nativeWindow->base + nativeWindow->offset; +void* egl_window_surface_v2_t::getBits() const { + return (GGLubyte*)buffer->bits; } -EGLint egl_window_surface_t::getHorizontalResolution() const { +EGLint egl_window_surface_v2_t::getHorizontalResolution() const { return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } -EGLint egl_window_surface_t::getVerticalResolution() const { +EGLint egl_window_surface_v2_t::getVerticalResolution() const { return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } -EGLint egl_window_surface_t::getRefreshRate() const { - return (nativeWindow->fps * EGL_DISPLAY_SCALING); +EGLint egl_window_surface_v2_t::getRefreshRate() const { + return (60 * EGL_DISPLAY_SCALING); // FIXME } -EGLint egl_window_surface_t::getSwapBehavior() const { - uint32_t flags = nativeWindow->flags; - if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER) - return EGL_BUFFER_DESTROYED; - return EGL_BUFFER_PRESERVED; +EGLint egl_window_surface_v2_t::getSwapBehavior() const { + //uint32_t flags = nativeWindow->flags; + //if (flags & SURFACE_FLAG_PRESERVE_CONTENT) + // return EGL_BUFFER_PRESERVED; + // This is now a feature of EGL, currently we don't preserve + // the content of the buffers. + return EGL_BUFFER_DESTROYED; } // ---------------------------------------------------------------------------- @@ -311,7 +388,7 @@ struct egl_pixmap_surface_t : public egl_surface_t virtual ~egl_pixmap_surface_t() { } - virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } + virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return nativePixmap.width; } @@ -347,7 +424,7 @@ EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl) buffer.stride = nativePixmap.stride; buffer.data = nativePixmap.data; buffer.format = nativePixmap.format; - + gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) gl->rasterizer.procs.depthBuffer(gl, &depth); @@ -376,7 +453,7 @@ struct egl_pbuffer_surface_t : public egl_surface_t virtual ~egl_pbuffer_surface_t(); - virtual bool isValid() const { return pbuffer.data != 0; } + virtual bool isValid() const { return pbuffer.data != 0; } virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return pbuffer.width; } @@ -407,7 +484,7 @@ egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, pbuffer.stride = w; pbuffer.data = (GGLubyte*)malloc(size); pbuffer.format = f; - + if (depthFormat) { depth.width = pbuffer.width; depth.height = pbuffer.height; @@ -468,7 +545,11 @@ struct config_management_t { static char const * const gVendorString = "Google Inc."; static char const * const gVersionString = "1.2 Android Driver"; static char const * const gClientApiString = "OpenGL ES"; -static char const * const gExtensionsString = ""; +static char const * const gExtensionsString = + "KHR_image_base " + // "KHR_image_pixmap " + "EGL_ANDROID_image_native_buffer " + ; // ---------------------------------------------------------------------------- @@ -478,25 +559,45 @@ struct extention_map_t { }; static const extention_map_t gExtentionMap[] = { - { "glDrawTexsOES", (void(*)())&glDrawTexsOES }, - { "glDrawTexiOES", (void(*)())&glDrawTexiOES }, - { "glDrawTexfOES", (void(*)())&glDrawTexfOES }, - { "glDrawTexxOES", (void(*)())&glDrawTexxOES }, - { "glDrawTexsvOES", (void(*)())&glDrawTexsvOES }, - { "glDrawTexivOES", (void(*)())&glDrawTexivOES }, - { "glDrawTexfvOES", (void(*)())&glDrawTexfvOES }, - { "glDrawTexxvOES", (void(*)())&glDrawTexxvOES }, - { "glQueryMatrixxOES", (void(*)())&glQueryMatrixxOES }, - { "glClipPlanef", (void(*)())&glClipPlanef }, - { "glClipPlanex", (void(*)())&glClipPlanex }, - { "glBindBuffer", (void(*)())&glBindBuffer }, - { "glBufferData", (void(*)())&glBufferData }, - { "glBufferSubData", (void(*)())&glBufferSubData }, - { "glDeleteBuffers", (void(*)())&glDeleteBuffers }, - { "glGenBuffers", (void(*)())&glGenBuffers }, + { "glDrawTexsOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, + { "glDrawTexiOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, + { "glDrawTexfOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, + { "glDrawTexxOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, + { "glDrawTexsvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, + { "glDrawTexivOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, + { "glDrawTexfvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, + { "glDrawTexxvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, + { "glQueryMatrixxOES", + (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, + { "glEGLImageTargetTexture2DOES", + (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, + { "glEGLImageTargetRenderbufferStorageOES", + (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, + { "glClipPlanef", + (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, + { "glClipPlanex", + (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, + { "glBindBuffer", + (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, + { "glBufferData", + (__eglMustCastToProperFunctionPointerType)&glBufferData }, + { "glBufferSubData", + (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, + { "glDeleteBuffers", + (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, + { "glGenBuffers", + (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, }; -/* +/* * In the lists below, attributes names MUST be sorted. * Additionally, all configs must be sorted according to * the EGL specification. @@ -507,7 +608,7 @@ static config_pair_t const config_base_attribute_list[] = { { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, { EGL_LEVEL, 0 }, { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, - { EGL_MAX_PBUFFER_PIXELS, + { EGL_MAX_PBUFFER_PIXELS, GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, { EGL_NATIVE_RENDERABLE, EGL_TRUE }, @@ -644,9 +745,9 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key) { while (first <= last) { int mid = (first + last) / 2; - if (key > sortedArray[mid].key) { + if (key > sortedArray[mid].key) { first = mid + 1; - } else if (key < sortedArray[mid].key) { + } else if (key < sortedArray[mid].key) { last = mid - 1; } else { return mid; @@ -658,13 +759,13 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key) static int isAttributeMatching(int i, EGLint attr, EGLint val) { // look for the attribute in all of our configs - config_pair_t const* configFound = gConfigs[i].array; + config_pair_t const* configFound = gConfigs[i].array; int index = binarySearch<config_pair_t>( gConfigs[i].array, 0, gConfigs[i].size-1, attr); if (index < 0) { - configFound = config_base_attribute_list; + configFound = config_base_attribute_list; index = binarySearch<config_pair_t>( config_base_attribute_list, 0, NELEM(config_base_attribute_list)-1, @@ -778,28 +879,28 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -812,9 +913,9 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, //if (EGLint(info.format) != pixelFormat) // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - egl_surface_t* surface = - new egl_window_surface_t(dpy, config, depthFormat, - static_cast<egl_native_window_t*>(window)); + egl_surface_t* surface; + surface = new egl_window_surface_v2_t(dpy, config, depthFormat, + static_cast<android_native_window_t*>(window)); if (!surface->isValid()) { // there was a problem in the ctor, the error @@ -847,28 +948,28 @@ static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -900,10 +1001,10 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, EGLint surfaceType; if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE; - + if (!(surfaceType & EGL_PBUFFER_BIT)) return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - + EGLint configID; if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) return EGL_FALSE; @@ -911,28 +1012,28 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -985,7 +1086,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) egl_display_t& d = egl_display_t::get_display(dpy); d.type = display; return dpy; - } + } return EGL_NO_DISPLAY; } @@ -993,10 +1094,10 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - + EGLBoolean res = EGL_TRUE; egl_display_t& d = egl_display_t::get_display(dpy); - + if (android_atomic_inc(&d.initialized) == 0) { // initialize stuff here if needed //pthread_mutex_lock(&gInitMutex); @@ -1064,7 +1165,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, *num_config = 0; return EGL_TRUE; } - + int numAttributes = 0; int numConfigs = NELEM(gConfigs); uint32_t possibleMatch = (1<<numConfigs)-1; @@ -1145,7 +1246,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, { return createWindowSurface(dpy, config, window, attrib_list); } - + EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) @@ -1158,7 +1259,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, { return createPbufferSurface(dpy, config, attrib_list); } - + EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) @@ -1228,7 +1329,7 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface, *value = (wr * EGL_DISPLAY_SCALING) / hr; } break; case EGL_SWAP_BEHAVIOR: - *value = surface->getSwapBehavior(); + *value = surface->getSwapBehavior(); break; default: ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); @@ -1278,7 +1379,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } EGLContext current_ctx = EGL_NO_CONTEXT; - + if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) return setError(EGL_BAD_MATCH, EGL_FALSE); @@ -1299,6 +1400,8 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } } + // TODO: call connect / disconnect on the surface + ogles_context_t* gl = (ogles_context_t*)ctx; if (makeCurrent(gl) == 0) { if (ctx) { @@ -1407,7 +1510,7 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - + egl_surface_t* d = static_cast<egl_surface_t*>(draw); if (d->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); @@ -1540,7 +1643,7 @@ EGLSurface eglCreatePbufferFromClientBuffer( } // ---------------------------------------------------------------------------- -// Android extensions +// EGL_EGLEXT_VERSION 3 // ---------------------------------------------------------------------------- void (*eglGetProcAddress (const char *procname))() @@ -1553,3 +1656,81 @@ void (*eglGetProcAddress (const char *procname))() } return NULL; } + +EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, + const EGLint *attrib_list) +{ + EGLBoolean result = EGL_FALSE; + return result; +} + +EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) +{ + EGLBoolean result = EGL_FALSE; + return result; +} + +EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); + } + if (ctx != EGL_NO_CONTEXT) { + return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); + } + if (target != EGL_NATIVE_BUFFER_ANDROID) { + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + buffer_handle_t bufferHandle; + gralloc_module_t const* module = + reinterpret_cast<gralloc_module_t const*>(pModule); + if (native_buffer->getHandle(native_buffer, &bufferHandle) < 0) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + if (module->map(module, bufferHandle, &native_buffer->bits) < 0) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + native_buffer->common.incRef(&native_buffer->common); + return (EGLImageKHR)native_buffer; +} + +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule) == 0) { + buffer_handle_t bufferHandle; + gralloc_module_t const* module = + reinterpret_cast<gralloc_module_t const*>(pModule); + if (native_buffer->getHandle(native_buffer, &bufferHandle) == 0) { + module->unmap(module, bufferHandle); + } + } + + native_buffer->common.decRef(&native_buffer->common); + + return EGL_TRUE; +} diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp index 5cbabea..a00f779 100644 --- a/opengl/libagl/state.cpp +++ b/opengl/libagl/state.cpp @@ -2,16 +2,16 @@ ** ** Copyright 2006, 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 +** 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 +** 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 +** 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. */ @@ -28,12 +28,16 @@ #include "BufferObjectManager.h" #include "TextureObjectManager.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include <hardware/copybit.h> +#endif // LIBAGL_USE_GRALLOC_COPYBITS + namespace android { // ---------------------------------------------------------------------------- static char const * const gVendorString = "Android"; -static char const * const gRendererString = "Android PixelFlinger 1.0"; +static char const * const gRendererString = "Android PixelFlinger 1.1"; static char const * const gVersionString = "OpenGL ES-CM 1.0"; static char const * const gExtensionsString = "GL_OES_byte_coordinates " // OK @@ -46,9 +50,9 @@ static char const * const gExtensionsString = "GL_OES_query_matrix " // OK // "GL_OES_point_size_array " // TODO // "GL_OES_point_sprite " // TODO + "GL_OES_EGL_image " // OK "GL_ARB_texture_compression " // OK "GL_ARB_texture_non_power_of_two " // OK - "GL_ANDROID_direct_texture " // OK "GL_ANDROID_user_clip_plane " // OK "GL_ANDROID_vertex_buffer_object " // OK "GL_ANDROID_generate_mipmap " // OK @@ -62,13 +66,13 @@ static char const * const gExtensionsString = ogles_context_t *ogles_init(size_t extra) { void* const base = malloc(extra + sizeof(ogles_context_t) + 32); - if (!base) return 0; + if (!base) return 0; ogles_context_t *c = (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL); memset(c, 0, sizeof(ogles_context_t)); ggl_init_context(&(c->rasterizer)); - + // XXX: this should be passed as an argument sp<EGLSurfaceManager> smgr(new EGLSurfaceManager()); c->surfaceManager = smgr.get(); @@ -87,13 +91,42 @@ ogles_context_t *ogles_init(size_t extra) c->rasterizer.base = base; c->point.size = TRI_ONE; c->line.width = TRI_ONE; - + // in OpenGL, writing to the depth buffer is enabled by default. c->rasterizer.procs.depthMask(c, 1); - + // OpenGL enables dithering by default c->rasterizer.procs.enable(c, GL_DITHER); + c->copybits.blitEngine = NULL; + c->copybits.minScale = 0; + c->copybits.maxScale = 0; + c->copybits.drawSurfaceFd = -1; + +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + hw_module_t const* module; + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { + struct copybit_device_t* copyBits; + if (copybit_open(module, ©Bits) == 0) { + c->copybits.blitEngine = copyBits; + { + int minLim = copyBits->get(copyBits, + COPYBIT_MINIFICATION_LIMIT); + if (minLim != -EINVAL && minLim > 0) { + c->copybits.minScale = (1 << 16) / minLim; + } + } + { + int magLim = copyBits->get(copyBits, + COPYBIT_MAGNIFICATION_LIMIT); + if (magLim != -EINVAL && magLim > 0) { + c->copybits.maxScale = min(32*1024-1, magLim) << 16; + } + } + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS + return c; } @@ -107,7 +140,12 @@ void ogles_uninit(ogles_context_t* c) c->surfaceManager->decStrong(c); c->bufferObjectManager->decStrong(c); ggl_uninit_context(&(c->rasterizer)); - free(c->rasterizer.base); + free(c->rasterizer.base); +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (c->copybits.blitEngine != NULL) { + copybit_close((struct copybit_device_t*) c->copybits.blitEngine); + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS } void _ogles_error(ogles_context_t* c, GLenum error) @@ -188,7 +226,7 @@ static void enable_disable(ogles_context_t* c, GLenum cap, int enabled) // these need to fall through into the rasterizer c->rasterizer.procs.enableDisable(c, cap, enabled); break; - + case GL_MULTISAMPLE: case GL_SAMPLE_ALPHA_TO_COVERAGE: case GL_SAMPLE_ALPHA_TO_ONE: @@ -281,7 +319,7 @@ void glHint(GLenum target, GLenum mode) case GL_LINE_SMOOTH_HINT: break; case GL_POINT_SMOOTH_HINT: - c->rasterizer.procs.enableDisable(c, + c->rasterizer.procs.enableDisable(c, GGL_POINT_SMOOTH_NICE, mode==GL_NICEST); break; case GL_PERSPECTIVE_CORRECTION_HINT: @@ -323,7 +361,7 @@ GLenum glGetError() c->error = 0; return ret; } - + if (c->rasterizer.error) { const GLenum ret(c->rasterizer.error); c->rasterizer.error = 0; @@ -362,25 +400,25 @@ void glGetIntegerv(GLenum pname, GLint *params) int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].ah - formats[index].al; - break; + break; } case GL_RED_BITS: { int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].rh - formats[index].rl; - break; + break; } case GL_GREEN_BITS: { int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].gh - formats[index].gl; - break; + break; } case GL_BLUE_BITS: { int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].bh - formats[index].bl; - break; + break; } case GL_COMPRESSED_TEXTURE_FORMATS: params[ 0] = GL_PALETTE4_RGB8_OES; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index b6f534b..9dca133 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -2,16 +2,16 @@ ** ** Copyright 2006, 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 +** 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 +** 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 +** 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. */ @@ -23,6 +23,13 @@ #include "texture.h" #include "TextureObjectManager.h" +#include <EGL/android_natives.h> + +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "copybit.h" +#include "gralloc_priv.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS + namespace android { // ---------------------------------------------------------------------------- @@ -48,7 +55,7 @@ void ogles_init_texture(ogles_context_t* c) // each context has a default named (0) texture (not shared) c->textures.defaultTexture = new EGLTextureObject(); c->textures.defaultTexture->incStrong(c); - + // bind the default texture to each texture unit for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { bindTextureTmu(c, i, 0, c->textures.defaultTexture); @@ -255,7 +262,7 @@ sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) u.texture->decStrong(c); if (name == 0) { - // 0 is our local texture object, not shared with anyone. + // 0 is our local texture object, not shared with anyone. // But it affects all bound TMUs immediately. // (we need to invalidate all units bound to this texture object) tex = c->textures.defaultTexture; @@ -273,7 +280,7 @@ sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) u.texture = tex.get(); u.texture->incStrong(c); u.name = name; - invalidate_texture(c, active); + invalidate_texture(c, active); return tex; } @@ -282,7 +289,7 @@ void bindTextureTmu( { if (tex.get() == c->textures.tmu[tmu].texture) return; - + // free the reference to the previously bound object texture_unit_t& u(c->textures.tmu[tmu]); if (u.texture) @@ -310,7 +317,7 @@ int createTextureSurface(ogles_context_t* c, if (formatIdx == 0) { // we don't know what to do with this return GL_INVALID_OPERATION; } - + // figure out the size we need as well as the stride const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); const int32_t align = c->textures.unpackAlignment-1; @@ -530,8 +537,8 @@ static void texParameterx( ogles_error(c, GL_INVALID_ENUM); return; } - - EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; + + EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; switch (pname) { case GL_TEXTURE_WRAP_S: if ((param == GL_REPEAT) || @@ -581,13 +588,10 @@ invalid_enum: } -static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, + +static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, ogles_context_t* c) { - // quickly reject empty rects - if ((w|h) <= 0) - return; - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = gglIntToFixed(cbSurface.height) - (y + h); w >>= FIXED_BITS; @@ -610,7 +614,7 @@ static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); u.dirty = 0xFF; // XXX: should be more subtle - EGLTextureObject* textureObject = u.texture; + EGLTextureObject* textureObject = u.texture; const GLint Ucr = textureObject->crop_rect[0] << 16; const GLint Vcr = textureObject->crop_rect[1] << 16; const GLint Wcr = textureObject->crop_rect[2] << 16; @@ -641,13 +645,30 @@ static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, c->rasterizer.procs.disable(c, GGL_W_LERP); c->rasterizer.procs.disable(c, GGL_AA); c->rasterizer.procs.shadeModel(c, GL_FLAT); - c->rasterizer.procs.recti(c, + c->rasterizer.procs.recti(c, gglFixedToIntRound(x), gglFixedToIntRound(y), gglFixedToIntRound(x)+w, gglFixedToIntRound(y)+h); } +static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, + ogles_context_t* c) +{ +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTexiOESWithCopybit(gglFixedToIntRound(x), + gglFixedToIntRound(y), gglFixedToIntRound(z), + gglFixedToIntRound(w), gglFixedToIntRound(h), c)) { + return; + } +#else + // quickly reject empty rects + if ((w|h) <= 0) + return; +#endif + drawTexxOESImp(x, y, z, w, h, c); +} + static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c) { // All coordinates are integer, so if we have only one @@ -656,14 +677,21 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte // which is a lot faster. if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTexiOESWithCopybit(x, y, z, w, h, c)) { + return; + } +#endif const int tmu = 0; texture_unit_t& u(c->textures.tmu[tmu]); - EGLTextureObject* textureObject = u.texture; + EGLTextureObject* textureObject = u.texture; const GLint Wcr = textureObject->crop_rect[2]; const GLint Hcr = textureObject->crop_rect[3]; if ((w == Wcr) && (h == -Hcr)) { +#ifndef LIBAGL_USE_GRALLOC_COPYBITS if ((w|h) <= 0) return; // quickly reject empty rects +#endif if (u.dirty) { c->rasterizer.procs.activeTexture(c, tmu); @@ -679,14 +707,14 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); u.dirty = 0xFF; // XXX: should be more subtle c->rasterizer.procs.activeTexture(c, c->textures.active); - + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = cbSurface.height - (y + h); const GLint Ucr = textureObject->crop_rect[0]; const GLint Vcr = textureObject->crop_rect[1]; const GLint s0 = Ucr - x; const GLint t0 = (Vcr + Hcr) - y; - + const GLuint tw = textureObject->surface.width; const GLuint th = textureObject->surface.height; if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) { @@ -694,7 +722,7 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte // in this case, so we just use the slow case, which // at least won't crash goto slow_case; - } + } c->rasterizer.procs.texCoord2i(c, s0, t0); const uint32_t enables = c->rasterizer.state.enables; @@ -711,7 +739,7 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte } slow_case: - drawTexxOES( + drawTexxOESImp( gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z), gglIntToFixed(w), gglIntToFixed(h), c); @@ -749,7 +777,7 @@ void glBindTexture(GLenum target, GLuint texture) } // Bind or create a texture - sp<EGLTextureObject> tex; + sp<EGLTextureObject> tex; if (texture == 0) { // 0 is our local texture object tex = c->textures.defaultTexture; @@ -837,7 +865,7 @@ void glPixelStorei(GLenum pname, GLint param) if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) { ogles_error(c, GL_INVALID_ENUM); return; - } + } if ((param<=0 || param>8) || (param & (param-1))) { ogles_error(c, GL_INVALID_VALUE); return; @@ -945,7 +973,7 @@ void glCompressedTexImage2D( } // "uncompress" the texture since pixelflinger doesn't support - // any compressed texture format natively. + // any compressed texture format natively. GLenum format; GLenum type; switch (internalformat) { @@ -1009,7 +1037,7 @@ void glTexImage2D( GLenum format, GLenum type, const GLvoid *pixels) { ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { + if (target != GL_TEXTURE_2D) { ogles_error(c, GL_INVALID_ENUM); return; } @@ -1017,7 +1045,7 @@ void glTexImage2D( ogles_error(c, GL_INVALID_VALUE); return; } - if (format != internalformat) { + if (format != (GLenum)internalformat) { ogles_error(c, GL_INVALID_OPERATION); return; } @@ -1027,16 +1055,10 @@ void glTexImage2D( int32_t size = 0; GGLSurface* surface = 0; - if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - int error = createTextureSurface(c, &surface, &size, - level, format, type, width, height); - if (error) { - ogles_error(c, error); - return; - } - } else if (pixels == 0 || level != 0) { - // pixel can't be null for direct texture - ogles_error(c, GL_INVALID_OPERATION); + int error = createTextureSurface(c, &surface, &size, + level, format, type, width, height); + if (error) { + ogles_error(c, error); return; } @@ -1057,18 +1079,12 @@ void glTexImage2D( userSurface.compressedFormat = 0; userSurface.data = (GLubyte*)pixels; - if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); - if (err) { - ogles_error(c, err); - return; - } - generateMipmap(c, level); - } else { - // bind it to the texture unit - sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); - tex->setSurface(&userSurface); + int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); + if (err) { + ogles_error(c, err); + return; } + generateMipmap(c, level); } } @@ -1143,7 +1159,7 @@ void glTexSubImage2D( int err = copyPixels(c, surface, xoffset, yoffset, - userSurface, 0, 0, width, height); + userSurface, 0, 0, width, height); if (err) { ogles_error(c, err); return; @@ -1196,7 +1212,7 @@ void glCopyTexImage2D( case GL_LUMINANCE_ALPHA: case GL_LUMINANCE: type = GL_UNSIGNED_BYTE; - break; + break; } // figure out the format to use for the new texture @@ -1206,7 +1222,7 @@ void glCopyTexImage2D( case GGL_PIXEL_FORMAT_RGBA_5551: case GGL_PIXEL_FORMAT_RGBA_4444: format = internalformat; - break; + break; case GGL_PIXEL_FORMAT_RGBX_8888: case GGL_PIXEL_FORMAT_RGB_888: case GGL_PIXEL_FORMAT_RGB_565: @@ -1215,7 +1231,7 @@ void glCopyTexImage2D( case GL_LUMINANCE: case GL_RGB: format = internalformat; - break; + break; } break; } @@ -1235,7 +1251,7 @@ void glCopyTexImage2D( ogles_error(c, error); return; } - + // The bottom row is stored first in textures GGLSurface txSurface(*surface); txSurface.stride = -txSurface.stride; @@ -1245,7 +1261,7 @@ void glCopyTexImage2D( int err = copyPixels(c, txSurface, 0, 0, - cbSurface, x, y, cbSurface.width, cbSurface.height); + cbSurface, x, y, cbSurface.width, cbSurface.height); if (err) { ogles_error(c, err); } @@ -1295,7 +1311,7 @@ void glCopyTexSubImage2D( int err = copyPixels(c, surface, xoffset, yoffset, - cbSurface, x, y, width, height); + cbSurface, x, y, width, height); if (err) { ogles_error(c, err); return; @@ -1365,7 +1381,7 @@ void glReadPixels( return; } - ggl->colorBuffer(ggl, &userSurface); // destination is user buffer + ggl->colorBuffer(ggl, &userSurface); // destination is user buffer ggl->bindTexture(ggl, &readSurface); // source is read-buffer ggl->texCoord2i(ggl, x, readSurface.height - (y + height)); ggl->recti(ggl, 0, 0, width, height); @@ -1419,3 +1435,73 @@ void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { ogles_context_t* c = ogles_context_t::get(); drawTexxOES(x, y, z, w, h, c); } + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark EGL Image Extension +#endif + +void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (native_buffer->common.version != sizeof(android_native_buffer_t)) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + if (native_buffer->bits == NULL) { + // this buffer cannot be used with this implementation + ogles_error(c, GL_INVALID_VALUE); + return; + } + + GGLSurface sur; + sur.version = sizeof(GGLSurface); + sur.width = native_buffer->width; + sur.height= native_buffer->height; + sur.stride= native_buffer->stride; + sur.format= native_buffer->format; + sur.data = (GGLubyte*)native_buffer->bits; + + // bind it to the texture unit + sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); + tex->setSurface(&sur); + + /* + * Here an implementation can retrieve the buffer_handle_t of this buffer + * which gives it access to an arbitrary-defined kernel resource + * (or anything else for that matter). + * There needs to be an intimate knowledge between GLES and buffer_handle_t, + * so make sure to validate the handle before using it. + * Typically, buffer_handle_t comes from the gralloc HAL which is provided + * by the implementor of GLES. + * + */ +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + tex->copybits_fd = -1; + buffer_handle_t handle; + if (native_buffer->getHandle(native_buffer, &handle) == 0) { + private_handle_t* hand; + if ((hand = private_handle_t::dynamicCast(handle)) != NULL) { + if (hand->usesPhysicallyContiguousMemory()) { + tex->copybits_fd = hand->fd; + } + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS +} + +void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ +} diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index 2ecc776..da00cc5 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -7,8 +7,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - EGL/egl.cpp \ - EGL/gpu.cpp \ + EGL/egl.cpp \ # LOCAL_SHARED_LIBRARIES += libcutils libutils libui @@ -23,6 +22,9 @@ else LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private endif +LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + include $(BUILD_SHARED_LIBRARY) @@ -35,7 +37,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ GLES_CM/gl.cpp.arm \ - GLES_CM/gl_logger.cpp \ # LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL @@ -50,4 +51,7 @@ else LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private endif +LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 0b4bcce..c58fff8 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -14,8 +14,6 @@ ** limitations under the License. */ -#define LOG_TAG "GLLogger" - #include <ctype.h> #include <string.h> #include <errno.h> @@ -38,6 +36,8 @@ #include <cutils/memory.h> #include <utils/RefBase.h> +#include <utils/threads.h> +#include <utils/KeyedVector.h> #include "hooks.h" #include "egl_impl.h" @@ -55,7 +55,14 @@ namespace android { static char const * const gVendorString = "Android"; static char const * const gVersionString = "1.31 Android META-EGL"; static char const * const gClientApiString = "OpenGL ES"; -static char const * const gExtensionString = ""; +static char const * const gExtensionString = + "EGL_KHR_image " + "KHR_image_base " + "KHR_image_pixmap " + "EGL_ANDROID_image_native_buffer " + ; + +// ---------------------------------------------------------------------------- template <int MAGIC> struct egl_object_t @@ -69,9 +76,9 @@ private: struct egl_display_t : public egl_object_t<'_dpy'> { - EGLDisplay dpys[2]; - EGLConfig* configs[2]; - EGLint numConfigs[2]; + EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; EGLint numTotalConfigs; char const* extensionsString; volatile int32_t refs; @@ -81,27 +88,21 @@ struct egl_display_t : public egl_object_t<'_dpy'> char const * clientApi; char const * extensions; }; - strings_t queryString[2]; + strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; }; struct egl_surface_t : public egl_object_t<'_srf'> { egl_surface_t(EGLDisplay dpy, EGLSurface surface, - NativeWindowType window, int impl, egl_connection_t const* cnx) - : dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx) + int impl, egl_connection_t const* cnx) + : dpy(dpy), surface(surface), impl(impl), cnx(cnx) { // NOTE: window must be incRef'ed and connected already } ~egl_surface_t() { - if (window) { - if (window->disconnect) - window->disconnect(window); - window->decRef(window); - } } EGLDisplay dpy; EGLSurface surface; - NativeWindowType window; int impl; egl_connection_t const* cnx; }; @@ -121,6 +122,18 @@ struct egl_context_t : public egl_object_t<'_ctx'> egl_connection_t const* cnx; }; +struct egl_image_t : public egl_object_t<'_img'> +{ + egl_image_t(EGLDisplay dpy, EGLContext context) + : dpy(dpy), context(context) + { + memset(images, 0, sizeof(images)); + } + EGLDisplay dpy; + EGLConfig context; + EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; +}; + struct tls_t { tls_t() : error(EGL_SUCCESS), ctx(0) { } @@ -156,7 +169,7 @@ static char const * const egl_names[] = { // ---------------------------------------------------------------------------- -egl_connection_t gEGLImpl[2]; +egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; static egl_display_t gDisplay[NUM_DISPLAYS]; static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t gEGLThreadLocalStorageKey = -1; @@ -261,14 +274,8 @@ EGLContext getContext() { return tls->ctx; } - /*****************************************************************************/ -class ISurfaceComposer; -const sp<ISurfaceComposer>& getSurfaceFlinger(); -request_gpu_t* gpu_acquire(void* user); -int gpu_release(void*, request_gpu_t* gpu); - static __attribute__((noinline)) void *load_driver(const char* driver, gl_hooks_t* hooks) { @@ -278,43 +285,60 @@ void *load_driver(const char* driver, gl_hooks_t* hooks) driver, dlerror()); if (dso) { - void** curr; + // first find the symbol for eglGetProcAddress + + typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( + const char*); + + getProcAddressType getProcAddress = + (getProcAddressType)dlsym(dso, "eglGetProcAddress"); + + LOGE_IF(!getProcAddress, + "can't find eglGetProcAddress() in %s", driver); + + __eglMustCastToProperFunctionPointerType* curr; char const * const * api; - gl_hooks_t::gl_t* gl = &hooks->gl; - curr = (void**)gl; - api = gl_names; + + gl_hooks_t::egl_t* egl = &hooks->egl; + curr = (__eglMustCastToProperFunctionPointerType*)egl; + api = egl_names; while (*api) { - void* f = dlsym(dso, *api); - //LOGD("<%s> @ 0x%p", *api, f); + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); if (f == NULL) { - //LOGW("<%s> not found in %s", *api, driver); - f = (void*)gl_unimplemented; + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + if (f == NULL) { + f = (__eglMustCastToProperFunctionPointerType)0; + } } *curr++ = f; api++; } - gl_hooks_t::egl_t* egl = &hooks->egl; - curr = (void**)egl; - api = egl_names; + + gl_hooks_t::gl_t* gl = &hooks->gl; + curr = (__eglMustCastToProperFunctionPointerType*)gl; + api = gl_names; while (*api) { - void* f = dlsym(dso, *api); + char const * name = *api; + // if the function starts with '__' it's a special case that + // uses a wrapper. skip the '__' when looking into the real lib. + if (name[0] == '_' && name[1] == '_') { + name += 2; + } + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); if (f == NULL) { - //LOGW("<%s> not found in %s", *api, driver); - f = (void*)0; + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + if (f == NULL) { + f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; + } } *curr++ = f; api++; } - - // hook this driver up with surfaceflinger if needed - register_gpu_t register_gpu = - (register_gpu_t)dlsym(dso, "oem_register_gpu"); - - if (register_gpu != NULL) { - if (getSurfaceFlinger() != 0) { - register_gpu(dso, gpu_acquire, gpu_release); - } - } } return dso; } @@ -365,6 +389,14 @@ struct extention_map_t { }; static const extention_map_t gExtentionMap[] = { + { "eglLockSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, + { "eglUnlockSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, + { "eglCreateImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, + { "eglDestroyImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, }; static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS]; @@ -382,6 +414,12 @@ 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; @@ -429,18 +467,24 @@ egl_display_t* get_display(EGLDisplay dpy) return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index]; } +template<typename NATIVE, typename EGL> +static inline NATIVE* egl_to_native_cast(EGL arg) { + return reinterpret_cast<NATIVE*>(arg); +} + static inline -egl_surface_t* get_surface(EGLSurface surface) -{ - egl_surface_t* s = (egl_surface_t *)surface; - return s; +egl_surface_t* get_surface(EGLSurface surface) { + return egl_to_native_cast<egl_surface_t>(surface); } static inline -egl_context_t* get_context(EGLContext context) -{ - egl_context_t* c = (egl_context_t *)context; - return c; +egl_context_t* get_context(EGLContext context) { + return egl_to_native_cast<egl_context_t>(context); +} + +static inline +egl_image_t* get_image(EGLImageKHR image) { + return egl_to_native_cast<egl_image_t>(image); } static egl_connection_t* validate_display_config( @@ -451,7 +495,7 @@ static egl_connection_t* validate_display_config( if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL); impl = uintptr_t(config)>>24; - if (uint32_t(impl) >= 2) { + if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) { return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); } index = uintptr_t(config) & 0xFFFFFF; @@ -491,13 +535,26 @@ static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) return EGL_TRUE; } -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- -using namespace android; +EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image) +{ + EGLContext context = getContext(); + if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR) + return EGL_NO_IMAGE_KHR; + + egl_context_t const * const c = get_context(context); + if (!c->isValid()) + return EGL_NO_IMAGE_KHR; -EGLDisplay eglGetDisplay(NativeDisplayType display) + egl_image_t const * const i = get_image(image); + if (!i->isValid()) + return EGL_NO_IMAGE_KHR; + + return i->images[c->impl]; +} + + +EGLDisplay egl_init_displays(NativeDisplayType display) { if (sEarlyInitState) { return EGL_NO_DISPLAY; @@ -510,7 +567,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); egl_display_t* d = &gDisplay[index]; - + // dynamically load all our EGL implementations for that display // and call into the real eglGetGisplay() egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE]; @@ -530,7 +587,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) property_get("debug.egl.hw", value, "1"); if (atoi(value) != 0) { cnx->hooks = &gHooks[IMPL_HARDWARE]; - cnx->dso = load_driver("libhgl.so", cnx->hooks); + cnx->dso = load_driver("libhgl2.so", cnx->hooks); } else { LOGD("3D hardware acceleration is disabled"); } @@ -573,6 +630,18 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) return dpy; } + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +using namespace android; + +EGLDisplay eglGetDisplay(NativeDisplayType display) +{ + return egl_init_displays(display); +} + // ---------------------------------------------------------------------------- // Initialization // ---------------------------------------------------------------------------- @@ -594,7 +663,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) // build our own extension string first, based on the extension we know // and the extension supported by our client implementation dp->extensionsString = strdup(gExtensionString); - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; cnx->major = -1; cnx->minor = -1; @@ -624,7 +693,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) } EGLBoolean res = EGL_FALSE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { EGLint n; @@ -663,7 +732,7 @@ EGLBoolean eglTerminate(EGLDisplay dpy) return EGL_TRUE; EGLBoolean res = EGL_FALSE; - for (int i=0 ; i<2 ; i++) { + 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]); @@ -706,7 +775,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy, return EGL_TRUE; } GLint n = 0; - for (int j=0 ; j<2 ; j++) { + for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) { for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) { *configs++ = MAKE_CONFIG(j, i); config_size--; @@ -794,7 +863,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, return res; } - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglChooseConfig( @@ -854,26 +923,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, int i=0, index=0; egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); if (cnx) { - // window must be connected upon calling underlying - // eglCreateWindowSurface - if (window) { - window->incRef(window); - if (window->connect) - window->connect(window); - } - EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface( dp->dpys[i], dp->configs[i][index], window, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx); + egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; } - - // something went wrong, disconnect and free window - // (will disconnect() automatically) - if (window) { - window->decRef(window); - } } return EGL_NO_SURFACE; } @@ -889,7 +944,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface( dp->dpys[i], dp->configs[i][index], pixmap, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); + egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; } } @@ -906,7 +961,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface( dp->dpys[i], dp->configs[i][index], attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); + egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; } } @@ -1107,7 +1162,7 @@ EGLBoolean eglWaitNative(EGLint engine) EGLint eglGetError(void) { EGLint result = EGL_SUCCESS; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { EGLint err = EGL_SUCCESS; egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) @@ -1120,8 +1175,15 @@ EGLint eglGetError(void) return result; } -void (*eglGetProcAddress(const char *procname))() +__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; + __eglMustCastToProperFunctionPointerType addr; addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); if (addr) return addr; @@ -1133,7 +1195,7 @@ void (*eglGetProcAddress(const char *procname))() addr = 0; int slot = -1; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglGetProcAddress) { @@ -1266,7 +1328,7 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); EGLBoolean res = EGL_TRUE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglSwapInterval) { @@ -1309,7 +1371,7 @@ EGLBoolean eglBindAPI(EGLenum api) { // bind this API on all EGLs EGLBoolean res = EGL_TRUE; - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglBindAPI) { @@ -1324,7 +1386,7 @@ EGLBoolean eglBindAPI(EGLenum api) EGLenum eglQueryAPI(void) { - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglQueryAPI) { @@ -1340,7 +1402,7 @@ EGLenum eglQueryAPI(void) EGLBoolean eglReleaseThread(void) { - for (int i=0 ; i<2 ; i++) { + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso) { if (cnx->hooks->egl.eglReleaseThread) { @@ -1366,3 +1428,124 @@ EGLSurface eglCreatePbufferFromClientBuffer( } return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); } + +// ---------------------------------------------------------------------------- +// EGL_EGLEXT_VERSION 3 +// ---------------------------------------------------------------------------- + +EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, + const EGLint *attrib_list) +{ + EGLBoolean result = EGL_FALSE; + if (!validate_display_surface(dpy, surface)) + return result; + + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + + if (s->cnx->hooks->egl.eglLockSurfaceKHR) { + result = s->cnx->hooks->egl.eglLockSurfaceKHR( + dp->dpys[s->impl], s->surface, attrib_list); + } + return result; +} + +EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) +{ + EGLBoolean result = EGL_FALSE; + if (!validate_display_surface(dpy, surface)) + return result; + + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + + if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) { + result = s->cnx->hooks->egl.eglUnlockSurfaceKHR( + dp->dpys[s->impl], s->surface); + } + return result; +} + +EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (ctx != EGL_NO_CONTEXT) { + if (!validate_display_context(dpy, ctx)) + return EGL_NO_IMAGE_KHR; + egl_display_t const * const dp = get_display(dpy); + egl_context_t * const c = get_context(ctx); + // since we have an EGLContext, we know which implementation to use + EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR( + dp->dpys[c->impl], c->context, target, buffer, attrib_list); + if (image == EGL_NO_IMAGE_KHR) + return image; + + egl_image_t* result = new egl_image_t(dpy, ctx); + result->images[c->impl] = image; + return (EGLImageKHR)result; + } else { + // EGL_NO_CONTEXT is a valid parameter + egl_display_t const * const dp = get_display(dpy); + if (dp == 0) { + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); + } + // since we don't have a way to know which implementation to call, + // we're calling all of them + + EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + bool success = false; + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + implImages[i] = EGL_NO_IMAGE_KHR; + if (cnx->dso) { + if (cnx->hooks->egl.eglCreateImageKHR) { + implImages[i] = cnx->hooks->egl.eglCreateImageKHR( + dp->dpys[i], ctx, target, buffer, attrib_list); + if (implImages[i] != EGL_NO_IMAGE_KHR) { + success = true; + } + } + } + } + if (!success) + return EGL_NO_IMAGE_KHR; + + egl_image_t* result = new egl_image_t(dpy, ctx); + memcpy(result->images, implImages, sizeof(implImages)); + return (EGLImageKHR)result; + } +} + +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + egl_display_t const * const dp = get_display(dpy); + if (dp == 0) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + egl_image_t* image = get_image(img); + if (!image->isValid()) { + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + } + + bool success = false; + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (image->images[i] != EGL_NO_IMAGE_KHR) { + if (cnx->dso) { + if (cnx->hooks->egl.eglCreateImageKHR) { + if (cnx->hooks->egl.eglDestroyImageKHR( + dp->dpys[i], image->images[i])) { + success = true; + } + } + } + } + } + if (!success) + return EGL_FALSE; + + delete image; + + return EGL_FALSE; +} diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp index 865cf44..a175343 100644 --- a/opengl/libs/GLES_CM/gl.cpp +++ b/opengl/libs/GLES_CM/gl.cpp @@ -14,8 +14,6 @@ ** limitations under the License. */ -#define LOG_TAG "GLES_CM" - #include <ctype.h> #include <string.h> #include <errno.h> @@ -29,6 +27,7 @@ #include <cutils/properties.h> #include "hooks.h" +#include "egl_impl.h" using namespace android; @@ -57,13 +56,6 @@ void glVertexPointerBounds(GLint size, GLenum type, // Actual GL entry-points // ---------------------------------------------------------------------------- -#if GL_LOGGER -# include "gl_logger.h" -# define GL_LOGGER_IMPL(_x) _x -#else -# define GL_LOGGER_IMPL(_x) -#endif - #undef API_ENTRY #undef CALL_GL_API #undef CALL_GL_API_RETURN @@ -96,16 +88,15 @@ void glVertexPointerBounds(GLint size, GLenum type, #define CALL_GL_API(_api, ...) \ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \ _c->_api(__VA_ARGS__) #define CALL_GL_API_RETURN(_api, ...) \ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \ return _c->_api(__VA_ARGS__) #endif + extern "C" { #include "gl_api.in" } @@ -114,3 +105,27 @@ extern "C" { #undef CALL_GL_API #undef CALL_GL_API_RETURN + +/* + * These GL calls are special because they need to EGL to retrieve some + * informations before they can execute. + */ + +extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); +extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); + + +void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + GLeglImageOES implImage = + (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); + __glEGLImageTargetTexture2DOES(target, implImage); +} + +void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + GLeglImageOES implImage = + (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); + __glEGLImageTargetRenderbufferStorageOES(target, image); +} + diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in index 9234ef2..f36b8c0 100644 --- a/opengl/libs/GLES_CM/gl_api.in +++ b/opengl/libs/GLES_CM/gl_api.in @@ -1,606 +1,760 @@ -void API_ENTRY(glActiveTexture)(GLenum texture) { - CALL_GL_API(glActiveTexture, texture); +void API_ENTRY(glColor4f)(GLfloat arg0, GLfloat arg1, GLfloat arg2, GLfloat arg3) { + CALL_GL_API(glColor4f, arg0, arg1, arg2, arg3); } -void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) { - CALL_GL_API(glAlphaFunc, func, ref); +void API_ENTRY(glColor4x)(GLfixed arg0, GLfixed arg1, GLfixed arg2, GLfixed arg3) { + CALL_GL_API(glColor4x, arg0, arg1, arg2, arg3); } -void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) { - CALL_GL_API(glAlphaFuncx, func, ref); +void API_ENTRY(glNormal3f)(GLfloat arg0, GLfloat arg1, GLfloat arg2) { + CALL_GL_API(glNormal3f, arg0, arg1, arg2); } -void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) { - CALL_GL_API(glBindTexture, target, texture); +void API_ENTRY(glNormal3x)(GLfixed arg0, GLfixed arg1, GLfixed arg2) { + CALL_GL_API(glNormal3x, arg0, arg1, arg2); } -void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) { - CALL_GL_API(glBlendFunc, sfactor, dfactor); +void API_ENTRY(glCullFace)(GLenum arg0) { + CALL_GL_API(glCullFace, arg0); } -void API_ENTRY(glClear)(GLbitfield mask) { - CALL_GL_API(glClear, mask); +void API_ENTRY(glFrontFace)(GLenum arg0) { + CALL_GL_API(glFrontFace, arg0); } -void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - CALL_GL_API(glClearColor, red, green, blue, alpha); +void API_ENTRY(glDisable)(GLenum arg0) { + CALL_GL_API(glDisable, arg0); } -void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { - CALL_GL_API(glClearColorx, red, green, blue, alpha); +void API_ENTRY(glEnable)(GLenum arg0) { + CALL_GL_API(glEnable, arg0); } -void API_ENTRY(glClearDepthf)(GLclampf depth) { - CALL_GL_API(glClearDepthf, depth); +void API_ENTRY(glFinish)(void) { + CALL_GL_API(glFinish); } -void API_ENTRY(glClearDepthx)(GLclampx depth) { - CALL_GL_API(glClearDepthx, depth); +void API_ENTRY(glFlush)(void) { + CALL_GL_API(glFlush); } -void API_ENTRY(glClearStencil)(GLint s) { - CALL_GL_API(glClearStencil, s); +GLenum API_ENTRY(glGetError)(void) { + CALL_GL_API_RETURN(glGetError); } -void API_ENTRY(glClientActiveTexture)(GLenum texture) { - CALL_GL_API(glClientActiveTexture, texture); +const GLubyte* API_ENTRY(glGetString)(GLenum arg0) { + CALL_GL_API_RETURN(glGetString, arg0); } -void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - CALL_GL_API(glColor4f, red, green, blue, alpha); +void API_ENTRY(glGetIntegerv)(GLenum arg0, GLint * arg1) { + CALL_GL_API(glGetIntegerv, arg0, arg1); } -void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) { - CALL_GL_API(glColor4x, red, green, blue, alpha); +void API_ENTRY(glColorMask)(GLboolean arg0, GLboolean arg1, GLboolean arg2, GLboolean arg3) { + CALL_GL_API(glColorMask, arg0, arg1, arg2, arg3); } -void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { - CALL_GL_API(glColorMask, r, g, b, a); +void API_ENTRY(glDepthMask)(GLboolean arg0) { + CALL_GL_API(glDepthMask, arg0); } -void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) -{ - CALL_GL_API(glColorPointer, size, type, stride, ptr); +void API_ENTRY(glStencilMask)(GLuint arg0) { + CALL_GL_API(glStencilMask, arg0); } -void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, - GLsizei imageSize, const GLvoid *data) { - CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, - width, height, border, imageSize, data); +void API_ENTRY(glDepthFunc)(GLenum arg0) { + CALL_GL_API(glDepthFunc, arg0); } -void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, - const GLvoid *data) { - CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, - width, height, format, imageSize, data); +void API_ENTRY(glDepthRangef)(GLclampf arg0, GLclampf arg1) { + CALL_GL_API(glDepthRangef, arg0, arg1); } -void API_ENTRY(glCopyTexImage2D)( GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) { - CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, - width, height, border); +void API_ENTRY(glDepthRangex)(GLclampx arg0, GLclampx arg1) { + CALL_GL_API(glDepthRangex, arg0, arg1); } -void API_ENTRY(glCopyTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLint x, GLint y, GLsizei width, - GLsizei height) { - CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, - width, height); +void API_ENTRY(glPolygonOffset)(GLfloat arg0, GLfloat arg1) { + CALL_GL_API(glPolygonOffset, arg0, arg1); } -void API_ENTRY(glCullFace)(GLenum mode) { - CALL_GL_API(glCullFace, mode); +void API_ENTRY(glPolygonOffsetx)(GLfixed arg0, GLfixed arg1) { + CALL_GL_API(glPolygonOffsetx, arg0, arg1); } -void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) { - CALL_GL_API(glDeleteTextures, n, textures); +void API_ENTRY(glLogicOp)(GLenum arg0) { + CALL_GL_API(glLogicOp, arg0); } -void API_ENTRY(glDepthFunc)(GLenum func) { - CALL_GL_API(glDepthFunc, func); +void API_ENTRY(glAlphaFuncx)(GLenum arg0, GLclampx arg1) { + CALL_GL_API(glAlphaFuncx, arg0, arg1); } -void API_ENTRY(glDepthMask)(GLboolean flag) { - CALL_GL_API(glDepthMask, flag); +void API_ENTRY(glAlphaFunc)(GLenum arg0, GLclampf arg1) { + CALL_GL_API(glAlphaFunc, arg0, arg1); } -void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { - CALL_GL_API(glDepthRangef, zNear, zFar); +void API_ENTRY(glBlendFunc)(GLenum arg0, GLenum arg1) { + CALL_GL_API(glBlendFunc, arg0, arg1); } -void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) { - CALL_GL_API(glDepthRangex, zNear, zFar); +void API_ENTRY(glClear)(GLbitfield arg0) { + CALL_GL_API(glClear, arg0); } -void API_ENTRY(glDisable)(GLenum cap) { - CALL_GL_API(glDisable, cap); +void API_ENTRY(glClearColor)(GLclampf arg0, GLclampf arg1, GLclampf arg2, GLclampf arg3) { + CALL_GL_API(glClearColor, arg0, arg1, arg2, arg3); } -void API_ENTRY(glDisableClientState)(GLenum array) { - CALL_GL_API(glDisableClientState, array); +void API_ENTRY(glClearColorx)(GLclampx arg0, GLclampx arg1, GLclampx arg2, GLclampx arg3) { + CALL_GL_API(glClearColorx, arg0, arg1, arg2, arg3); } -void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) { - CALL_GL_API(glDrawArrays, mode, first, count); +void API_ENTRY(glClearDepthf)(GLclampf arg0) { + CALL_GL_API(glClearDepthf, arg0); } -void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, - GLenum type, const GLvoid *indices) { - CALL_GL_API(glDrawElements, mode, count, type, indices); +void API_ENTRY(glClearDepthx)(GLclampx arg0) { + CALL_GL_API(glClearDepthx, arg0); } -void API_ENTRY(glEnable)(GLenum cap) { - CALL_GL_API(glEnable, cap); +void API_ENTRY(glClearStencil)(GLint arg0) { + CALL_GL_API(glClearStencil, arg0); } -void API_ENTRY(glEnableClientState)(GLenum array) { - CALL_GL_API(glEnableClientState, array); +void API_ENTRY(glPointSize)(GLfloat arg0) { + CALL_GL_API(glPointSize, arg0); } -void API_ENTRY(glFinish)(void) { - CALL_GL_API(glFinish); +void API_ENTRY(glPointSizex)(GLfixed arg0) { + CALL_GL_API(glPointSizex, arg0); } -void API_ENTRY(glFlush)(void) { - CALL_GL_API(glFlush); +void API_ENTRY(glSampleCoverage)(GLclampf arg0, GLboolean arg1) { + CALL_GL_API(glSampleCoverage, arg0, arg1); } -void API_ENTRY(glFogf)(GLenum pname, GLfloat param) { - CALL_GL_API(glFogf, pname, param); +void API_ENTRY(glSampleCoveragex)(GLclampx arg0, GLboolean arg1) { + CALL_GL_API(glSampleCoveragex, arg0, arg1); } -void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glFogfv, pname, params); +void API_ENTRY(glStencilFunc)(GLenum arg0, GLint arg1, GLuint arg2) { + CALL_GL_API(glStencilFunc, arg0, arg1, arg2); } -void API_ENTRY(glFogx)(GLenum pname, GLfixed param) { - CALL_GL_API(glFogx, pname, param); +void API_ENTRY(glStencilOp)(GLenum arg0, GLenum arg1, GLenum arg2) { + CALL_GL_API(glStencilOp, arg0, arg1, arg2); } -void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glFogxv, pname, params); +void API_ENTRY(glScissor)(GLint arg0, GLint arg1, GLsizei arg2, GLsizei arg3) { + CALL_GL_API(glScissor, arg0, arg1, arg2, arg3); } -void API_ENTRY(glFrontFace)(GLenum mode) { - CALL_GL_API(glFrontFace, mode); +void API_ENTRY(glHint)(GLenum arg0, GLenum arg1) { + CALL_GL_API(glHint, arg0, arg1); } -void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar) { - CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar); +void API_ENTRY(glLineWidth)(GLfloat arg0) { + CALL_GL_API(glLineWidth, arg0); } -void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar) { - CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar); +void API_ENTRY(glLineWidthx)(GLfixed arg0) { + CALL_GL_API(glLineWidthx, arg0); } -void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) { - CALL_GL_API(glGenTextures, n, textures); +void API_ENTRY(glShadeModel)(GLenum arg0) { + CALL_GL_API(glShadeModel, arg0); } -GLenum API_ENTRY(glGetError)(void) { - CALL_GL_API_RETURN(glGetError); +void API_ENTRY(glLightModelf)(GLenum arg0, GLfloat arg1) { + CALL_GL_API(glLightModelf, arg0, arg1); +} + +void API_ENTRY(glLightModelfv)(GLenum arg0, const GLfloat * arg1) { + CALL_GL_API(glLightModelfv, arg0, arg1); +} + +void API_ENTRY(glLightModelx)(GLenum arg0, GLfixed arg1) { + CALL_GL_API(glLightModelx, arg0, arg1); +} + +void API_ENTRY(glLightModelxv)(GLenum arg0, const GLfixed * arg1) { + CALL_GL_API(glLightModelxv, arg0, arg1); +} + +void API_ENTRY(glLightf)(GLenum arg0, GLenum arg1, GLfloat arg2) { + CALL_GL_API(glLightf, arg0, arg1, arg2); +} + +void API_ENTRY(glLightfv)(GLenum arg0, GLenum arg1, const GLfloat * arg2) { + CALL_GL_API(glLightfv, arg0, arg1, arg2); +} + +void API_ENTRY(glLightx)(GLenum arg0, GLenum arg1, GLfixed arg2) { + CALL_GL_API(glLightx, arg0, arg1, arg2); +} + +void API_ENTRY(glLightxv)(GLenum arg0, GLenum arg1, const GLfixed * arg2) { + CALL_GL_API(glLightxv, arg0, arg1, arg2); +} + +void API_ENTRY(glMaterialf)(GLenum arg0, GLenum arg1, GLfloat arg2) { + CALL_GL_API(glMaterialf, arg0, arg1, arg2); +} + +void API_ENTRY(glMaterialfv)(GLenum arg0, GLenum arg1, const GLfloat * arg2) { + CALL_GL_API(glMaterialfv, arg0, arg1, arg2); +} + +void API_ENTRY(glMaterialx)(GLenum arg0, GLenum arg1, GLfixed arg2) { + CALL_GL_API(glMaterialx, arg0, arg1, arg2); +} + +void API_ENTRY(glMaterialxv)(GLenum arg0, GLenum arg1, const GLfixed * arg2) { + CALL_GL_API(glMaterialxv, arg0, arg1, arg2); } -void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) { - CALL_GL_API(glGetIntegerv, pname, params); +void API_ENTRY(glFogf)(GLenum arg0, GLfloat arg1) { + CALL_GL_API(glFogf, arg0, arg1); } -const GLubyte * API_ENTRY(glGetString)(GLenum name) { - CALL_GL_API_RETURN(glGetString, name); +void API_ENTRY(glFogfv)(GLenum arg0, const GLfloat * arg1) { + CALL_GL_API(glFogfv, arg0, arg1); } -void API_ENTRY(glHint)(GLenum target, GLenum mode) { - CALL_GL_API(glHint, target, mode); +void API_ENTRY(glFogx)(GLenum arg0, GLfixed arg1) { + CALL_GL_API(glFogx, arg0, arg1); } -void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) { - CALL_GL_API(glLightModelf, pname, param); +void API_ENTRY(glFogxv)(GLenum arg0, const GLfixed * arg1) { + CALL_GL_API(glFogxv, arg0, arg1); } -void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glLightModelfv, pname, params); +void API_ENTRY(glVertexPointer)(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3) { + CALL_GL_API(glVertexPointer, arg0, arg1, arg2, arg3); } -void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) { - CALL_GL_API(glLightModelx, pname, param); +void API_ENTRY(glColorPointer)(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3) { + CALL_GL_API(glColorPointer, arg0, arg1, arg2, arg3); } -void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glLightModelxv, pname, params); +void API_ENTRY(glNormalPointer)(GLenum arg0, GLsizei arg1, const GLvoid * arg2) { + CALL_GL_API(glNormalPointer, arg0, arg1, arg2); } -void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) { - CALL_GL_API(glLightf, light, pname, param); +void API_ENTRY(glTexCoordPointer)(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3) { + CALL_GL_API(glTexCoordPointer, arg0, arg1, arg2, arg3); } -void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) { - CALL_GL_API(glLightfv, light, pname, params); +void API_ENTRY(glEnableClientState)(GLenum arg0) { + CALL_GL_API(glEnableClientState, arg0); } -void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) { - CALL_GL_API(glLightx, light, pname, param); +void API_ENTRY(glDisableClientState)(GLenum arg0) { + CALL_GL_API(glDisableClientState, arg0); } -void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) { - CALL_GL_API(glLightxv, light, pname, params); +void API_ENTRY(glClientActiveTexture)(GLenum arg0) { + CALL_GL_API(glClientActiveTexture, arg0); } -void API_ENTRY(glLineWidth)(GLfloat width) { - CALL_GL_API(glLineWidth, width); +void API_ENTRY(glDrawArrays)(GLenum arg0, GLint arg1, GLsizei arg2) { + CALL_GL_API(glDrawArrays, arg0, arg1, arg2); } -void API_ENTRY(glLineWidthx)(GLfixed width) { - CALL_GL_API(glLineWidthx, width); +void API_ENTRY(glDrawElements)(GLenum arg0, GLsizei arg1, GLenum arg2, const GLvoid * arg3) { + CALL_GL_API(glDrawElements, arg0, arg1, arg2, arg3); } void API_ENTRY(glLoadIdentity)(void) { CALL_GL_API(glLoadIdentity); } -void API_ENTRY(glLoadMatrixf)(const GLfloat *m) { - CALL_GL_API(glLoadMatrixf, m); +void API_ENTRY(glLoadMatrixf)(const GLfloat* arg0) { + CALL_GL_API(glLoadMatrixf, arg0); } -void API_ENTRY(glLoadMatrixx)(const GLfixed *m) { - CALL_GL_API(glLoadMatrixx, m); +void API_ENTRY(glLoadMatrixx)(const GLfixed* arg0) { + CALL_GL_API(glLoadMatrixx, arg0); } -void API_ENTRY(glLogicOp)(GLenum opcode) { - CALL_GL_API(glLogicOp, opcode); +void API_ENTRY(glMatrixMode)(GLenum arg0) { + CALL_GL_API(glMatrixMode, arg0); } -void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) { - CALL_GL_API(glMaterialf, face, pname, param); +void API_ENTRY(glMultMatrixf)(const GLfloat* arg0) { + CALL_GL_API(glMultMatrixf, arg0); } -void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) { - CALL_GL_API(glMaterialfv, face, pname, params); +void API_ENTRY(glMultMatrixx)(const GLfixed* arg0) { + CALL_GL_API(glMultMatrixx, arg0); } -void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) { - CALL_GL_API(glMaterialx, face, pname, param); +void API_ENTRY(glPopMatrix)(void) { + CALL_GL_API(glPopMatrix); } -void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) { - CALL_GL_API(glMaterialxv, face, pname, params); +void API_ENTRY(glPushMatrix)(void) { + CALL_GL_API(glPushMatrix); } -void API_ENTRY(glMatrixMode)(GLenum mode) { - CALL_GL_API(glMatrixMode, mode); +void API_ENTRY(glFrustumf)(GLfloat arg0, GLfloat arg1, GLfloat arg2, GLfloat arg3, GLfloat arg4, GLfloat arg5) { + CALL_GL_API(glFrustumf, arg0, arg1, arg2, arg3, arg4, arg5); } -void API_ENTRY(glMultMatrixf)(const GLfloat *m) { - CALL_GL_API(glMultMatrixf, m); +void API_ENTRY(glFrustumx)(GLfixed arg0, GLfixed arg1, GLfixed arg2, GLfixed arg3, GLfixed arg4, GLfixed arg5) { + CALL_GL_API(glFrustumx, arg0, arg1, arg2, arg3, arg4, arg5); } -void API_ENTRY(glMultMatrixx)(const GLfixed *m) { - CALL_GL_API(glMultMatrixx, m); +void API_ENTRY(glOrthof)(GLfloat arg0, GLfloat arg1, GLfloat arg2, GLfloat arg3, GLfloat arg4, GLfloat arg5) { + CALL_GL_API(glOrthof, arg0, arg1, arg2, arg3, arg4, arg5); } -void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { - CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q); +void API_ENTRY(glOrthox)(GLfixed arg0, GLfixed arg1, GLfixed arg2, GLfixed arg3, GLfixed arg4, GLfixed arg5) { + CALL_GL_API(glOrthox, arg0, arg1, arg2, arg3, arg4, arg5); } -void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) { - CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q); +void API_ENTRY(glRotatef)(GLfloat arg0, GLfloat arg1, GLfloat arg2, GLfloat arg3) { + CALL_GL_API(glRotatef, arg0, arg1, arg2, arg3); } -void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) { - CALL_GL_API(glNormal3f, nx, ny, nz); +void API_ENTRY(glRotatex)(GLfixed arg0, GLfixed arg1, GLfixed arg2, GLfixed arg3) { + CALL_GL_API(glRotatex, arg0, arg1, arg2, arg3); } -void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) { - CALL_GL_API(glNormal3x, nx, ny, nz); +void API_ENTRY(glScalef)(GLfloat arg0, GLfloat arg1, GLfloat arg2) { + CALL_GL_API(glScalef, arg0, arg1, arg2); } -void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glNormalPointer, type, stride, pointer); +void API_ENTRY(glScalex)(GLfixed arg0, GLfixed arg1, GLfixed arg2) { + CALL_GL_API(glScalex, arg0, arg1, arg2); } -void API_ENTRY(glOrthof)( GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar) { - CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar); +void API_ENTRY(glTranslatef)(GLfloat arg0, GLfloat arg1, GLfloat arg2) { + CALL_GL_API(glTranslatef, arg0, arg1, arg2); } -void API_ENTRY(glOrthox)( GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar) { - CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar); +void API_ENTRY(glTranslatex)(GLfixed arg0, GLfixed arg1, GLfixed arg2) { + CALL_GL_API(glTranslatex, arg0, arg1, arg2); } -void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) { - CALL_GL_API(glPixelStorei, pname, param); +void API_ENTRY(glViewport)(GLint arg0, GLint arg1, GLsizei arg2, GLsizei arg3) { + CALL_GL_API(glViewport, arg0, arg1, arg2, arg3); } -void API_ENTRY(glPointSize)(GLfloat size) { - CALL_GL_API(glPointSize, size); +void API_ENTRY(glActiveTexture)(GLenum arg0) { + CALL_GL_API(glActiveTexture, arg0); } -void API_ENTRY(glPointSizex)(GLfixed size) { - CALL_GL_API(glPointSizex, size); +void API_ENTRY(glBindTexture)(GLenum arg0, GLuint arg1) { + CALL_GL_API(glBindTexture, arg0, arg1); } -void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { - CALL_GL_API(glPolygonOffset, factor, units); +void API_ENTRY(glGenTextures)(GLsizei arg0, GLuint* arg1) { + CALL_GL_API(glGenTextures, arg0, arg1); } -void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) { - CALL_GL_API(glPolygonOffsetx, factor, units); +void API_ENTRY(glDeleteTextures)(GLsizei arg0, const GLuint * arg1) { + CALL_GL_API(glDeleteTextures, arg0, arg1); } -void API_ENTRY(glPopMatrix)(void) { - CALL_GL_API(glPopMatrix); +void API_ENTRY(glMultiTexCoord4f)(GLenum arg0, GLfloat arg1, GLfloat arg2, GLfloat arg3, GLfloat arg4) { + CALL_GL_API(glMultiTexCoord4f, arg0, arg1, arg2, arg3, arg4); } -void API_ENTRY(glPushMatrix)(void) { - CALL_GL_API(glPushMatrix); +void API_ENTRY(glMultiTexCoord4x)(GLenum arg0, GLfixed arg1, GLfixed arg2, GLfixed arg3, GLfixed arg4) { + CALL_GL_API(glMultiTexCoord4x, arg0, arg1, arg2, arg3, arg4); +} + +void API_ENTRY(glPixelStorei)(GLenum arg0, GLint arg1) { + CALL_GL_API(glPixelStorei, arg0, arg1); +} + +void API_ENTRY(glTexEnvf)(GLenum arg0, GLenum arg1, GLfloat arg2) { + CALL_GL_API(glTexEnvf, arg0, arg1, arg2); +} + +void API_ENTRY(glTexEnvfv)(GLenum arg0, GLenum arg1, const GLfloat* arg2) { + CALL_GL_API(glTexEnvfv, arg0, arg1, arg2); +} + +void API_ENTRY(glTexEnvx)(GLenum arg0, GLenum arg1, GLfixed arg2) { + CALL_GL_API(glTexEnvx, arg0, arg1, arg2); +} + +void API_ENTRY(glTexEnvxv)(GLenum arg0, GLenum arg1, const GLfixed* arg2) { + CALL_GL_API(glTexEnvxv, arg0, arg1, arg2); +} + +void API_ENTRY(glTexParameterf)(GLenum arg0, GLenum arg1, GLfloat arg2) { + CALL_GL_API(glTexParameterf, arg0, arg1, arg2); +} + +void API_ENTRY(glTexParameterx)(GLenum arg0, GLenum arg1, GLfixed arg2) { + CALL_GL_API(glTexParameterx, arg0, arg1, arg2); +} + +void API_ENTRY(glCompressedTexImage2D)(GLenum arg0, GLint arg1, GLenum arg2, GLsizei arg3, GLsizei arg4, GLint arg5, GLsizei arg6, const GLvoid* arg7) { + CALL_GL_API(glCompressedTexImage2D, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + +void API_ENTRY(glCompressedTexSubImage2D)(GLenum arg0, GLint arg1, GLint arg2, GLint arg3, GLsizei arg4, GLsizei arg5, GLenum arg6, GLsizei arg7, const GLvoid* arg8) { + CALL_GL_API(glCompressedTexSubImage2D, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); +} + +void API_ENTRY(glCopyTexImage2D)(GLenum arg0, GLint arg1, GLenum arg2, GLint arg3, GLint arg4, GLsizei arg5, GLsizei arg6, GLint arg7) { + CALL_GL_API(glCopyTexImage2D, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + +void API_ENTRY(glCopyTexSubImage2D)(GLenum arg0, GLint arg1, GLint arg2, GLint arg3, GLint arg4, GLint arg5, GLsizei arg6, GLsizei arg7) { + CALL_GL_API(glCopyTexSubImage2D, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + +void API_ENTRY(glTexImage2D)(GLenum arg0, GLint arg1, GLint arg2, GLsizei arg3, GLsizei arg4, GLint arg5, GLenum arg6, GLenum arg7, const GLvoid* arg8) { + CALL_GL_API(glTexImage2D, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); +} + +void API_ENTRY(glTexSubImage2D)(GLenum arg0, GLint arg1, GLint arg2, GLint arg3, GLsizei arg4, GLsizei arg5, GLenum arg6, GLenum arg7, const GLvoid* arg8) { + CALL_GL_API(glTexSubImage2D, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } -void API_ENTRY(glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels) { - CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels); +void API_ENTRY(glReadPixels)(GLint arg0, GLint arg1, GLsizei arg2, GLsizei arg3, GLenum arg4, GLenum arg5, GLvoid * arg6) { + CALL_GL_API(glReadPixels, arg0, arg1, arg2, arg3, arg4, arg5, arg6); } -void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glRotatef, angle, x, y, z); +void API_ENTRY(glClipPlanef)(GLenum arg0, const GLfloat* arg1) { + CALL_GL_API(glClipPlanef, arg0, arg1); } -void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) { - CALL_GL_API(glRotatex, angle, x, y, z); +void API_ENTRY(glClipPlanex)(GLenum arg0, const GLfixed* arg1) { + CALL_GL_API(glClipPlanex, arg0, arg1); } -void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) { - CALL_GL_API(glSampleCoverage, value, invert); +void API_ENTRY(glBindBuffer)(GLenum arg0, GLuint arg1) { + CALL_GL_API(glBindBuffer, arg0, arg1); } -void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) { - CALL_GL_API(glSampleCoveragex, value, invert); +void API_ENTRY(glBufferData)(GLenum arg0, GLsizeiptr arg1, const GLvoid* arg2, GLenum arg3) { + CALL_GL_API(glBufferData, arg0, arg1, arg2, arg3); } -void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glScalef, x, y, z); +void API_ENTRY(glBufferSubData)(GLenum arg0, GLintptr arg1, GLsizeiptr arg2, const GLvoid* arg3) { + CALL_GL_API(glBufferSubData, arg0, arg1, arg2, arg3); } -void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) { - CALL_GL_API(glScalex, x, y, z); +void API_ENTRY(glDeleteBuffers)(GLsizei arg0, const GLuint* arg1) { + CALL_GL_API(glDeleteBuffers, arg0, arg1); } -void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) { - CALL_GL_API(glScissor, x, y, width, height); +void API_ENTRY(glGenBuffers)(GLsizei arg0, GLuint* arg1) { + CALL_GL_API(glGenBuffers, arg0, arg1); } -void API_ENTRY(glShadeModel)(GLenum mode) { - CALL_GL_API(glShadeModel, mode); +void API_ENTRY(glGetBooleanv)(GLenum arg0, GLboolean * arg1) { + CALL_GL_API(glGetBooleanv, arg0, arg1); } -void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) { - CALL_GL_API(glStencilFunc, func, ref, mask); +void API_ENTRY(glGetFixedv)(GLenum arg0, GLfixed * arg1) { + CALL_GL_API(glGetFixedv, arg0, arg1); } -void API_ENTRY(glStencilMask)(GLuint mask) { - CALL_GL_API(glStencilMask, mask); +void API_ENTRY(glGetFloatv)(GLenum arg0, GLfloat * arg1) { + CALL_GL_API(glGetFloatv, arg0, arg1); } -void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) { - CALL_GL_API(glStencilOp, fail, zfail, zpass); +void API_ENTRY(glGetPointerv)(GLenum arg0, void ** arg1) { + CALL_GL_API(glGetPointerv, arg0, arg1); } -void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glTexCoordPointer, size, type, stride, pointer); +void API_ENTRY(glGetBufferParameteriv)(GLenum arg0, GLenum arg1, GLint * arg2) { + CALL_GL_API(glGetBufferParameteriv, arg0, arg1, arg2); } -void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) { - CALL_GL_API(glTexEnvf, target, pname, param); +void API_ENTRY(glGetClipPlanef)(GLenum arg0, GLfloat arg1[4]) { + CALL_GL_API(glGetClipPlanef, arg0, arg1); } -void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) { - CALL_GL_API(glTexEnvfv, target, pname, params); +void API_ENTRY(glGetClipPlanex)(GLenum arg0, GLfixed arg1[4]) { + CALL_GL_API(glGetClipPlanex, arg0, arg1); } -void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) { - CALL_GL_API(glTexEnvx, target, pname, param); +void API_ENTRY(glGetLightxv)(GLenum arg0, GLenum arg1, GLfixed * arg2) { + CALL_GL_API(glGetLightxv, arg0, arg1, arg2); } -void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { - CALL_GL_API(glTexEnvxv, target, pname, params); +void API_ENTRY(glGetLightfv)(GLenum arg0, GLenum arg1, GLfloat * arg2) { + CALL_GL_API(glGetLightfv, arg0, arg1, arg2); } -void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLint border, GLenum format, - GLenum type, const GLvoid *pixels) { - CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, - border, format, type, pixels); +void API_ENTRY(glGetMaterialxv)(GLenum arg0, GLenum arg1, GLfixed * arg2) { + CALL_GL_API(glGetMaterialxv, arg0, arg1, arg2); } -void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { - CALL_GL_API(glTexParameterf, target, pname, param); +void API_ENTRY(glGetMaterialfv)(GLenum arg0, GLenum arg1, GLfloat * arg2) { + CALL_GL_API(glGetMaterialfv, arg0, arg1, arg2); } -void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) { - CALL_GL_API(glTexParameterx, target, pname, param); +void API_ENTRY(glGetTexEnvfv)(GLenum arg0, GLenum arg1, GLfloat * arg2) { + CALL_GL_API(glGetTexEnvfv, arg0, arg1, arg2); } -void API_ENTRY(glTexSubImage2D)( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid *pixels) { - CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, - width, height, format, type, pixels); +void API_ENTRY(glGetTexEnviv)(GLenum arg0, GLenum arg1, GLint * arg2) { + CALL_GL_API(glGetTexEnviv, arg0, arg1, arg2); } -void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) { - CALL_GL_API(glTranslatef, x, y, z); +void API_ENTRY(glGetTexEnvxv)(GLenum arg0, GLenum arg1, GLfixed * arg2) { + CALL_GL_API(glGetTexEnvxv, arg0, arg1, arg2); } -void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) { - CALL_GL_API(glTranslatex, x, y, z); +void API_ENTRY(glGetTexParameterfv)(GLenum arg0, GLenum arg1, GLfloat * arg2) { + CALL_GL_API(glGetTexParameterfv, arg0, arg1, arg2); } -void API_ENTRY(glVertexPointer)( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glVertexPointer, size, type, stride, pointer); +void API_ENTRY(glGetTexParameteriv)(GLenum arg0, GLenum arg1, GLint * arg2) { + CALL_GL_API(glGetTexParameteriv, arg0, arg1, arg2); } -void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) { - CALL_GL_API(glViewport, x, y, width, height); +void API_ENTRY(glGetTexParameterxv)(GLenum arg0, GLenum arg1, GLfixed * arg2) { + CALL_GL_API(glGetTexParameterxv, arg0, arg1, arg2); } -// ES 1.1 -void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) { - CALL_GL_API(glClipPlanef, plane, equation); +GLboolean API_ENTRY(glIsBuffer)(GLuint arg0) { + CALL_GL_API_RETURN(glIsBuffer, arg0); } -void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) { - CALL_GL_API(glClipPlanex, plane, equation); + +GLboolean API_ENTRY(glIsEnabled)(GLenum arg0) { + CALL_GL_API_RETURN(glIsEnabled, arg0); +} + +GLboolean API_ENTRY(glIsTexture)(GLuint arg0) { + CALL_GL_API_RETURN(glIsTexture, arg0); +} + +void API_ENTRY(glPointParameterf)(GLenum arg0, GLfloat arg1) { + CALL_GL_API(glPointParameterf, arg0, arg1); +} + +void API_ENTRY(glPointParameterfv)(GLenum arg0, const GLfloat * arg1) { + CALL_GL_API(glPointParameterfv, arg0, arg1); +} + +void API_ENTRY(glPointParameterx)(GLenum arg0, GLfixed arg1) { + CALL_GL_API(glPointParameterx, arg0, arg1); +} + +void API_ENTRY(glPointParameterxv)(GLenum arg0, const GLfixed * arg1) { + CALL_GL_API(glPointParameterxv, arg0, arg1); +} + +void API_ENTRY(glColor4ub)(GLubyte arg0, GLubyte arg1, GLubyte arg2, GLubyte arg3) { + CALL_GL_API(glColor4ub, arg0, arg1, arg2, arg3); +} + +void API_ENTRY(glTexEnvi)(GLenum arg0, GLenum arg1, GLint arg2) { + CALL_GL_API(glTexEnvi, arg0, arg1, arg2); +} + +void API_ENTRY(glTexEnviv)(GLenum arg0, GLenum arg1, const GLint * arg2) { + CALL_GL_API(glTexEnviv, arg0, arg1, arg2); } -void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { - CALL_GL_API(glBindBuffer, target, buffer); + +void API_ENTRY(glTexParameterfv)(GLenum arg0, GLenum arg1, const GLfloat * arg2) { + CALL_GL_API(glTexParameterfv, arg0, arg1, arg2); } -void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { - CALL_GL_API(glBufferData, target, size, data, usage); + +void API_ENTRY(glTexParameteriv)(GLenum arg0, GLenum arg1, const GLint * arg2) { + CALL_GL_API(glTexParameteriv, arg0, arg1, arg2); } -void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { - CALL_GL_API(glBufferSubData, target, offset, size, data); + +void API_ENTRY(glTexParameteri)(GLenum arg0, GLenum arg1, GLint arg2) { + CALL_GL_API(glTexParameteri, arg0, arg1, arg2); } -void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) { - CALL_GL_API(glDeleteBuffers, n, buffers); + +void API_ENTRY(glTexParameterxv)(GLenum arg0, GLenum arg1, const GLfixed * arg2) { + CALL_GL_API(glTexParameterxv, arg0, arg1, arg2); } -void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) { - CALL_GL_API(glGenBuffers, n, buffers); + +void API_ENTRY(glPointSizePointerOES)(GLenum arg0, GLsizei arg1, const GLvoid* arg2) { + CALL_GL_API(glPointSizePointerOES, arg0, arg1, arg2); } -void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) { - CALL_GL_API(glGetBooleanv, pname, params); + +void API_ENTRY(glDrawTexsOES)(GLshort arg0, GLshort arg1, GLshort arg2, GLshort arg3, GLshort arg4) { + CALL_GL_API(glDrawTexsOES, arg0, arg1, arg2, arg3, arg4); } -void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) { - CALL_GL_API(glGetFixedv, pname, params); + +void API_ENTRY(glDrawTexiOES)(GLint arg0, GLint arg1, GLint arg2, GLint arg3, GLint arg4) { + CALL_GL_API(glDrawTexiOES, arg0, arg1, arg2, arg3, arg4); } -void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) { - CALL_GL_API(glGetFloatv, pname, params); + +void API_ENTRY(glDrawTexfOES)(GLfloat arg0, GLfloat arg1, GLfloat arg2, GLfloat arg3, GLfloat arg4) { + CALL_GL_API(glDrawTexfOES, arg0, arg1, arg2, arg3, arg4); } -void API_ENTRY(glGetPointerv)(GLenum pname, void **params) { - CALL_GL_API(glGetPointerv, pname, params); + +void API_ENTRY(glDrawTexxOES)(GLfixed arg0, GLfixed arg1, GLfixed arg2, GLfixed arg3, GLfixed arg4) { + CALL_GL_API(glDrawTexxOES, arg0, arg1, arg2, arg3, arg4); +} + +void API_ENTRY(glDrawTexsvOES)(const GLshort* arg0) { + CALL_GL_API(glDrawTexsvOES, arg0); +} + +void API_ENTRY(glDrawTexivOES)(const GLint* arg0) { + CALL_GL_API(glDrawTexivOES, arg0); +} + +void API_ENTRY(glDrawTexfvOES)(const GLfloat* arg0) { + CALL_GL_API(glDrawTexfvOES, arg0); +} + +void API_ENTRY(glDrawTexxvOES)(const GLfixed* arg0) { + CALL_GL_API(glDrawTexxvOES, arg0); } -void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) { - CALL_GL_API(glGetBufferParameteriv, target, pname, params); + +GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* arg0, GLint* arg1) { + CALL_GL_API_RETURN(glQueryMatrixxOES, arg0, arg1); } -void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) { - CALL_GL_API(glGetClipPlanef, pname, eqn); + +void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum arg0, GLeglImageOES arg1) { + CALL_GL_API(__glEGLImageTargetTexture2DOES, arg0, arg1); } -void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) { - CALL_GL_API(glGetClipPlanex, pname, eqn); + +void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum arg0, GLeglImageOES arg1) { + CALL_GL_API(__glEGLImageTargetRenderbufferStorageOES, arg0, arg1); } -void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetLightxv, light, pname, params); + +void API_ENTRY(glBlendEquationSeparateOES)(GLenum arg0, GLenum arg1) { + CALL_GL_API(glBlendEquationSeparateOES, arg0, arg1); } -void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetLightfv, light, pname, params); + +void API_ENTRY(glBlendFuncSeparateOES)(GLenum arg0, GLenum arg1, GLenum arg2, GLenum arg3) { + CALL_GL_API(glBlendFuncSeparateOES, arg0, arg1, arg2, arg3); } -void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetMaterialxv, face, pname, params); + +void API_ENTRY(glBlendEquationOES)(GLenum arg0) { + CALL_GL_API(glBlendEquationOES, arg0); } -void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetMaterialfv, face, pname, params); + +GLboolean API_ENTRY(glIsRenderbufferOES)(GLuint arg0) { + CALL_GL_API_RETURN(glIsRenderbufferOES, arg0); } -void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetTexEnvfv, env, pname, params); + +void API_ENTRY(glBindRenderbufferOES)(GLenum arg0, GLuint arg1) { + CALL_GL_API(glBindRenderbufferOES, arg0, arg1); } -void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) { - CALL_GL_API(glGetTexEnviv, env, pname, params); + +void API_ENTRY(glDeleteRenderbuffersOES)(GLsizei arg0, const GLuint* arg1) { + CALL_GL_API(glDeleteRenderbuffersOES, arg0, arg1); } -void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetTexEnvxv, env, pname, params); + +void API_ENTRY(glGenRenderbuffersOES)(GLsizei arg0, GLuint* arg1) { + CALL_GL_API(glGenRenderbuffersOES, arg0, arg1); } -void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) { - CALL_GL_API(glGetTexParameterfv, target, pname, params); + +void API_ENTRY(glRenderbufferStorageOES)(GLenum arg0, GLenum arg1, GLsizei arg2, GLsizei arg3) { + CALL_GL_API(glRenderbufferStorageOES, arg0, arg1, arg2, arg3); } -void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) { - CALL_GL_API(glGetTexParameteriv, target, pname, params); + +void API_ENTRY(glGetRenderbufferParameterivOES)(GLenum arg0, GLenum arg1, GLint* arg2) { + CALL_GL_API(glGetRenderbufferParameterivOES, arg0, arg1, arg2); } -void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) { - CALL_GL_API(glGetTexParameterxv, target, pname, params); + +GLboolean API_ENTRY(glIsFramebufferOES)(GLuint arg0) { + CALL_GL_API_RETURN(glIsFramebufferOES, arg0); } -GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { - CALL_GL_API_RETURN(glIsBuffer, buffer); + +void API_ENTRY(glBindFramebufferOES)(GLenum arg0, GLuint arg1) { + CALL_GL_API(glBindFramebufferOES, arg0, arg1); } -GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { - CALL_GL_API_RETURN(glIsEnabled, cap); + +void API_ENTRY(glDeleteFramebuffersOES)(GLsizei arg0, const GLuint* arg1) { + CALL_GL_API(glDeleteFramebuffersOES, arg0, arg1); } -GLboolean API_ENTRY(glIsTexture)(GLuint texture) { - CALL_GL_API_RETURN(glIsTexture, texture); + +void API_ENTRY(glGenFramebuffersOES)(GLsizei arg0, GLuint* arg1) { + CALL_GL_API(glGenFramebuffersOES, arg0, arg1); } -void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) { - CALL_GL_API(glPointParameterf, pname, param); + +GLenum API_ENTRY(glCheckFramebufferStatusOES)(GLenum arg0) { + CALL_GL_API_RETURN(glCheckFramebufferStatusOES, arg0); } -void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) { - CALL_GL_API(glPointParameterfv, pname, params); + +void API_ENTRY(glFramebufferRenderbufferOES)(GLenum arg0, GLenum arg1, GLenum arg2, GLuint arg3) { + CALL_GL_API(glFramebufferRenderbufferOES, arg0, arg1, arg2, arg3); } -void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) { - CALL_GL_API(glPointParameterx, pname, param); + +void API_ENTRY(glFramebufferTexture2DOES)(GLenum arg0, GLenum arg1, GLenum arg2, GLuint arg3, GLint arg4) { + CALL_GL_API(glFramebufferTexture2DOES, arg0, arg1, arg2, arg3, arg4); } -void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) { - CALL_GL_API(glPointParameterxv, pname, params); + +void API_ENTRY(glGetFramebufferAttachmentParameterivOES)(GLenum arg0, GLenum arg1, GLenum arg2, GLint* arg3) { + CALL_GL_API(glGetFramebufferAttachmentParameterivOES, arg0, arg1, arg2, arg3); } -void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { - CALL_GL_API(glColor4ub, red, green, blue, alpha); + +void API_ENTRY(glGenerateMipmapOES)(GLenum arg0) { + CALL_GL_API(glGenerateMipmapOES, arg0); } -void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) { - CALL_GL_API(glTexEnvi, target, pname, param); + +void* API_ENTRY(glMapBufferOES)(GLenum arg0, GLenum arg1) { + CALL_GL_API_RETURN(glMapBufferOES, arg0, arg1); } -void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) { - CALL_GL_API(glTexEnviv, target, pname, params); + +GLboolean API_ENTRY(glUnmapBufferOES)(GLenum arg0) { + CALL_GL_API_RETURN(glUnmapBufferOES, arg0); } -void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) { - CALL_GL_API(glTexParameterfv, target, pname, params); +void API_ENTRY(glGetBufferPointervOES)(GLenum arg0, GLenum arg1, void** arg2) { + CALL_GL_API(glGetBufferPointervOES, arg0, arg1, arg2); } -void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) { - CALL_GL_API(glTexParameteriv, target, pname, params); +void API_ENTRY(glCurrentPaletteMatrixOES)(GLuint arg0) { + CALL_GL_API(glCurrentPaletteMatrixOES, arg0); } -void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { - CALL_GL_API(glTexParameteri, target, pname, param); +void API_ENTRY(glLoadPaletteFromModelViewMatrixOES)(void) { + CALL_GL_API(glLoadPaletteFromModelViewMatrixOES); } -void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) { - CALL_GL_API(glTexParameterxv, target, pname, params); + +void API_ENTRY(glMatrixIndexPointerOES)(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3) { + CALL_GL_API(glMatrixIndexPointerOES, arg0, arg1, arg2, arg3); } -void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) { - CALL_GL_API(glPointSizePointerOES, type, stride, pointer); + +void API_ENTRY(glWeightPointerOES)(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3) { + CALL_GL_API(glWeightPointerOES, arg0, arg1, arg2, arg3); } -// Extensions -void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { - CALL_GL_API(glDrawTexsOES, x, y, z, w, h); +void API_ENTRY(glTexGenfOES)(GLenum arg0, GLenum arg1, GLfloat arg2) { + CALL_GL_API(glTexGenfOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) { - CALL_GL_API(glDrawTexiOES, x, y, z, w, h); + +void API_ENTRY(glTexGenfvOES)(GLenum arg0, GLenum arg1, const GLfloat * arg2) { + CALL_GL_API(glTexGenfvOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) { - CALL_GL_API(glDrawTexfOES, x, y, z, w, h); + +void API_ENTRY(glTexGeniOES)(GLenum arg0, GLenum arg1, GLint arg2) { + CALL_GL_API(glTexGeniOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { - CALL_GL_API(glDrawTexxOES, x, y, z, w, h); + +void API_ENTRY(glTexGenivOES)(GLenum arg0, GLenum arg1, const GLint * arg2) { + CALL_GL_API(glTexGenivOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) { - CALL_GL_API(glDrawTexsvOES, coords); + +void API_ENTRY(glTexGenxOES)(GLenum arg0, GLenum arg1, GLfixed arg2) { + CALL_GL_API(glTexGenxOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexivOES)(const GLint* coords) { - CALL_GL_API(glDrawTexivOES, coords); + +void API_ENTRY(glTexGenxvOES)(GLenum arg0, GLenum arg1, const GLfixed * arg2) { + CALL_GL_API(glTexGenxvOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) { - CALL_GL_API(glDrawTexfvOES, coords); + +void API_ENTRY(glGetTexGenfvOES)(GLenum arg0, GLenum arg1, GLfloat * arg2) { + CALL_GL_API(glGetTexGenfvOES, arg0, arg1, arg2); } -void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) { - CALL_GL_API(glDrawTexxvOES, coords); + +void API_ENTRY(glGetTexGenivOES)(GLenum arg0, GLenum arg1, GLint * arg2) { + CALL_GL_API(glGetTexGenivOES, arg0, arg1, arg2); } -GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) { - CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); + +void API_ENTRY(glGetTexGenxvOES)(GLenum arg0, GLenum arg1, GLfixed * arg2) { + CALL_GL_API(glGetTexGenxvOES, arg0, arg1, arg2); } + diff --git a/opengl/libs/egl_entries.in b/opengl/libs/egl_entries.in index 33b4c65..3b4551b 100644 --- a/opengl/libs/egl_entries.in +++ b/opengl/libs/egl_entries.in @@ -43,3 +43,10 @@ EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGL /* EGL 1.3 */ /* EGL 1.4 */ + +/* EGL_EGLEXT_VERSION 3 */ + +EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint *) +EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *) +EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR) diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h index 62ce3fc..4e0c7bf 100644 --- a/opengl/libs/egl_impl.h +++ b/opengl/libs/egl_impl.h @@ -20,6 +20,7 @@ #include <ctype.h> #include <EGL/egl.h> +#include <EGL/eglext.h> // ---------------------------------------------------------------------------- namespace android { @@ -36,6 +37,8 @@ struct egl_connection_t int unavailable; }; +EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image); + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/opengl/libs/gl_entries.in b/opengl/libs/gl_entries.in index b97e8fe..4e8f828 100644 --- a/opengl/libs/gl_entries.in +++ b/opengl/libs/gl_entries.in @@ -15,30 +15,30 @@ GL_ENTRY(void, glColorMask, GLboolean, GLboolean, GLboolean, GLboolean) GL_ENTRY(void, glDepthMask, GLboolean) GL_ENTRY(void, glStencilMask, GLuint) GL_ENTRY(void, glDepthFunc, GLenum) -GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar) -GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar) -GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units) -GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units) -GL_ENTRY(void, glLogicOp, GLenum opcode) -GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref) -GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref) -GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor) -GL_ENTRY(void, glClear, GLbitfield mask) -GL_ENTRY(void, glClearColor, GLclampf r, GLclampf g, GLclampf b, GLclampf a) -GL_ENTRY(void, glClearColorx, GLclampx r, GLclampx g, GLclampx b, GLclampx a) -GL_ENTRY(void, glClearDepthf, GLclampf depth) -GL_ENTRY(void, glClearDepthx, GLclampx depth) -GL_ENTRY(void, glClearStencil, GLint s) +GL_ENTRY(void, glDepthRangef, GLclampf, GLclampf) +GL_ENTRY(void, glDepthRangex, GLclampx, GLclampx) +GL_ENTRY(void, glPolygonOffset, GLfloat, GLfloat) +GL_ENTRY(void, glPolygonOffsetx, GLfixed, GLfixed) +GL_ENTRY(void, glLogicOp, GLenum) +GL_ENTRY(void, glAlphaFuncx, GLenum, GLclampx) +GL_ENTRY(void, glAlphaFunc, GLenum, GLclampf) +GL_ENTRY(void, glBlendFunc, GLenum, GLenum) +GL_ENTRY(void, glClear, GLbitfield) +GL_ENTRY(void, glClearColor, GLclampf, GLclampf, GLclampf, GLclampf) +GL_ENTRY(void, glClearColorx, GLclampx, GLclampx, GLclampx, GLclampx) +GL_ENTRY(void, glClearDepthf, GLclampf) +GL_ENTRY(void, glClearDepthx, GLclampx) +GL_ENTRY(void, glClearStencil, GLint) GL_ENTRY(void, glPointSize, GLfloat) GL_ENTRY(void, glPointSizex, GLfixed) -GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert) -GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert) -GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask) -GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass) -GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height) -GL_ENTRY(void, glHint, GLenum, GLenum mode) -GL_ENTRY(void, glLineWidth, GLfloat width) -GL_ENTRY(void, glLineWidthx, GLfixed width) +GL_ENTRY(void, glSampleCoverage, GLclampf, GLboolean) +GL_ENTRY(void, glSampleCoveragex, GLclampx, GLboolean) +GL_ENTRY(void, glStencilFunc, GLenum, GLint, GLuint) +GL_ENTRY(void, glStencilOp, GLenum, GLenum, GLenum) +GL_ENTRY(void, glScissor, GLint, GLint, GLsizei, GLsizei) +GL_ENTRY(void, glHint, GLenum, GLenum) +GL_ENTRY(void, glLineWidth, GLfloat) +GL_ENTRY(void, glLineWidthx, GLfixed) GL_ENTRY(void, glShadeModel, GLenum) GL_ENTRY(void, glLightModelf, GLenum, GLfloat) GL_ENTRY(void, glLightModelfv, GLenum, const GLfloat *) @@ -63,12 +63,12 @@ GL_ENTRY(void, glTexCoordPointer, GLint, GLenum, GLsizei, const GLvoid *) GL_ENTRY(void, glEnableClientState, GLenum) GL_ENTRY(void, glDisableClientState, GLenum) GL_ENTRY(void, glClientActiveTexture, GLenum) -GL_ENTRY(void, glDrawArrays, GLenum, GLint first, GLsizei) +GL_ENTRY(void, glDrawArrays, GLenum, GLint, GLsizei) GL_ENTRY(void, glDrawElements, GLenum, GLsizei, GLenum, const GLvoid *) GL_ENTRY(void, glLoadIdentity, void) GL_ENTRY(void, glLoadMatrixf, const GLfloat*) GL_ENTRY(void, glLoadMatrixx, const GLfixed*) -GL_ENTRY(void, glMatrixMode, GLenum mode) +GL_ENTRY(void, glMatrixMode, GLenum) GL_ENTRY(void, glMultMatrixf, const GLfloat*) GL_ENTRY(void, glMultMatrixx, const GLfixed*) GL_ENTRY(void, glPopMatrix, void) @@ -87,7 +87,7 @@ GL_ENTRY(void, glViewport, GLint, GLint, GLsizei, GLsizei) GL_ENTRY(void, glActiveTexture, GLenum) GL_ENTRY(void, glBindTexture, GLenum, GLuint) GL_ENTRY(void, glGenTextures, GLsizei, GLuint*) -GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *) +GL_ENTRY(void, glDeleteTextures, GLsizei, const GLuint *) GL_ENTRY(void, glMultiTexCoord4f, GLenum, GLfloat, GLfloat, GLfloat, GLfloat) GL_ENTRY(void, glMultiTexCoord4x, GLenum, GLfixed, GLfixed, GLfixed, GLfixed) GL_ENTRY(void, glPixelStorei, GLenum, GLint) @@ -106,8 +106,8 @@ GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, G GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *) // 1.1 additions -GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat*) -GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed*) +GL_ENTRY(void, glClipPlanef, GLenum, const GLfloat*) +GL_ENTRY(void, glClipPlanex, GLenum, const GLfixed*) GL_ENTRY(void, glBindBuffer, GLenum, GLuint) GL_ENTRY(void, glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum) GL_ENTRY(void, glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*) @@ -144,7 +144,7 @@ GL_ENTRY(void, glTexParameterfv, GLenum, GLenum, const GLfloat *) GL_ENTRY(void, glTexParameteriv, GLenum, GLenum, const GLint *) GL_ENTRY(void, glTexParameteri, GLenum, GLenum, GLint) GL_ENTRY(void, glTexParameterxv, GLenum, GLenum, const GLfixed *) -GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid*) +GL_ENTRY(void, glPointSizePointerOES, GLenum, GLsizei, const GLvoid*) // Extensions GL_ENTRY(void, glDrawTexsOES, GLshort, GLshort, GLshort, GLshort, GLshort) @@ -155,5 +155,40 @@ GL_ENTRY(void, glDrawTexsvOES, const GLshort*) GL_ENTRY(void, glDrawTexivOES, const GLint*) GL_ENTRY(void, glDrawTexfvOES, const GLfloat*) GL_ENTRY(void, glDrawTexxvOES, const GLfixed*) -GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed* mantissa, GLint* exponent) - +GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed*, GLint*) +GL_ENTRY(void, __glEGLImageTargetTexture2DOES, GLenum, GLeglImageOES) +GL_ENTRY(void, __glEGLImageTargetRenderbufferStorageOES, GLenum, GLeglImageOES) +GL_ENTRY(void, glBlendEquationSeparateOES, GLenum, GLenum) +GL_ENTRY(void, glBlendFuncSeparateOES, GLenum, GLenum, GLenum, GLenum) +GL_ENTRY(void, glBlendEquationOES, GLenum) +GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint) +GL_ENTRY(void, glBindRenderbufferOES, GLenum, GLuint) +GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei, const GLuint*) +GL_ENTRY(void, glGenRenderbuffersOES, GLsizei, GLuint*) +GL_ENTRY(void, glRenderbufferStorageOES, GLenum, GLenum, GLsizei, GLsizei) +GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum, GLenum, GLint*) +GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint) +GL_ENTRY(void, glBindFramebufferOES, GLenum, GLuint) +GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei, const GLuint*) +GL_ENTRY(void, glGenFramebuffersOES, GLsizei, GLuint*) +GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum) +GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum, GLenum, GLenum, GLuint) +GL_ENTRY(void, glFramebufferTexture2DOES, GLenum, GLenum, GLenum, GLuint, GLint) +GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum, GLenum, GLenum, GLint*) +GL_ENTRY(void, glGenerateMipmapOES, GLenum) +GL_ENTRY(void*, glMapBufferOES, GLenum, GLenum) +GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum) +GL_ENTRY(void, glGetBufferPointervOES, GLenum, GLenum, void**) +GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint) +GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void) +GL_ENTRY(void, glMatrixIndexPointerOES, GLint, GLenum, GLsizei, const GLvoid *) +GL_ENTRY(void, glWeightPointerOES, GLint, GLenum, GLsizei, const GLvoid *) +GL_ENTRY(void, glTexGenfOES, GLenum, GLenum, GLfloat) +GL_ENTRY(void, glTexGenfvOES, GLenum, GLenum, const GLfloat *) +GL_ENTRY(void, glTexGeniOES, GLenum, GLenum, GLint) +GL_ENTRY(void, glTexGenivOES, GLenum, GLenum, const GLint *) +GL_ENTRY(void, glTexGenxOES, GLenum, GLenum, GLfixed) +GL_ENTRY(void, glTexGenxvOES, GLenum, GLenum, const GLfixed *) +GL_ENTRY(void, glGetTexGenfvOES, GLenum, GLenum, GLfloat *) +GL_ENTRY(void, glGetTexGenivOES, GLenum, GLenum, GLint *) +GL_ENTRY(void, glGetTexGenxvOES, GLenum, GLenum, GLfixed *) diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h index 63fb017..392724f 100644 --- a/opengl/libs/hooks.h +++ b/opengl/libs/hooks.h @@ -22,9 +22,10 @@ #include <errno.h> #include <EGL/egl.h> +#include <EGL/eglext.h> #include <GLES/gl.h> +#include <GLES/glext.h> -#define GL_LOGGER 0 #if !defined(__arm__) #define USE_SLOW_BINDING 1 #else @@ -35,7 +36,7 @@ #define MAX_NUMBER_OF_GL_EXTENSIONS 32 -#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER && __OPTIMIZE__ +#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && __OPTIMIZE__ #define USE_FAST_TLS_KEY 1 #else #define USE_FAST_TLS_KEY 0 @@ -55,7 +56,10 @@ const unsigned int NUM_DISPLAYS = 1; enum { IMPL_HARDWARE = 0, IMPL_SOFTWARE, - IMPL_CONTEXT_LOST, + + IMPL_NUM_DRIVERS_IMPLEMENTATIONS, + + IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS, IMPL_NO_CONTEXT, IMPL_NUM_IMPLEMENTATIONS diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen new file mode 100755 index 0000000..0333294 --- /dev/null +++ b/opengl/libs/tools/glapigen @@ -0,0 +1,51 @@ +#! /usr/bin/perl + +use strict; + +my $lineNum = 0; +while (my $line = <>) { + $lineNum += 1; + next if $line =~ /^\//; + next if $line =~ /^#/; + next if $line =~ /^\s*$/; + if ($line !~ /^GL_ENTRY\(([^,]+),\s*([^,]+),\s*([^)]+)\)/) { + printf STDERR "Cannot parse line number $lineNum:\n$line"; + next; + } + my $type = $1; + my $name = $2; + my $args = $3; + + printf("%s API_ENTRY(%s)(", $type, $name); + my @args = split ',', $args; + + my $len = scalar(@args); + for (my $num = 0; $num < $len; $num++) { + print ", " if $num > 0; + my $arg = $args[$num]; + if ($arg =~ /([^]]+)(\[[^]]\])/) { + my $argtype = $1; + my $array = $2; + printf("%s arg%d%s", $argtype, $num, $array); + } else { + if ($arg eq "void") { + printf("void"); + } else { + printf("%s arg%d", $arg, $num); + } + } + } + printf(") {\n"); + if ($type eq "void") { + printf(" CALL_GL_API(%s", $name); + } else { + printf(" CALL_GL_API_RETURN(%s", $name); + } + for (my $num = 0; $num < $len; $num++) { + if ($args[$num] ne "void") { + print ", "; + printf("arg%d", $num); + } + } + printf(");\n}\n\n"); +} diff --git a/opengl/tests/copybits/Android.mk b/opengl/tests/copybits/Android.mk new file mode 100644 index 0000000..d5ded42 --- /dev/null +++ b/opengl/tests/copybits/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + copybits.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libEGL \ + libGLESv1_CM \ + libui + +LOCAL_MODULE:= test-opengl-copybits + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) + diff --git a/opengl/tests/copybits/copybits.cpp b/opengl/tests/copybits/copybits.cpp new file mode 100644 index 0000000..ff17cc9 --- /dev/null +++ b/opengl/tests/copybits/copybits.cpp @@ -0,0 +1,752 @@ +// Test software OpenGL hardware accelleration using copybits. + +#define LOG_TAG "copybits_test" + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <ui/PixelFormat.h> + +#include <cutils/log.h> +#include <cutils/native_handle.h> + +#include <utils/Atomic.h> + +#include <private/ui/SharedState.h> + +#include <hardware/gralloc.h> +#include <hardware/hardware.h> + +#define EGL_EGLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <GLES/gl.h> +#include <GLES/glext.h> + +extern "C" EGLNativeWindowType android_createDisplaySurface(void); + +using namespace android; + +EGLDisplay eglDisplay; +EGLSurface eglSurface; +EGLContext eglContext; +GLuint texture; + +hw_module_t const* gralloc_module; +alloc_device_t *sAllocDev; + +#define FIXED_ONE 0x10000 + +int init_gl_surface(); +void free_gl_surface(); +void init_scene(); + +int create_physical_texture(); +int readTimer(); + +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== + +class NativeBuffer; + +class Buffer : public android_native_buffer_t, + public LightRefBase<Buffer> +{ +public: + + // creates w * h buffer + Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage); + + // return status + status_t initCheck() const; + + + uint32_t getWidth() const { return mWidth; } + uint32_t getHeight() const { return mHeight; } + uint32_t getStride() const { return mStride; } + uint32_t getUsage() const { return mUsage; } + PixelFormat getPixelFormat() const { return mFormat; } + buffer_handle_t getHandle() const { return mBufferHandle; } + + android_native_buffer_t* getNativeBuffer() const; + + void setPixel(int x, int y, int r, int g, int b, int a); + +private: + friend class LightRefBase<Buffer>; + Buffer(const Buffer& rhs); + ~Buffer(); + Buffer& operator = (const Buffer& rhs); + const Buffer& operator = (const Buffer& rhs) const; + + status_t initSize(uint32_t w, uint32_t h); + + static void incRef(android_native_base_t* buffer); + static void decRef(android_native_base_t* buffer); + static int getHandlePriv(android_native_buffer_t const * buffer, + buffer_handle_t* handle); + + buffer_handle_t mBufferHandle; + ssize_t mInitCheck; + + uint32_t mWidth; + uint32_t mHeight; + uint32_t mStride; + uint32_t mVStride; + PixelFormat mFormat; + void* mData; + uint32_t mUsage; +}; + +Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage) + : mBufferHandle(0), mInitCheck(NO_INIT), + mWidth(0), mHeight(0), mStride(0), mVStride(0), mFormat(format), mData(0), + mUsage(usage) +{ + common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + common.version = sizeof(android_native_buffer_t); + common.incRef = incRef; + common.decRef = decRef; + android_native_buffer_t::getHandle = getHandlePriv; + if (w>0 && h>0) { + mInitCheck = initSize(w, h); + } +} + +Buffer::~Buffer() +{ + if (mBufferHandle) { + + gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module; + mod->unmap(mod, mBufferHandle); + + sAllocDev->free(sAllocDev, mBufferHandle); + } +} + +void Buffer::incRef(android_native_base_t* buffer) { + Buffer* self = static_cast<Buffer*>( + reinterpret_cast<android_native_buffer_t *>(buffer)); + self->incStrong(self); +} + +void Buffer::decRef(android_native_base_t* buffer) { + Buffer* self = static_cast<Buffer*>( + reinterpret_cast<android_native_buffer_t *>(buffer)); + self->decStrong(self); +} + +int Buffer::getHandlePriv(android_native_buffer_t const * buffer, + buffer_handle_t* handle) { + Buffer const * self = static_cast<Buffer const *>(buffer); + *handle = self->getHandle(); + return 0; +} + +status_t Buffer::initCheck() const { + return mInitCheck; +} + +android_native_buffer_t* Buffer::getNativeBuffer() const +{ + Buffer* that = const_cast<Buffer*>(this); + that->android_native_buffer_t::width = mWidth; + that->android_native_buffer_t::height = mHeight; + that->android_native_buffer_t::stride = mStride; + that->android_native_buffer_t::format = mFormat; + that->android_native_buffer_t::usage = mUsage; + that->android_native_buffer_t::bits = mData; + return static_cast<android_native_buffer_t*>(that); +} + +status_t Buffer::initSize(uint32_t w, uint32_t h) +{ + status_t err = NO_ERROR; + + int32_t stride; + err = sAllocDev->alloc(sAllocDev, w, h, mFormat, mUsage, &mBufferHandle, &stride); + + if (err == NO_ERROR) { + void* addr = 0; + gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module; + err = mod->map(mod, mBufferHandle, &addr); + if (err == NO_ERROR) { + mData = addr; + mWidth = w; + mHeight = h; + mStride = stride; + mVStride = 0; + } + } + + return err; +} + +void Buffer::setPixel(int x, int y, int r, int g, int b, int a) { + if (x < 0 || (unsigned int) x >= mWidth + || y < 0 || (unsigned int) y >= mHeight) { + // clipped + return; + } + int index = mStride * y + x; + switch (mFormat) { + case HAL_PIXEL_FORMAT_RGB_565: { + unsigned short val = (unsigned short) ( + ((0x1f & (r >> 3)) << 11) + | ((0x3f & (g >> 2)) << 5) + | (0x1f & (b >> 3))); + ((unsigned short*) mData)[index]= val; + } + break; + case HAL_PIXEL_FORMAT_RGBA_8888: { // ABGR + unsigned int val = (unsigned int) + (((a & 0xff) << 24) + | ((b & 0xff) << 16) + | ((g & 0xff) << 8) + | (r & 0xff)); + ((unsigned int*) mData)[index] = val; + } + break; + default: + // Unsupported pixel format + break; + } +} + + +static void gluLookAt(float eyeX, float eyeY, float eyeZ, + float centerX, float centerY, float centerZ, float upX, float upY, + float upZ) +{ + // See the OpenGL GLUT documentation for gluLookAt for a description + // of the algorithm. We implement it in a straightforward way: + + float fx = centerX - eyeX; + float fy = centerY - eyeY; + float fz = centerZ - eyeZ; + + // Normalize f + float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz); + fx *= rlf; + fy *= rlf; + fz *= rlf; + + // Normalize up + float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ); + upX *= rlup; + upY *= rlup; + upZ *= rlup; + + // compute s = f x up (x means "cross product") + + float sx = fy * upZ - fz * upY; + float sy = fz * upX - fx * upZ; + float sz = fx * upY - fy * upX; + + // compute u = s x f + float ux = sy * fz - sz * fy; + float uy = sz * fx - sx * fz; + float uz = sx * fy - sy * fx; + + float m[16] ; + m[0] = sx; + m[1] = ux; + m[2] = -fx; + m[3] = 0.0f; + + m[4] = sy; + m[5] = uy; + m[6] = -fy; + m[7] = 0.0f; + + m[8] = sz; + m[9] = uz; + m[10] = -fz; + m[11] = 0.0f; + + m[12] = 0.0f; + m[13] = 0.0f; + m[14] = 0.0f; + m[15] = 1.0f; + + glMultMatrixf(m); + glTranslatef(-eyeX, -eyeY, -eyeZ); +} + +int init_gralloc() { + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gralloc_module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + + if (err == 0) { + gralloc_open(gralloc_module, &sAllocDev); + } + return err; +} + +int init_gl_surface(void) +{ + EGLint numConfigs = 1; + EGLConfig myConfig = {0}; + EGLint attrib[] = + { + EGL_DEPTH_SIZE, 16, + EGL_NONE + }; + + printf("init_gl_surface\n"); + if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY ) + { + printf("eglGetDisplay failed\n"); + return 0; + } + + if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE ) + { + printf("eglInitialize failed\n"); + return 0; + } + + if ( eglChooseConfig(eglDisplay, attrib, &myConfig, 1, &numConfigs) != EGL_TRUE ) + { + printf("eglChooseConfig failed\n"); + return 0; + } + + if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig, + android_createDisplaySurface(), 0)) == EGL_NO_SURFACE ) + { + printf("eglCreateWindowSurface failed\n"); + return 0; + } + + if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT ) + { + printf("eglCreateContext failed\n"); + return 0; + } + + if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE ) + { + printf("eglMakeCurrent failed\n"); + return 0; + } + + return 1; +} + +void free_gl_surface(void) +{ + if (eglDisplay != EGL_NO_DISPLAY) + { + eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT ); + eglDestroyContext( eglDisplay, eglContext ); + eglDestroySurface( eglDisplay, eglSurface ); + eglTerminate( eglDisplay ); + eglDisplay = EGL_NO_DISPLAY; + } +} + +void init_scene(void) +{ + glDisable(GL_DITHER); + glEnable(GL_CULL_FACE); + float ratio = 320.0f / 480.0f; + glViewport(0, 0, 320, 480); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustumf(-ratio, ratio, -1, 1, 1, 10); + + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + gluLookAt( + 0, 0, 3, // eye + 0, 0, 0, // center + 0, 1, 0); // up + + glEnable(GL_TEXTURE_2D); +} + +// #define USE_ALPHA_COLOR + +#define USE_GL_REPLACE +// #define USE_GL_MODULATE + +// #define USE_BLEND + +#define USE_565 +// #define USE_8888 + +// #define USE_NEAREST +#define USE_LINEAR + +#define USE_SCALE + +void setSmoothGradient(Buffer* bufferObject) { + int pixels = bufferObject->getHeight() * bufferObject->getWidth(); + int step = 0; + for (unsigned int y = 0; y < bufferObject->getHeight(); y++) { + for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) { + int grey = step * 255 / pixels; + bufferObject->setPixel(x, y, grey, grey, grey, 255); + ++step; + } + } +} + +void setSmoothAlphaGradient(Buffer* bufferObject) { + int pixels = bufferObject->getHeight() * bufferObject->getWidth(); + int step = 0; + for (unsigned int y = 0; y < bufferObject->getHeight(); y++) { + for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) { + int grey = step * 255 / pixels; + bufferObject->setPixel(x, y, 255, 255, 255, grey); + ++step; + } + } +} + +void setOrientedCheckerboard(Buffer* bufferObject) { + bufferObject->setPixel(0, 0, 0, 0, 0, 255); + for(unsigned int x = 1; x < bufferObject->getWidth() ; x++) { + bufferObject->setPixel(x, 0, 0, 255, 0, 255); + } + for (unsigned int y = 1; y < bufferObject->getHeight(); y++) { + for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) { + if ((x ^ y ) & 1) { + bufferObject->setPixel(x, y, 255, 255, 255, 255); + } else { + bufferObject->setPixel(x, y, 255, 0, 0, 255); + } + } + } +} + +int create_physical_texture(unsigned int w, unsigned int h) +{ + +#ifdef USE_565 + PixelFormat format = HAL_PIXEL_FORMAT_RGB_565; +#else + PixelFormat format = HAL_PIXEL_FORMAT_RGBA_8888; +#endif + int usage = GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_HW_2D; /* This is the key to allocating the texture in pmem. */ + int32_t stride; + buffer_handle_t handle; + + // Allocate the hardware buffer + Buffer* bufferObject = new Buffer(w, h, format, usage); + + android_native_buffer_t* buffer = bufferObject->getNativeBuffer(); + + buffer->common.incRef(&buffer->common); + + // create the new EGLImageKHR + EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_NONE }; + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)buffer, attrs); + if (image == EGL_NO_IMAGE_KHR) { + printf("Could not create an image %d\n", eglGetError()); + return -1; + } + + if (buffer->bits == NULL) { + printf("No bits allocated for image.\n"); + return -2; + } + + setOrientedCheckerboard(bufferObject); + // setSmoothGradient(bufferObject); + // setSmoothAlphaGradient(bufferObject); + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); +#ifdef USE_LINEAR + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#elif defined(USE_NEAREST) + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +#endif + +#ifdef USE_GL_REPLACE + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +#elif defined(USE_GL_MODULATE) + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#endif + +#ifdef USE_ALPHA_COLOR + glColor4f(1.0f, 1.0f, 1.0f, 0.4f); +#else + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +#endif + +#ifdef USE_BLEND + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#endif + return 0; +} + +static const int SCALE_COUNT = 12; + +int scale(int base, int factor) { + static const float kTable[SCALE_COUNT] = { + 0.1f, 0.25f, 0.5f, 0.75f, 1.0f, + 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 5.0f + }; + return base * kTable[factor]; +} + +class Timer { + struct timeval first; + double elapsedSeconds; + +public: + Timer() {} + void start() { + gettimeofday(&first, NULL); + } + + void stop() { + struct timeval second, + elapsed; + gettimeofday(&second, NULL); + + if (first.tv_usec > second.tv_usec) { + second.tv_usec += 1000000; + second.tv_sec--; + } + + elapsedSeconds = (second.tv_sec - first.tv_sec) + + (second.tv_usec - first.tv_usec) / 1000000.0; + } + + double getElapsedSeconds() { + return elapsedSeconds; + } + + double getElapsedMs() { + return elapsedSeconds* 1000.0f; + } +}; + +int testTime() +{ + static const int WIDTH = 320; + static const int HEIGHT = 480; + static const int SCALE = 8; + + if (create_physical_texture(WIDTH, HEIGHT) != 0) { + return -1; + } + // Need to do a dummy eglSwapBuffers first. Don't know why. + glClearColor(0.4, 1.0, 0.4, 0.4); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + eglSwapBuffers(eglDisplay, eglSurface); + + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + +#if defined(USE_SCALE) + static const int scaleOffset = 0; +#else + static const int scaleOffset = 1; +#endif + printf("ms\n"); + for(int j = 0; j < SCALE; j++) { + int w = WIDTH >> (j + scaleOffset); + int h = HEIGHT >> j; + int cropRect[4] = {0,h,w,-h}; // Left bottom width height. Width and Height can be neg to flip. + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); + Timer timer; + timer.start(); + + int copyCount = 1000; + for (int i = 0; i < copyCount; i++) { + glDrawTexiOES(0, 0, 0, w, h); + } + + timer.stop(); + printf("%g\n", timer.getElapsedMs() / copyCount); + } + + eglSwapBuffers(eglDisplay, eglSurface); + return 0; +} + +int testStretch() +{ + static const int WIDTH = 8; + static const int HEIGHT = 8; + + if (create_physical_texture(WIDTH, HEIGHT) != 0) { + return -1; + } + // Need to do a dummy eglSwapBuffers first. Don't know why. + glClearColor(0.4, 1.0, 0.4, 0.4); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + eglSwapBuffers(eglDisplay, eglSurface); + + int cropRect[4] = {0,HEIGHT,WIDTH,-HEIGHT}; // Left bottom width height. Width and Height can be neg to flip. + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); + + for(int frame = 0; frame < 2; frame++) { + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + int baseX = 10; + for (int x = 0; x < SCALE_COUNT; x++) { + int baseY = 10; + int width = scale(WIDTH, x); + for (int y = 0; y < SCALE_COUNT; y++) { + int height = scale(HEIGHT, y); + glDrawTexxOES(baseX << 16, baseY << 16, 0, width << 16, height << 16); + baseY += height + 10; + } + baseX += width + 10; + } + + eglSwapBuffers(eglDisplay, eglSurface); + } + return 0; +} + +int testRot90() +{ + static const int WIDTH = 8; + static const int HEIGHT = 8; + + if (create_physical_texture(WIDTH, HEIGHT) != 0) { + return -1; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrthof(0, 320, 480, 0, 0, 1); + + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + + // Need to do a dummy eglSwapBuffers first. Don't know why. + glClearColor(0.4, 0.4, 0.4, 0.4); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + eglSwapBuffers(eglDisplay, eglSurface); + + glEnable(GL_TEXTURE_2D); + 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_MIN_FILTER, GL_LINEAR); + glColor4x(0x10000, 0x10000, 0x10000, 0x10000); + glDisable(GL_BLEND); + glShadeModel(GL_FLAT); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + + for(int frame = 0; frame < 2; frame++) { + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + int baseX = 10; + for (int x = 0; x < SCALE_COUNT; x++) { + int baseY = 10; + int width = scale(WIDTH, x); + for (int y = 0; y < SCALE_COUNT; y++) { + int height = scale(HEIGHT, y); + + // Code copied from SurfaceFlinger LayerBase.cpp + + const GLfixed texCoords[4][2] = { + { 0, 0 }, + { 0, 0x10000 }, + { 0x10000, 0x10000 }, + { 0x10000, 0 } + }; + + GLfixed fx = baseX << 16; + GLfixed fy = baseY << 16; + GLfixed fw = width << 16; + GLfixed fh = height << 16; + + /* + * Vertex pattern: + * (2)--(3) + * |\ | + * | \ | + * | \ | + * | \| + * (1)--(0) + * + */ + + const GLfixed vertices[4][2] = { + {fx + fw, fy}, + {fx, fy}, + {fx, fy + fh}, + {fx + fw, fy + fh} + }; + + static const bool rotate90 = true; + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FIXED, 0, vertices); + glTexCoordPointer(2, GL_FIXED, 0, texCoords); + + LOGW("testRot90 %d, %d %d, %d", baseX, baseY, width, height); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + baseY += height + 10; + } + baseX += width + 10; + } + + eglSwapBuffers(eglDisplay, eglSurface); + } + return 0; +} + +int main(int argc, char **argv) +{ + + int q; + int start, end; + + if (init_gralloc()) { + printf("gralloc initialization failed - exiting\n"); + return 0; + } + + printf("Initializing EGL...\n"); + + if(!init_gl_surface()) + { + printf("GL initialisation failed - exiting\n"); + return 0; + } + + init_scene(); + + printf("Start test...\n"); + // testTime(); + // testStretch(); + testRot90(); + free_gl_surface(); + + return 0; +} |