http://blog.csdn.net/lewif/article/details/50532011
前面提到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。
上面提到,如果需要使用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);
}
而
typedefEGLNativeWindowType NativeWindowType;
从下面的定义可以看到,在系统为android的宏下,本地窗口其实为ANativeWindow。
#elifdefined(__ANDROID__) || defined(ANDROID)
struct ANativeWindow;
structegl_native_pixmap_t;
typedefstructANativeWindow* EGLNativeWindowType;
typedefstructegl_native_pixmap_t* EGLNativePixmapType;
typedefvoid* EGLNativeDisplayType;
下面是ANativeWindow结构体,里面有一组函数指针,我们能够猜到,两个本地窗口都是继承了ANativeWindow,然后对函数进行赋值,“实现协议”。
struct ANativeWindow
{
structandroid_native_base_t common;
/* flags describing some attributes ofthis surface or its updater */
const uint32_t flags;
/* min swap interval supported by this updated */
constint minSwapInterval;
/* max swap interval supported by thisupdated */
constint maxSwapInterval;
/* horizontal and vertical resolution inDPI */
constfloat xdpi;
constfloat ydpi;
/* Some storage reserved for the OEM'sdriver. */
intptr_t oem[4];
int (*setSwapInterval)(struct ANativeWindow*window,
int interval);
int (*query)(conststruct ANativeWindow*window,
int what, int* value);
int (*perform)(struct ANativeWindow*window,
int operation, ...);
int (*cancelBuffer_DEPRECATED)(struct ANativeWindow*window,
structANativeWindowBuffer* buffer);
int (*dequeueBuffer)(struct ANativeWindow*window,
structANativeWindowBuffer** buffer, int* fenceFd);
int (*queueBuffer)(struct ANativeWindow*window,
structANativeWindowBuffer* buffer, int fenceFd);
int (*cancelBuffer)(struct ANativeWindow*window,
structANativeWindowBuffer* buffer, int fenceFd);
};
最终找到的两个本地窗口为FramebufferNativeWindow和Surface。
SurfaceFlinger对应的本地窗口为FramebufferNativeWindow,继承了ANativeWindow,里面有个sp<NativeBuffer>buffers[MAX_NUM_FRAME_BUFFERS];,这应该就是“本地的纸”,而且还有和ANativeWindow对应的函数实现。
class FramebufferNativeWindow
: publicANativeObjectBase<
ANativeWindow,
FramebufferNativeWindow,
LightRefBase<FramebufferNativeWindow> >
{
public:
FramebufferNativeWindow();
framebuffer_device_t const * getDevice() const { return fbDev; }
boolisUpdateOnDemand() const { returnmUpdateOnDemand; }
status_tsetUpdateRectangle(const Rect&updateRect);
status_tcompositionComplete();
voiddump(String8& result);
// for debugging only
intgetCurrentBufferIndex() const;
private:
friend classLightRefBase<FramebufferNativeWindow>;
~FramebufferNativeWindow(); // this class cannot be overloaded
staticintsetSwapInterval(ANativeWindow* window, int interval);
staticintdequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd);
staticint queueBuffer(ANativeWindow*window, ANativeWindowBuffer* buffer, int fenceFd);
staticint query(const ANativeWindow*window, int what, int* value);
staticintperform(ANativeWindow* window, int operation, ...);
staticint dequeueBuffer_DEPRECATED(ANativeWindow*window, ANativeWindowBuffer** buffer);
staticintqueueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
staticintlockBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
framebuffer_device_t* fbDev;
alloc_device_t*grDev;
sp<NativeBuffer> buffers[MAX_NUM_FRAME_BUFFERS];
sp<NativeBuffer> front;
mutable Mutexmutex;
ConditionmCondition;
int32_tmNumBuffers;
int32_tmNumFreeBuffers;
int32_t mBufferHead;
int32_tmCurrentBufferIndex;
boolmUpdateOnDemand;
};
众多App对应的本地窗口为Surface,继承了ANativeWindow,类似的也有个BufferSlot mSlots[NUM_BUFFER_SLOTS];,是App的“本地的纸”,而且还有和ANativeWindow对应的函数实现。
class Surface
: public ANativeObjectBase<ANativeWindow,Surface, RefBase>
{
public:
/*
* creates aSurface from the given IGraphicBufferProducer (which concrete
*implementation is a BufferQueue).
*
* Surface is mainlystate-less while it'sdisconnected, it can be
* viewed as a glorifiedIGraphicBufferProducer holder. It's therefore
* safe tocreate other Surfaces from the same IGraphicBufferProducer.
*
* However,once a Surface is connected,it'll prevent other Surfaces
* referring tothe same IGraphicBufferProducer to become connected and
* thereforeprevent them to be used as actual producers of buffers.
*
* thecontrolledByApp flag indicates that thisSurface (producer) is
* controlledby the application. This flag is used at connect time.
*/
Surface(constsp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp= false);
/* getIGraphicBufferProducer() returnsthe IGraphicBufferProducer this
* Surface was created with. Usually it'san error to use the
* IGraphicBufferProducer while the Surfaceis connected.
*/
sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
/* convenience function to check thatthe given surface is non NULL as
* well as its IGraphicBufferProducer */
staticbool isValid(constsp<Surface>& surface) {
return surface != NULL&& surface->getIGraphicBufferProducer() != NULL;
}
protected:
virtual ~Surface();
private:
// can't becopied
Surface& operator = (const Surface&rhs);
Surface(const Surface&rhs);
// ANativeWindow hooks
staticinthook_cancelBuffer(ANativeWindow* window,
ANativeWindowBuffer* buffer, int fenceFd);
staticint hook_dequeueBuffer(ANativeWindow*window,
ANativeWindowBuffer** buffer, int* fenceFd);
staticinthook_perform(ANativeWindow* window, int operation, ...);
staticint hook_query(const ANativeWindow*window, int what, int* value);
staticinthook_queueBuffer(ANativeWindow* window,
ANativeWindowBuffer* buffer, int fenceFd);
staticinthook_setSwapInterval(ANativeWindow* window, int interval);
staticinthook_cancelBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer* buffer);
staticinthook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer** buffer);
staticinthook_lockBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer* buffer);
staticinthook_queueBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer* buffer);
intdispatchConnect(va_list args);
intdispatchDisconnect(va_list args);
intdispatchSetBufferCount(va_list args);
intdispatchSetBuffersGeometry(va_list args);
intdispatchSetBuffersDimensions(va_list args);
intdispatchSetBuffersUserDimensions(va_list args);
intdispatchSetBuffersFormat(va_list args);
intdispatchSetScalingMode(va_list args);
int dispatchSetBuffersTransform(va_listargs);
intdispatchSetBuffersTimestamp(va_list args);
intdispatchSetCrop(va_list args);
intdispatchSetPostTransformCrop(va_list args);
intdispatchSetUsage(va_list args);
intdispatchLock(va_list args);
intdispatchUnlockAndPost(va_list args);
protected:
virtualintdequeueBuffer(ANativeWindowBuffer**buffer, int* fenceFd);
virtualintcancelBuffer(ANativeWindowBuffer* buffer, int fenceFd);
virtualintqueueBuffer(ANativeWindowBuffer* buffer, int fenceFd);
virtualint perform(int operation,va_list args);
virtualint query(int what, int* value) const;
virtualintsetSwapInterval(int interval);
virtualintlockBuffer_DEPRECATED(ANativeWindowBuffer* buffer);
virtualint connect(int api);
virtualint disconnect(int api);
virtualint setBufferCount(int bufferCount);
virtualintsetBuffersDimensions(int w, int h);
virtualintsetBuffersUserDimensions(int w, int h);
virtualintsetBuffersFormat(int format);
virtualint setScalingMode(int mode);
virtualintsetBuffersTransform(int transform);
virtualintsetBuffersTimestamp(int64_t timestamp);
virtualint setCrop(Rect const* rect);
virtualintsetUsage(uint32_t reqUsage);
public:
virtualintlock(ANativeWindow_Buffer*outBuffer, ARect* inOutDirtyBounds);
virtualintunlockAndPost();
protected:
enum {NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
enum {DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
private:
voidfreeAllBuffers();
intgetSlotFromBufferLocked(android_native_buffer_t* buffer) const;
struct BufferSlot {
sp<GraphicBuffer> buffer;
RegiondirtyRegion;
};
// mSurfaceTexture is the interface tothe surface texture server. All
// operations on the surface textureclient ultimately translate into
// interactions with the server usingthis interface.
// TODO: rename to mBufferProducer
sp<IGraphicBufferProducer> mGraphicBufferProducer;
// mSlots stores the buffers that havebeen allocated for each buffer slot.
// It is initialized to null pointers,and gets filled in with the result of
// IGraphicBufferProducer::requestBufferwhen the client dequeues a buffer from a
// slot that has not yet been used. Thebuffer allocated to a slot will also
// be replaced if the requested bufferusage or geometry differs from that
// of the buffer allocated to a slot.
BufferSlotmSlots[NUM_BUFFER_SLOTS];
// mReqWidth is the buffer width thatwill be requested at the next dequeue
// operation. It is initialized to 1.
uint32_tmReqWidth;
// mReqHeight is the buffer height thatwill be requested at the next
// dequeue operation. It is initializedto 1.
uint32_tmReqHeight;
// mReqFormat is the buffer pixel formatthat will be requested at the next
// deuque operation. It is initializedto PIXEL_FORMAT_RGBA_8888.
uint32_tmReqFormat;
// mReqUsage is the set of buffer usageflags that will be requested
// at the next deuque operation. It isinitialized to 0.
uint32_tmReqUsage;
// mTimestamp is the timestamp that willbe used for the next buffer queue
// operation. It defaults toNATIVE_WINDOW_TIMESTAMP_AUTO, which means that
// a timestamp is auto-generated whenqueueBuffer is called.
int64_tmTimestamp;
// mCrop is the crop rectangle that willbe used for the next buffer
// that gets queued. It is set bycalling setCrop.
Rect mCrop;
// mScalingMode is the scaling mode that will be used forthe next
// buffers that get queued. It is set bycalling setScalingMode.
int mScalingMode;
// mTransform is the transformidentifier that will be used for the next
// buffer that gets queued. It is set bycalling setTransform.
uint32_tmTransform;
// mDefaultWidth is default width of thebuffers, regardless of the
// native_window_set_buffers_dimensionscall.
uint32_tmDefaultWidth;
// mDefaultHeight is default height ofthe buffers, regardless of the
// native_window_set_buffers_dimensionscall.
uint32_tmDefaultHeight;
// mUserWidth, if non-zero, is anapplication-specified override
// of mDefaultWidth. This is lower priority than the width set by
// native_window_set_buffers_dimensions.
uint32_tmUserWidth;
// mUserHeight, if non-zero, is anapplication-specified override
// of mDefaultHeight. This is lower priority than the height set
// by native_window_set_buffers_dimensions.
uint32_tmUserHeight;
// mTransformHint is the transformprobably applied to buffers of this
// window. this is only a hint, actualtransform may differ.
uint32_tmTransformHint;
// mProducerControlledByApp whether thisbuffer producer is controlled
// by the application
boolmProducerControlledByApp;
// mSwapIntervalZero set if we shoulddrop buffers at queue() time to
// achieve an asynchronous swap interval
boolmSwapIntervalZero;
// mConsumerRunningBehind whether theconsumer is running more than
// one buffer behind the producer.
mutable boolmConsumerRunningBehind;
// mMutex is the mutex used to preventconcurrent access to the member
// variables of Surface objects. It must be locked whenever the
// member variables are accessed.
mutable MutexmMutex;
// must be used from the lock/unlockthread
sp<GraphicBuffer> mLockedBuffer;
sp<GraphicBuffer> mPostedBuffer;
bool mConnectedToCpu;
// must be accessed from lock/unlockthread only
RegionmDirtyRegion;
};