android graphic(2)—EGL和OpenGL ES
2016-01-17 15:32
561 查看
Android的本地窗口
FramebufferNativeWindow
Surface
前面提到android EGL库的主要作用就是将OpenGL ES和本地窗口系统结合起来。OpenGL ES就像是一个打印机,各个厂商打印机的内部实现不同(不同的OpenGL ES的实现,软件、硬件等,实现的库由EGL加载),但是只要打印的文档内容相同,按下打印键,其输出的结果都是相同的。当然打印机可以在不同种类的纸张上打印,A4,A5或者牛皮纸、塑料纸等等,打印机对这些都需要支持。OpenGL ES和打印机一样,需要兼容windows、塞班、android等多个不同的系统,所以它的实现是平台无关的,而windows、android等系统需要给OpenGL ES提供纸,这个纸就是本地窗口,而不同系统的实现肯定是不同的。打印机打印的最终内容需要呈现在纸上,对软件来说本地窗口里面肯定有buffer的存在来保存OpenGL ES画的图。
2016/03/25 注:android 4.4中已经不使用FramebufferNativeWindow了,而是使用FramebufferSurface和hwcomposer去做composer。
我们需要两种本地窗口,一种是面对app的,一种是面对SurfaceFlinger。那么本地窗口在android中到底是什么?我们从EGL函数的调用开始,在eglCreateWindowSurface函数中,有个和平台无关的结构体为NativeWindowType,
而
从下面的定义可以看到,在系统为android的宏下,本地窗口其实为ANativeWindow。
下面是ANativeWindow结构体,里面有一组函数指针,我们能够猜到,两个本地窗口都是继承了ANativeWindow,然后对函数进行赋值,“实现协议”。
最终找到的两个本地窗口为FramebufferNativeWindow和Surface。
FramebufferNativeWindow
Surface
前面提到android EGL库的主要作用就是将OpenGL ES和本地窗口系统结合起来。OpenGL ES就像是一个打印机,各个厂商打印机的内部实现不同(不同的OpenGL ES的实现,软件、硬件等,实现的库由EGL加载),但是只要打印的文档内容相同,按下打印键,其输出的结果都是相同的。当然打印机可以在不同种类的纸张上打印,A4,A5或者牛皮纸、塑料纸等等,打印机对这些都需要支持。OpenGL ES和打印机一样,需要兼容windows、塞班、android等多个不同的系统,所以它的实现是平台无关的,而windows、android等系统需要给OpenGL ES提供纸,这个纸就是本地窗口,而不同系统的实现肯定是不同的。打印机打印的最终内容需要呈现在纸上,对软件来说本地窗口里面肯定有buffer的存在来保存OpenGL ES画的图。
2016/03/25 注:android 4.4中已经不使用FramebufferNativeWindow了,而是使用FramebufferSurface和hwcomposer去做composer。
Android的本地窗口
上面提到,如果需要使用OpenGL ES就需要本地窗口的加入,而在前面文章中提到有两处使用OpenGL ES的地方:一是上层的3D绘图,二是SurfaceFlinger对layer的合成(先不考虑Canvas和overlay)。那么我们可以想象下面这幅图画:我们需要两种本地窗口,一种是面对app的,一种是面对SurfaceFlinger。那么本地窗口在android中到底是什么?我们从EGL函数的调用开始,在eglCreateWindowSurface函数中,有个和平台无关的结构体为NativeWindowType,
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) { return createWindowSurface(dpy, config, window, attrib_list); }
而
typedef EGLNativeWindowType NativeWindowType;
从下面的定义可以看到,在系统为android的宏下,本地窗口其实为ANativeWindow。
#elif defined(__ANDROID__) || defined(ANDROID) struct ANativeWindow; struct egl_native_pixmap_t; typedef struct ANativeWindow* EGLNativeWindowType; typedef struct egl_native_pixmap_t* EGLNativePixmapType; typedef void* EGLNativeDisplayType;
下面是ANativeWindow结构体,里面有一组函数指针,我们能够猜到,两个本地窗口都是继承了ANativeWindow,然后对函数进行赋值,“实现协议”。
struct ANativeWindow { 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]; int (*setSwapInterval)(struct ANativeWindow* window, int interval); int (*query)(const struct ANativeWindow* window, int what, int* value); int (*perform)(struct ANativeWindow* window, int operation, ... ); int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd); int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd); int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd); };
最终找到的两个本地窗口为FramebufferNativeWindow和Surface。
FramebufferNativeWindow
SurfaceFlinger对应的本地窗口为FramebufferNativeWindow,继承了ANativeWindow,里面有个sp<NativeBuffer> buffers[MAX_NUM_FRAME_BUFFERS];,这应该就是“本地的纸”,而且还有和ANativeWindow对应的函数实现。
class FramebufferNativeWindow : public ANativeObjectBase< ANativeWindow, FramebufferNativeWindow, LightRefBase<FramebufferNativeWindow> > { public: FramebufferNativeWindow(); framebuffer_device_t const * getDevice() const { return fbDev; } bool isUpdateOnDemand() const { return mUpdateOnDemand; } status_t setUpdateRectangle(const Rect& updateRect); status_t compositionComplete(); void dump(String8& result); // for debugging only int getCurrentBufferIndex() const; private: friend class LightRefBase<FramebufferNativeWindow>; ~FramebufferNativeWindow(); // this class cannot be overloaded static int setSwapInterval(ANativeWindow* window, int interval); static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd); static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int query(const ANativeWindow* window, int what, int* value); static int perform(ANativeWindow* window, int operation, ...); static int dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer); static int queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); static int lockBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); framebuffer_device_t* fbDev; alloc_device_t* grDev; sp<NativeBuffer> buffers[MAX_NUM_FRAME_BUFFERS]; sp<NativeBuffer> front; mutable Mutex mutex; Condition mCondition; int32_t mNumBuffers; int32_t mNumFreeBuffers; int32_t mBufferHead; int32_t mCurrentBufferIndex; bool mUpdateOnDemand; };
Surface
众多App对应的本地窗口为Surface,继承了ANativeWindow,类似的也有个BufferSlot mSlots[NUM_BUFFER_SLOTS];,是App的“本地的纸”,而且还有和ANativeWindow对应的函数实现。
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase> { public: /* * creates a Surface from the given IGraphicBufferProducer (which concrete * implementation is a BufferQueue). * * Surface is mainly state-less while it's disconnected, it can be * viewed as a glorified IGraphicBufferProducer holder. It's therefore * safe to create other Surfaces from the same IGraphicBufferProducer. * * However, once a Surface is connected, it'll prevent other Surfaces * referring to the same IGraphicBufferProducer to become connected and * therefore prevent them to be used as actual producers of buffers. * * the controlledByApp flag indicates that this Surface (producer) is * controlled by the application. This flag is used at connect time. */ Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false); /* getIGraphicBufferProducer() returns the IGraphicBufferProducer this * Surface was created with. Usually it's an error to use the * IGraphicBufferProducer while the Surface is connected. */ sp<IGraphicBufferProducer> getIGraphicBufferProducer() const; /* convenience function to check that the given surface is non NULL as * well as its IGraphicBufferProducer */ static bool isValid(const sp<Surface>& surface) { return surface != NULL && surface->getIGraphicBufferProducer() != NULL; } protected: virtual ~Surface(); private: // can't be copied Surface& operator = (const Surface& rhs); Surface(const Surface& rhs); // ANativeWindow hooks static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd); static int hook_perform(ANativeWindow* window, int operation, ...); static int hook_query(const ANativeWindow* window, int what, int* value); static int hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int hook_setSwapInterval(ANativeWindow* window, int interval); static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer); static int hook_lockBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); static int hook_queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); int dispatchConnect(va_list args); int dispatchDisconnect(va_list args); int dispatchSetBufferCount(va_list args); int dispatchSetBuffersGeometry(va_list args); int dispatchSetBuffersDimensions(va_list args); int dispatchSetBuffersUserDimensions(va_list args); int dispatchSetBuffersFormat(va_list args); int dispatchSetScalingMode(va_list args); int dispatchSetBuffersTransform(va_list args); int dispatchSetBuffersTimestamp(va_list args); int dispatchSetCrop(va_list args); int dispatchSetPostTransformCrop(va_list args); int dispatchSetUsage(va_list args); int dispatchLock(va_list args); int dispatchUnlockAndPost(va_list args); protected: virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd); virtual int cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd); virtual int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd); virtual int perform(int operation, va_list args); virtual int query(int what, int* value) const; virtual int setSwapInterval(int interval); virtual int lockBuffer_DEPRECATED(ANativeWindowBuffer* buffer); virtual int connect(int api); virtual int disconnect(int api); virtual int setBufferCount(int bufferCount); virtual int setBuffersDimensions(int w, int h); virtual int setBuffersUserDimensions(int w, int h); virtual int setBuffersFormat(int format); virtual int setScalingMode(int mode); virtual int setBuffersTransform(int transform); virtual int setBuffersTimestamp(int64_t timestamp); virtual int setCrop(Rect const* rect); virtual int setUsage(uint32_t reqUsage); public: virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); virtual int unlockAndPost(); protected: enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; private: void freeAllBuffers(); int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; struct BufferSlot { sp<GraphicBuffer> buffer; Region dirtyRegion; }; // mSurfaceTexture is the interface to the surface texture server. All // operations on the surface texture client ultimately translate into // interactions with the server using this interface. // TODO: rename to mBufferProducer sp<IGraphicBufferProducer> mGraphicBufferProducer; // mSlots stores the buffers that have been allocated for each buffer slot. // It is initialized to null pointers, and gets filled in with the result of // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a // slot that has not yet been used. The buffer allocated to a slot will also // be replaced if the requested buffer usage or geometry differs from that // of the buffer allocated to a slot. BufferSlot mSlots[NUM_BUFFER_SLOTS]; // mReqWidth is the buffer width that will be requested at the next dequeue // operation. It is initialized to 1. uint32_t mReqWidth; // mReqHeight is the buffer height that will be requested at the next // dequeue operation. It is initialized to 1. uint32_t mReqHeight; // mReqFormat is the buffer pixel format that will be requested at the next // deuque operation. It is initialized to PIXEL_FORMAT_RGBA_8888. uint32_t mReqFormat; // mReqUsage is the set of buffer usage flags that will be requested // at the next deuque operation. It is initialized to 0. uint32_t mReqUsage; // mTimestamp is the timestamp that will be used for the next buffer queue // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that // a timestamp is auto-generated when queueBuffer is called. int64_t mTimestamp; // mCrop is the crop rectangle that will be used for the next buffer // that gets queued. It is set by calling setCrop. Rect mCrop; // mScalingMode is the scaling mode that will be used for the next // buffers that get queued. It is set by calling setScalingMode. int mScalingMode; // mTransform is the transform identifier that will be used for the next // buffer that gets queued. It is set by calling setTransform. uint32_t mTransform; // mDefaultWidth is default width of the buffers, regardless of the // native_window_set_buffers_dimensions call. uint32_t mDefaultWidth; // mDefaultHeight is default height of the buffers, regardless of the // native_window_set_buffers_dimensions call. uint32_t mDefaultHeight; // mUserWidth, if non-zero, is an application-specified override // of mDefaultWidth. This is lower priority than the width set by // native_window_set_buffers_dimensions. uint32_t mUserWidth; // mUserHeight, if non-zero, is an application-specified override // of mDefaultHeight. This is lower priority than the height set // by native_window_set_buffers_dimensions. uint32_t mUserHeight; // mTransformHint is the transform probably applied to buffers of this // window. this is only a hint, actual transform may differ. uint32_t mTransformHint; // mProducerControlledByApp whether this buffer producer is controlled // by the application bool mProducerControlledByApp; // mSwapIntervalZero set if we should drop buffers at queue() time to // achieve an asynchronous swap interval bool mSwapIntervalZero; // mConsumerRunningBehind whether the consumer is running more than // one buffer behind the producer. mutable bool mConsumerRunningBehind; // mMutex is the mutex used to prevent concurrent access to the member // variables of Surface objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; bool mConnectedToCpu; // must be accessed from lock/unlock thread only Region mDirtyRegion; };
相关文章推荐
- Android源码学习之一-Activity是如何实现主题变化的
- Android 开发笔记(二)菜单设计
- Android 开发笔记(一) 按钮事件调用Activity
- Android通知栏与界面沟通
- Android之 学习路线
- Android笔记(10) - Animation详解
- Android之 环境搭建
- Android中下拉刷新和加载更多的实现方式
- 注册时手机验证用户
- Android 实现个性的ViewPager切换动画 实战PageTransformer
- Android 四大组件之ContentProvider
- android 自定义Toast
- Android中的Activity启动的方式分析
- Android插件化基础(4),动态启动插件中的Activity
- 《第一行代码Android》学习日记20——传感器应用
- Android下拉上滑显示与隐藏Toolbar另一种实现
- android欢迎界面的使用
- Android性能优化之Splash页应该这样设计
- Android音频底层调试-基于tinyalsa
- Android四大组件--Broadcast Receiver具体解释