您的位置:首页 > 移动开发 > Android开发

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。

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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: