Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3|回复: 0
打印 上一主题 下一主题

android graphic(2)—EGL和OpenGL ES

[复制链接]

1198

主题

2060

帖子

7058

积分

超级版主

Rank: 8Rank: 8

积分
7058
跳转到指定楼层
楼主
发表于 2016-7-25 21:13:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式



前面提到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;};


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Comsenz Inc.

GMT+8, 2025-12-15 02:20 , Processed in 0.016815 second(s), 8 queries , Apc On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表