- 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
{
int width ;
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设备定义,渲染到屏幕的
f ramebuffer_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 ( new Fence ( 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 );
}
ANativeWindow相关推荐
- ANativeWindow是个什么东西
公司经常组织一些培训,培训的都是些奇技淫巧.什么设计模式啦,开发策略啦,git啦,repo啦,另外就是培训一些开发流程的东东,例如CMMI啦.可是,却忘记了,程序员终究要归结到三个问题上: 1.解决什 ...
- 【Android FFMPEG 开发】FFMPEG ANativeWindow 原生绘制 ( 设置 ANativeWindow 缓冲区属性 | 获取绘制缓冲区 | 填充数据到缓冲区 | 启动绘制 )
文章目录 I . FFMPEG ANativeWindow 原生绘制 前置操作 II . FFMPEG 原生绘制流程 III . 设置 ANativeWindow 绘制窗口属性 ANativeWind ...
- 【Android FFMPEG 开发】FFMPEG ANativeWindow 原生绘制 ( Java 层获取 Surface | 传递画布到本地 | 创建 ANativeWindow )
文章目录 I . FFMPEG ANativeWindow 原生绘制 II . FFMPEG 原生绘制流程 III . Java 层获取 Surface 画布 IV . 传递 Surface 画布到 ...
- android全平台编译libjpeg-turbo并基于ANativeWindow加载JPEG图片
图形图像实践 android全平台编译libjpeg-turbo并基于ANativeWindow加载JPEG图片 android全平台编译libpng并基于ANativeWindow加载PNG图片 概 ...
- android平台下基于ANativeWindow实现渲染bitmap图像
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow
1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...
- Android开发之六:SurfaceView、ANativeWindow原生绘制
SurfaceView Activity的View hierachy的树形结构,最顶层的DecorView,也就是根结点视图,在SurfaceFlinger中有对应的Layer. 对于具有Su ...
- ANativeWindow 和 Surface
Android播放视频从解码到显示实质也是BufferQueue的生产消费的过程,如下图所示: 其中生产者是Surface,消费者是SurfaceFlinger. 本文主要针对Surface进行分析, ...
- 实操教程:android camera nanodet 实时物体检测的高效实现总结
作者丨nihui@知乎(已授权) 来源丨https://zhuanlan.zhihu.com/p/356991989 编辑丨极市平台 未经允许禁止二次转载 导读 本文介绍了配合高效的Android应用 ...
最新文章
- IO测试工具之fio详解
- python 办公_python 让办公变得自动化
- Redis中的可用性保证之Sentinel 原理
- 将来时态:I will fly - I'm going to fly - I'm flying_48
- spring-boot-maven-plugin插件
- python项目软件代码_七套Python库快速提升您项目的代码可维护性,软件工程,代码库...
- 静态导入 java面试_Java面试系列【静态导入】-静态导入,基础篇
- python c++ socket 通信一个示例
- RK3399 Android上面调试IMX291 Camera驱动
- pta 7-5 病毒变种 C语言
- 基于单片机的红外光电计数器(双探头)
- 创新设计思维总结报告
- python裂缝检测_通过opencv-python检测裂缝
- 中国近代史纲要 期末复习
- php footer'=%3e2,为基于Wordpress的博客添加CNZZ统计代码
- 计算机专业我的理想作文,我的理想经典优秀作文
- 初中计算机科学生情况,初中计算机科学与技术的现代化运用探究
- java基础之Object类_繁星漫天_新浪博客
- 常见的海外广告投放平台,海外社交广告平台的开户流程与要求
- 千兆网卡和普通网卡有什么区别?如何判断?
热门文章
- Maya XGen 毛发制作3 - 创建发块
- 机械臂控制软件,上位机软件 此机器人上位软件。 运动采用通用G代码指令编程,具有G5三维的空间圆弧插补,空间直线插补功能
- C\C++中头文件string与string.h的区别
- 电子招投标系统EBD
- MQ--1( Message queuing)RabbitMQ
- cola ui ajax,Cola-UI 文档中心
- Aborted(core dumped)
- base64加密原理详解
- 聚合收款码怎么推广?
- 《MATLAB智能算法30个案例》:第19章 基于模拟退火算法的TSP算法