当前位置: 首页 > news >正文

网站 linux 服务器配置烘焙培训

网站 linux 服务器配置,烘焙培训,人才网站查询档案,健康类网站模板本文涉及的源代码基于 Android-7.1.1r。一、Android GUI 框架SurfaceFlinger 是 Android GUI 的核心#xff0c;但是从 OpenGL_ES 的角度来看#xff0c;它也只是个“应用程序”。Android 的显示系统大致框架图下图所示#xff1a;GUI_STRUCT.png下面就“由下向上”来逐一分…本文涉及的源代码基于 Android-7.1.1r。一、Android GUI 框架SurfaceFlinger 是 Android GUI 的核心但是从 OpenGL_ES 的角度来看它也只是个“应用程序”。Android 的显示系统大致框架图下图所示GUI_STRUCT.png下面就“由下向上”来逐一分析该框架。(1) 显示驱动Linux 内核提供了统一的 framebuffer 显示驱动。设备节点是 /dev/graphics/fb* 或 /dev/fb*而 fb0 表示第一个 Monitor当前系统实现中只用到了一个显示屏。(2) HAL 层Android 的 HAL 层提供了 Gralloc包括 fb 和 gralloc 两个设备。fb 负责打开内核中的 framebuffer初始化配置并提供 postsetSwapIntervel 等操作接口gralloc 用于管理帧缓冲区的分配和释放。HAL 层还包含另一个重要模块 —— “Composer”它为厂商自定制“UI合成”提供了接口。Composer 的直接使用者是 SurfaceFlinger 中的 HWComposerHWComposer 除了负责管理 Composer 的 HAL 模块外还负责 VSync 信号(软件、硬件)的产生和控制。(3) FramebufferNativeWindowFramebufferNativeWindow 是负责 OpenGL ES(通用函数库) 在 Android 平台上本地化的中介之一它将 Android 的窗口系统与 OpenGL ES 产生联系为 OpenGL ES 配置本地窗口的是 EGL。(4) EGLEGL 负责为 OpenGL ES 配合本地窗口。OpenGL ES 更多的只是一个接口协议具体实现即可以采用软件也可以采用硬件实现而 EGL 会去读取 egl.cfg并根据用户的设置来动态加载 libagl(软件实现)或是 libhgl(硬件实现)。(5) DisplayDeviceSurfaceFlinger 中持有一个成员数组 mDisplays 用来描述系统中支持的各种显示设备具体有那些 Display 是由 SurfaceFlinger 在 readyToRun 中进行判断并赋值的。DisplayDevice 在初始化的时候会调用 eglGetDisplayeglCreateWindowSurface 等接口并利用 EGL 来完成 OpenGL ES 环境的搭建。(6) OpenGL ES 模块很多模块都可以调用 OpenGL ES 提供的 API其中就包括 SurfaceFLinger 和 DisplayerDevice。与 OpenGL ES 的相关的模块分为以下几类配置类帮助 OpenGL ES 完成配置包括 EGLDisplayHardware 都属这一类。依赖类OpenGL ES 要运行的起来所依赖的“本地化”的东西在上图中指的就是 FramebufferNativeWindow。使用类使用 OpenGL ES 的用户如 DisplayDevice 即扮演了使用者又扮演了构建 OpenGL ES 的配置者。二、HALHAL 是子系统(显示系统、音频系统)与 Linux 内核驱动之间的统一接口。HAL 需要解决以下问题硬件的抽象接口的稳定灵活的使用。(1) 硬件抽象HAL 多数使用 C 语言编写而 C 语言不是面向对象的所以具体的“继承”关系就没有像 C 或是 Java 这类的面向对象的语言表现的那么直接。在 C 语言中要实现类似的“继承”关系只需要让子类的第一个成员变量是父类结构即可。以 Gralloc 为例它就是 hw_module_t 的子类代码如下typedef struct gralloc_module_t {struct hw_module_t common; // 父类// 结构体中定义函数指针(结构体中不能定义函数)int (*registerBuffer)(struct gralloc_module_t const* module,buffer_handle_t handle);int (*unregisterBuffer)(struct gralloc_module_t const* module,buffer_handle_t handle);int (*lock)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,void** vaddr);int (*unlock)(struct gralloc_module_t const* module,buffer_handle_t handle);int (*perform)(struct gralloc_module_t const* module,int operation, ... );int (*lock_ycbcr)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,struct android_ycbcr *ycbcr);int (*lockAsync)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,void** vaddr, int fenceFd);int (*unlockAsync)(struct gralloc_module_t const* module,buffer_handle_t handle, int* fenceFd);int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,struct android_ycbcr *ycbcr, int fenceFd);void* reserved_proc[3];} gralloc_module_t;(2) 接口的稳定HAL 中的接口必须是稳定不变的Android 系统中已经预定好了这些接口如下图所示(源码位置hardware/libhardware/include/hardware)HAL接口.png(3) 灵活的使用硬件生产商只要按照 Android 提供的硬件要求来实现 HAL 接口手机开发商只需要移植硬件生产商提供的 HAL 库就可以了。三、Android 终端显示设备 ———— Gralloc 和 FramebufferFramebuffer 是 Linux 内核提供的图形硬件的抽象描述它占用了系统内存的一部分是一块包含屏幕显示信息的缓冲区。在 Android 中Framebuffer 提供的设备文件节点是 /dev/graphics/fb*。这里以 sony Xperia 为例它的 fb 节点如下图所示Sony_Xperia_fb.pngAndroid 的子系统不会直接使用内核驱动而是由 HAL 层来间接引用底层框架。显示系统也是一样它通过 HAL 层来做操作帧缓冲区而完成这一中介任务的就是 Gralloc。3.1、Gralloc 模块的加载Gralloc 对应的模块是在 FramebufferNativeWindow(GUI 结构图中位于 Grlloc 上方) 的构造函数中加载的(在 Androdi-7.1.1 中是通过 Gralloc1.cpp 进行加载的)即int err hw_get_module(GRALLOC_HARDWARE_MODULE_ID, module); //hw_get_module 是上层使用(FramebufferNativeWindow)者加载 HAL 库的入口。lib 库有以下几种形式;gralloc.[ro.hardware].sogralloc.[ro.product.board].sogralloc.[ro.board.platform].sogralloc.[ro.arch].so当以上文件都不存在时就使用默认的gralloc.default.so源码位置hardware/libhardware/modules/gralloc/由 gralloc.cppframebuffer.cpp 和 mapper.cpp 三个主要文件编译而成。3.2、Gralloc 提供的接口Gralloc 是 hw_module_t 的子类hw_module_t 代码如下typedef struct hw_module_t {uint32_t tag;uint16_t module_api_version;#define version_major module_api_versionuint16_t hal_api_version;#define version_minor hal_api_versionconst char *id;const char *name;const char *author;struct hw_module_methods_t* methods; // hw_module_t 中必须提供void* dso;#ifdef __LP64__uint64_t reserved[32-7];#elseuint32_t reserved[32-7];#endif} hw_module_t;typedef struct hw_module_methods_t {// 函数指针用于打开设备int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);} hw_module_methods_t;任何硬件设备的 HAL 库都必须实现 hw_module_methods_t该结构体中只有一个函数指针变量也就是 open由于函数体内不能定义函数所以这里使用了函数指针。当上层使用者调用 hw_get_module 时系统首先会在指定目录下加载正确的 HAL 库然后通过 open 函数打开指定的设备。这里 open 方法对应的实现是 gralloc_device_open()gralloc.cpp。open接口可以可以帮助上层使用者打开两种设备define GRALLOC_HARDWARE_FB0主屏define GRALLOC_HARDWARE_GPU0负责图形缓冲区的分配和释放define 前有“#”由于格式问题这里没有打出。下面看 gralloc_device_open() 的实现// gralloc.cppint gralloc_device_open(const hw_module_t* module, const char* name,hw_device_t** device){int status -EINVAL;// 打开 gralloc 设备或是打开 fb 设备。if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {gralloc_context_t *dev;dev (gralloc_context_t*)malloc(sizeof(*dev));/* initialize our state here */memset(dev, 0, sizeof(*dev));/* initialize the procs */dev-device.common.tag HARDWARE_DEVICE_TAG;dev-device.common.version 0;dev-device.common.module const_cast(module);dev-device.common.close gralloc_close;dev-device.alloc gralloc_alloc;dev-device.free gralloc_free;*device dev-device.common;status 0;} else {status fb_device_open(module, name, device); // 打开 Framebuffer}return status;}下面看 framebuffer 设备的打开过程int fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device){int status -EINVAL;if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {/* initialize our state here */fb_context_t *dev (fb_context_t*)malloc(sizeof(*dev)); // 分配 hw_device_t 空间这只是一个“壳”memset(dev, 0, sizeof(*dev)); // 初始化/* initialize the procs */dev-device.common.tag HARDWARE_DEVICE_TAG;dev-device.common.version 0;dev-device.common.module const_cast(module);// 核心接口dev-device.common.close fb_close;dev-device.setSwapInterval fb_setSwapInterval;dev-device.post fb_post;dev-device.setUpdateRect 0;private_module_t* m (private_module_t*)module;status mapFrameBuffer(m); // 内存映射 mmapif (status 0) {int stride m-finfo.line_length / (m-info.bits_per_pixel 3);int format (m-info.bits_per_pixel 32)? (m-info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : HAL_PIXEL_FORMAT_RGBX_8888): HAL_PIXEL_FORMAT_RGB_565;const_cast(dev-device.flags) 0;const_cast(dev-device.width) m-info.xres;const_cast(dev-device.height) m-info.yres;const_cast(dev-device.stride) stride;const_cast(dev-device.format) format;const_cast(dev-device.xdpi) m-xdpi;const_cast(dev-device.ydpi) m-ydpi;const_cast(dev-device.fps) m-fps;const_cast(dev-device.minSwapInterval) 1;const_cast(dev-device.maxSwapInterval) 1;*device dev-device.common; // 核心}}return status;}其中 fb_context_t 是 framebuffer 内部使用的一个类它包含了众多信息而最终返回的 device 只是其内部的 device.common。这种“通用和差异”并存的编码风格在 HAL 层非常常见。fb_context_t 唯一的成员就是 framebuffer_device_t这是对 frambuffer 设备的统一描述。struct fb_context_t {framebuffer_device_t device;};一个标准的 fb 设备通常要提供如下的函数实现int(post)(struct framebuffer_device_t dev, buffer_handle_t buffer);将 buffer 数据 post 到显示屏上。要求 buffer 必须与屏幕尺寸一致并且没有被 locked。这样的话buffer 内容将在下一次 VSYNC 中被显示出来。int(setSwapInterval)(struct framebuffer_device_t window, int interval);设置两个缓冲区交换的时间间隔int(setUpdateRect)(struct framebuffer_device_t window, int left, int top, int width, int height);设置刷新区域需要 framebuffer 驱动支持“update-on-demand”。也就是说在这个区域外的数据很可能被认为无效。framebuffer_device_t 中的重要成员变量typedef struct framebuffer_device_t {struct hw_device_t common;const uint32_t flags; // 用来记录系统帧缓冲区的标志const uint32_t width; // 用来描述设备显示屏的宽度const uint32_t height; // 用来描述设备显示屏的高度const int stride; // 用来描述设备显示屏的一行有多少个像素点const int format; // 用来描述系统帧缓冲区的像素格式const float xdpi; // 用来描述设备显示屏在宽度上的密度const float ydpi; // 用来描述设备显示屏在高度上的密度const float fps; // 用来描述设备显示屏的刷新频率const int minSwapInterval; // 用来描述帧缓冲区交换前后两个图形缓冲区的最小时间间隔const int maxSwapInterval; // 用来描述帧缓冲区交换前后两个图形缓冲区的最大时间间隔int reserved[8];//保留// 用来设置帧缓冲区交换前后两个图形缓冲区的最小和最大时间间隔int (*setSwapInterval)(struct framebuffer_device_t* window,int interval);// 用来设置帧缓冲区的更新区域int (*setUpdateRect)(struct framebuffer_device_t* window,int left, int top, int width, int height);// 用来将图形缓冲区buffer的内容渲染到帧缓冲区中去int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);// 用来通知 fb 设备图形缓冲区的组合工作已经完成int (*compositionComplete)(struct framebuffer_device_t* dev);void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);int (*enableScreen)(struct framebuffer_device_t* dev, int enable);// 保留void* reserved_proc[6];} framebuffer_device_t;变 量描 述uint32_t flags标志位指示framebuffer 的属性配置uint32_t width; uint32_t height;framebuffer 的宽和高以像素为单位int formatframebuffer 的像素格式比如HAL_PIXEL_FORMAT_RGBA_8888HAL_PIXEL_FORMAT_RGBX_8888HAL_PIXEL_FORMAT_RGB_888HAL_PIXEL_FORMAT_RGB_565 等等float xdpi;float ydpi;x和y轴的密度(pixel per inch)float fps屏幕的每秒刷新频率假如无法正常从设备获取的话默认设置为 60Hzint minSwapInterval;int maxSwapInterval;该 framebuffer 支持的最小和最大缓冲交换时间我们以下面简图来小结对 Gralloc 的分析[图片上传失败...(image-f944da-1542183518291)]四、Android 本地窗口Native Window为OpenGL与本地窗口系统之间搭建了桥梁。整个GUI系统至少需要两种本地窗口面向管理者(SurfaceFlinger)SurfaceFlinger 是系统中所有 UI 界面的管理者需要直接或间接的持有“本地窗口”此本地窗口是FramebufferNativeWindow(4.2 后被废弃)。面向应用程序这类本地窗口是 Surface。正常情况按照 SDK 向导生成 APK 应用程序是采用 Skia 等第三方图形库而对于希望使用 OpenGL ES 来完成复杂界面渲染的应用开发者来说Android 也提供封装的 GLSurfaceView(或其他方式)来实现图形显示。4.1、FramebufferNativeWindowEGL 需要根据本地窗口来为 OpenGL/OpenGL ES 创造环境但是不论哪一类本地窗口都需要和“本地窗口类型”保持一致。// /frameworks/native/opengl/include/EGL/eglplatform.h...typedef HWND EGLNativeWindowType;#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */typedef int EGLNativeDisplayType;typedef void *EGLNativeWindowType;typedef void *EGLNativePixmapType;#elif defined(__ANDROID__) || defined(ANDROID) // Android 系统struct ANativeWindow;struct egl_native_pixmap_t;typedef struct ANativeWindow* EGLNativeWindowType;...#elif defined(__unix__) // unix 系统...typedef Window EGLNativeWindowType;#else#error Platform not recognized#endif...EGLNativeWindowType 在不同系统中对应不同的数据类型而在 Android 中对应的是 ANativeWindow 指针。// /system/core/include/system/window.hstruct ANativeWindow{...const uint32_t flags; // 与 Surface 或 update 有关的属性const int minSwapInterval; // 最小交换时间间隔const int maxSwapInterval; // 最大交换时间间隔const float xdpi; // 水平方向密度 dpiconst float ydpi; // 垂直方向密度 dpiintptr_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);// EGL 通过该接口来申请 bufferint (*dequeueBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer** buffer, int* fenceFd);// EGL 对 buffer 渲染完成后就调用该接口来 unlock 和 post bufferint (*queueBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer, int fenceFd);// 取消一个已经 dequeue 的 bufferint (*cancelBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer, int fenceFd);};ANativeWindow 更像一份“协议”规定了本地窗口的形态和功能。下面来分析 FramebufferNativeWindow 是如何履行“协议”的。(1) FramebufferNativeWindow 构造函数FramebufferNativeWindow 构造函数的功能包括加载 Gralloc 模块(GRALLOC_HARDWARE_MODULE_ID)。打开 fb 和 gralloc(gpu0) 设备打开后由 fbDev 和 grDev 管理。根据设备属性为 FramebufferNativeWindow 赋初值。根据 FramebufferNativeWindow 的实现来填充 ANativeWindow 中的“协议”。其他必要的初始化。所有申请到的缓冲区都由 FramebufferNativeWindow 中的 buffers[] 来记录每个元素是一个 NativeBuffer该类继承了 ANativeWindowBuffer 该类的声明如下// /system/core/include/system/window.htypedef struct ANativeWindowBuffer{...int width;int height;int stride;int format;int usage;void* reserved[2];buffer_handle_t handle; // 代表内存块的句柄void* reserved_proc[8];} ANativeWindowBuffer_t;(2) dequeueBufferint FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,ANativeWindowBuffer** buffer){FramebufferNativeWindow* self getSelf(window);Mutex::Autolock _l(self-mutex);// 从 FramebufferNativeWindow 对象中取出 fb 设备描述符在构造 FramebufferNativeWindow 对象时已经打开了 fb 设备framebuffer_device_t* fb self-fbDev;// 计算当前申请的图形缓冲区在 buffers 数组中的索引同时将下一个申请的 buffe r的索引保存到 mBufferHead 中int index self-mBufferHead;// 如果申请的下一个 buffer 的索引大于或等于 buffer 总数则将下一个申请的 buffer 索引设置为 0这样就实现了对 buffer 数组的循环管理if (self-mBufferHead self-mNumBuffers)self-mBufferHead 0;// 如果当前没有空闲的 buffer即 mNumFreeBuffers 0则线程睡眠等待 buffer 的释放while (!self-mNumFreeBuffers) {self-mCondition.wait(self-mutex);}// 存在了空闲 buffer线程被唤醒继续执行由于此时要申请一块 buffer因此空闲 buffer 的个数又需要减 1self-mNumFreeBuffers--;// 保存当前申请的 buffer 在缓冲区数组中的索引位置self-mCurrentBufferIndex index;// 得到 buffer 数组中的 NativeBuffer 对象指针*buffer self-buffers[index].get();return 0;}dequeueBuffer 函数就是从 FramebufferNativeWindow 创建的包含 2 个图形缓冲区的缓冲区队列 buffers 中取出一块空闲可用的图形 buffer如果当前缓冲区队列中没有空闲的 buffer则当前申请 buffer 线程阻塞等待等待其他线程释放图形缓冲区。mNumFreeBuffers 用来描述可用的空闲图形 buffer 个数index 记录当前申请 buffer 在图形缓冲区队列中的索引位置mBufferHead 指向下一次申请的图形 buffer 的位置由于我们是循环利用两个缓冲区的所以如果这个变量的值超过 mNumBuffers就需要置 0。也就是说 mBufferHead 的值永远只能是 0或者 1。4.2、SurfaceViewSurface 也继承了 ANativeWindowclass Surface: public ANativeObjectBase{ ... }Surface 是面向 Android 系统中所有 UI 应用程序的即它承担着应用进程中的 UI 显示需求。Surface 需要面向上层实现(主要是 Java 层)提供绘制图像的画板。SurfaceFlinger 需要收集系统中所有应用程序绘制的图像数据然后集中显示到物理屏幕上。Surface 需要扮演相应角色本质上还是由 SurfaceFlinger 服务统一管理的涉及到很多跨进程的通信细节。下面来看 Surface 中的关键成员变量成员变量说明sp mGraphicsBufferProducerSurface 核心变量BufferSlot mSlots[32]Surface 内部存储 buffer 的地方BufferSlot 内不包括GraphicsBuffer 和 dirtyRegion当用户 dequeue 时将申请内存Surface 将通过 mGraphicBufferProducer 来获取 buffer这些缓冲区会被记录在 mSlots 中数据中。mGraphicBufferProducer 这一核心成员的初始化流程如下ViewRootImpl 持有一个 Java 层的 Surface 对象(mSurface)。ViewRootImpl 向 WindowManagerService 发起 relayout 请求此时 mSurface 被赋予真正的有效值将辗转生成的 SurfaceControl 通过S urface.copyFrom() 函数复制到 mSurface 中。由此Surface 由 SurfaceControl 管理SurfaceControl 由 SurfaceComposerClient 创建。SurfaceComposerClient 获得的匿名 Binder 是 ISurfaceComposer其服务端实现是 SurfaceFlinger。而 Surface 依赖的 IGraphicBufferProducer 对象在 Service 端的实现是 BufferQueue。class SurfaceFlinger :public BinderService, // 在 ServiceManager 中注册为 SurfaceFlingerpublic BnSurfaceComposer, // 实现的接口却叫 ISurfaceComposerBufferConsumerProducer 是“生产者-消费者”模型中的 3 个参与对象如何协调好它们的工作是应用程序能否正常显示UI的关键。Buffer 是 BufferQueueProducer 是应用程序Consumer 是 SurfaceFlinger。五、BufferQueueTo be continued ....
http://www.sadfv.cn/news/291821/

相关文章:

  • 深圳松岗 网站建设软件开发项目管理工具
  • 深圳住房和建设局网站预约放号网站开发数据交互
  • 摄影网站怎么做数据库中国设备网
  • 网站主页设计优点烟台做网站企业
  • 做jsp网站用哪些软件下载域名查询大全
  • 互联网定制网站网站模版asp
  • 杭州做公司网站哪家好怎么看kk园区视频
  • cvm服务器做网站ppt页面设计模板
  • 网站开发需要学多久深喉咙企业网站生成系统
  • 广州制作网站免费承接网站建设
  • 购买腾讯云 做网站集团公司网站欣赏
  • 如何建设线报网站建设一个私人视频网站
  • wordpress 移动端不显示图片关键词营销优化
  • 兰州网络公司网站wordpress获取友情链接
  • 网站开发的相关技术金融投资理财网站建设
  • 旅游网站策划营销wordpress此网页包含重定向循环
  • 网站首页的尺寸外链seo服务
  • 申请网站空间就是申请域名个人怎么做电影相关的网站
  • 游戏网站策划网站建设的外国文献
  • 阿里巴巴网站怎么做推广方案无锡seo优化
  • 建设通网站是什么性质建立网站需要什么软件
  • 网站定制开发注意事项阿里云网页版入口
  • 有免费的网站做农家院宣传企业网站怎么做毕业设计
  • 英文网站设计公司wordpress百度云加速插件
  • 网站建设设计ppt百度如何建网站群
  • 苏州网站建站推广微信小程序是怎么开发的
  • 刷网站百度关键词软件网站的经营推广
  • 城市建设规划网站网站管理规章制度
  • 广西网站建设开发wordpress 片刻主题
  • 国际贸易网站大全余姚建设公司网站