android graphic(2)—EGL和OpenGL ES


前面提到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;
};
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
In Pro OpenGL ES for Android, you'll find out how to harness the full power of OpenGL ES, and design your own 3D applications by building a fully-functional 3D solar system model using Open GL ES! OpenGL has set the standard for 3D computer graphics, and is an essential aspect of Android development. This book offers everything you need to know, from basic mathematical concepts to advanced coding techniques. You'll learn by building a fascinating 3D solar system simulator! After introducing Open GL ES, Pro OpenGL ES for Android explains the basics of 3D math and then orients you to the native Android 3D libraries you'll be using in your own 3D games and the solar system project you'll build using this book. Through the solar system example project, you'll learn how to incorporate a variety of graphic and animation techniques into your applications. You will also discover how the full spectrum of 3D development that awaits, with topics such as lighting, texture-mapping, modeling, shaders, blending modes, and several more advanced concepts. By the time you finish Pro OpenGL ES for Android, you'll have learned all the skills you'll need to build your own incredible 3D applications, based on one of the most powerful 3D libraries available. What you'll learn * The basics of 3D mathematics, and how they are applied in the OpenGL library * How to design and build your 3D worlds * To create 2D interfaces within the 3D world * To develop animation and 3D movement * How to implement 3D shading, coloring, and texturing * The differences between OpenGL and other 3D toolkits * To build a fully-functional 3D solar system simulator using OpenGL ES Who this book is for Experienced Android programmers who want to enter the 3D world of OpenGL ES programming. Table of Contents * Introduction to OpenGL ES and Our 3D Solar System Project * Generating a Basic OpenGL Program * Getting Past the 3D Math * Shading, Lighting and Colors * Materials and Textures * Animation * Creating a User Interface * Blending Modes, Buffer Objects, and Other Cool Stuff * Latest Features of OpenGL ES * Ray Tracing, Hidden Surfaces, and Other Advanced Topics Appendix A: APIs

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值