- ANativeWindow : opengl工作的绘图画布本地窗口,按标准定义好函数(下面好多代码都简化)
struct
ANativeWindow
{
.....
//上层定义好函数指针,传给opengl后,opengl在必要的时候会调用相应的函数
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
);
}
ANativeWindowBuffer:绘制的图像缓冲区
struct
ANativeWindowBuffer
{
intwidth;
int
height
;
int
usage;
.....
//通过这个handle就跟Gralloc模块申请的图片缓存关联起来了,可能在fb申请也能是共享内存中申请的(看他了usage
)
buffer_handle_t
handle
;
}
fenceFd:暂时把他当作这个buffer的锁,因为缓存区需要cpu,gpu,composer共享,普通锁不管用啊。
2.android中的本地窗口
(1.)操作显存的,surfaceflinger服务中应用的。最总渲染到屏幕的
FramebufferNativeWindow:
public
ANativeObjectBase
<
ANativeWindow,
FramebufferNativeWindow,
LightRefBase<FramebufferNativeWindow
> >
别看上面的这么复杂其实就是 FramebufferNativeWindow: public ANativeWindow,看名字就是包装了fb显存了,用它直接绘制到屏幕上的
构造函数:
FramebufferNativeWindow
::FramebufferNativeWindow()
:
BASE(),
fbDev
(0),
grDev(0),
mUpdateOnDemand(false
)
{
hw_module_t
const
*
module;
//打开Gralloc硬件抽象层模块
hw_get_module
(GRALLOC_HARDWARE_MODULE_ID,
& module);
//获取抽象层中的fb设备定义,渲染到屏幕的
framebuffer_open
(module,
& fbDev);
//获取抽象层图像缓存申请设备,获取一段内存或显存的
gralloc_open
(module,
& grDev);
//看一下fb支持缓冲区大小,可能有多个离屏缓冲,初始化一下这些缓冲区
if(fbDev
->numFramebuffers
>=
MIN_NUM_FRAME_BUFFERS
&&
fbDev->numFramebuffers
<=
MAX_NUM_FRAME_BUFFERS){
mNumBuffers
=
fbDev
->numFramebuffers;
}
else
{
mNumBuffers
=
MIN_NUM_FRAME_BUFFERS
;
}
for
(i
= 0;
i
<
mNumBuffers;
i++)
{
// NativeBuffer
:
public
ANativeWindowBuffer 从ANativeWindowBuffer继承
buffers[i]
= new NativeBuffer(fbDev->width,
fbDev->height,
fbDev->format,
GRALLOC_USAGE_HW_FB
);
grDev
->alloc(
grDev,
fbDev->width
,
fbDev->
height,
fbDev
->format,
GRALLOC_USAGE_HW_FB, &buffers
[i]->
handle, &buffers[i
]->stride);
}
//opengl需要的本地窗口定义了
const_cast<uint32_t
&>(ANativeWindow::
flags) =
fbDev
->flags;
const_cast<float
&>(ANativeWindow::
xdpi) =
fbDev
->xdpi;
const_cast<float
&>(ANativeWindow::
ydpi) =
fbDev
->ydpi;
const_cast<int
&>(ANativeWindow::
minSwapInterval) =
fbDev->minSwapInterval
;
const_cast<int
&>(ANativeWindow::
maxSwapInterval) =
fbDev->maxSwapInterval
;
ANativeWindow::setSwapInterval
=
setSwapInterval;
ANativeWindow::dequeueBuffer
=
dequeueBuffer;
ANativeWindow::queueBuffer
=
queueBuffer;
ANativeWindow::query
=
query;
ANativeWindow::perform
=
perform;
ANativeWindow::dequeueBuffer_DEPRECATED
=
dequeueBuffer_DEPRECATED;
ANativeWindow::lockBuffer_DEPRECATED
=
lockBuffer_DEPRECATED;
ANativeWindow::queueBuffer_DEPRECATED
=
queueBuffer_DEPRECATED;
}
int
FramebufferNativeWindow
::setSwapInterval(
ANativeWindow*
window
,
int
interval)
{
return
fb
->setSwapInterval(
fb,
interval
);
}
//opengl要一个图像缓冲区,要后台绘制了
int
FramebufferNativeWindow
::dequeueBuffer(
ANativeWindow*
window
,
ANativeWindowBuffer**
buffer
,
int*
fenceFd)
{
//根据一系列条件找到一个空闲的缓冲区,如果没有空闲的了,还的等待queuebuffer释放一个缓存
int
index
=???
*
buffer
=
self
->buffers[
index].get
();
*
fenceFd
= -1;
}
//这个buffer绘制完成,可以绘制到屏幕上了
int
FramebufferNativeWindow
::queueBuffer(
ANativeWindow*
window
,
ANativeWindowBuffer*
buffer
,
int
fenceFd)
{
//等待其他硬件都这个buffer操作完成
sp<Fence>
fence(newFence(fenceFd));
fence->wait
(Fence::
TIMEOUT_NEVER);
//绘制到屏幕上
fb->
post(fb
,
handle);
}
egl中定义了:
typedef
struct
ANativeWindow*
EGLNativeWindowType;
(2.)app端,临时用的的ANativeWindow,最终这个buffer会间接的提交到Framebuffer那面,显示到屏幕上。
class Surface
:
public ANativeObjectBase<ANativeWindow,
Surface,
RefBase>
构造函数,跟上面的差不多吧,都先初始化ANativeWindow相关函数接口
Surface::Surface
(
const
sp
<IGraphicBufferProducer>&
bufferProducer,
bool
controlledByApp
)
:
mGraphicBufferProducer(bufferProducer
)
{
ANativeWindow::setSwapInterval
=
hook_setSwapInterval;
ANativeWindow::dequeueBuffer
=
hook_dequeueBuffer;
ANativeWindow::cancelBuffer
=
hook_cancelBuffer;
ANativeWindow::queueBuffer
=
hook_queueBuffer;
ANativeWindow::query
=
hook_query;
ANativeWindow::perform
=
hook_perform;
ANativeWindow::dequeueBuffer_DEPRECATED
=
hook_dequeueBuffer_DEPRECATED
;
ANativeWindow::cancelBuffer_DEPRECATED
=
hook_cancelBuffer_DEPRECATED
;
ANativeWindow::lockBuffer_DEPRECATED
=
hook_lockBuffer_DEPRECATED
;
ANativeWindow::queueBuffer_DEPRECATED
=
hook_queueBuffer_DEPRECATED
;
const_cast<int
&>(ANativeWindow::
minSwapInterval) = 0;
const_cast<int
&>(ANativeWindow::
maxSwapInterval) = 1;
mReqWidth
= 0;
mReqHeight
= 0;
mReqFormat
= 0;
.....
}
//opengl要一个图像缓冲区,要后台绘制了
int
Surface
::dequeueBuffer(
android_native_buffer_t**
buffer
,
int*
fenceFd) {
sp<Fence
>
fence;
// producer(BufferQueue)中获取一段空闲的图像缓冲区,这个内部也是通过硬件抽象层的Gralloc申请的
status_t
result
=
mGraphicBufferProducer->
dequeueBuffer(&buf
, &fence,
mSwapIntervalZero
,
reqW,
reqH
,
mReqFormat,
mReqUsage);
sp<GraphicBuffer
>&
gbuf(
mSlots[buf
].buffer);
if
((result
&
IGraphicBufferProducer::
BUFFER_NEEDS_REALLOCATION) ||
gbuf
== 0) {
result
=
mGraphicBufferProducer
->requestBuffer(
buf, &gbuf
);
}
*
fenceFd
=
fence
->dup();
*
buffer
=
gbuf
.get();
return
OK
;
}
//这个buffer绘制完成,可以用了啊
int
Surface
::queueBuffer(
android_native_buffer_t*
buffer
,
int
fenceFd) {
Rect
crop
;
mCrop.intersect
(Rect(
buffer->width
,
buffer->
height), &crop
);
sp<Fence
>
fence(
fenceFd
>= 0 ?
new
Fence(
fenceFd) :
Fence::NO_FENCE
);
IGraphicBufferProducer::QueueBufferOutput
output;
IGraphicBufferProducer::QueueBufferInput
input(
timestamp,
isAutoTimestamp,
crop,
mScalingMode
,
mTransform,
mSwapIntervalZero,
fence
);
//producer(BufferQueue)添加一段填充好的buffer,需要渲染buffer的就看着办吧
status_t
err
= mGraphicBufferProducer->
queueBuffer(i
,
input, &output);
uint32_t
numPendingBuffers
= 0;
output.deflate
(&mDefaultWidth,
& mDefaultHeight, &mTransformHint
,
&
numPendingBuffers);
return
err
;
}
mGraphicBufferProducer (BufferQueue)入队,出队是 一个跨进程的操作,他们通过Binder通讯。
BufferQueue是一个典型的生产消费结构,生产者加工好数据丢进来,消耗者发现有数据后马上消耗掉,这个以后再分析。
3.opengl如何使用这个ANativeWindow的呢
android中opengl环境的搭建是由EGL帮忙完成的,opengl是一组跨进程的api,
NativeWindowType就是一个ANativeWindow
typedef
struct
ANativeWindow*
EGLNativeWindowType;
EGLSurface
eglCreateWindowSurface
(
EGLDisplay
dpy,
EGLConfig
config,
NativeWindowType
window
,
const
EGLint
*attrib_list)
{
//保存了加载的opengl相关的so导出接口,egl接口
egl_connection_t*
cnx
=
NULL;
egl_display_ptr
dp
=
validate_display_connection(
dpy,
cnx
);
//可以想象一下就是吧window包装成一个EGlSurface,cnx->
egl是so提供的一系类函数指针
EGLSurface
surface
=
cnx->
egl.eglCreateWindowSurface
(
iDpy,
config
,
window,
attrib_list);
}