一,概念解释

什么是渲染?这是高大上的说法,翻译成正常语言,就是把图像缓冲区的数据显示到屏幕的过程,就是渲染。

原理说白了很简单,但实际操作中有太多因素需要考量。

OS/硬件提供的加速机制/解码后图像数据格式/字幕数据的格式。。。。

刚开始查找资料时,我总是试图找到所有的渲染方式,后来发现这实在错的比较离谱。因为说到底,这是一个图形学的问题:如何在计算机屏幕上绘图。不同的图形库有不同的绘图接口,太多的厂商有自己的图形库,根本不可能穷举出所有的图形库。我们只能讨论一些相对主流的方式。另外去找所有的图形渲染方式也是没有意义的,因为他们的理念大体上又是差不多的,只是API不同。唯一的要求是,你要画的足够快,因为如果你想一张张图像看起来是连续的,那么速度要达到24帧以上。当然,对于一些特殊应用,比如视频会议,15帧的速度不会让人有卡顿感,这个帧数也完全Ok。

二,问题的概念空间与一些解决方案

说完了,回到开始的问题,如何渲染。

这里又有两个问题需要解释:

1.图像缓冲区里面的数据是什么样的?RGB还是YUV,又是哪种RGB,哪种YUV?

2.如何把缓冲区的数据搬到屏幕?CPU,普通的2D加速,还是GPU,用GPU时,是OpenGL还是D3D?

第一个问题:

这里我们只说几个常见的。这里的图像缓冲区,特指解码后的数据,而非对应屏幕显示的那块。因为对于目前的真彩色显示器来说,屏幕对应的数据只有一种,就是RGB888。无论你给到的数据如何,传输到屏幕点亮色点的数据都会被驱动/硬件/总线给处理成这种格式。这是由屏幕的物理属性决定的,物理屏幕就是TTL电路点亮的一堆小灯。

常见的有RGB888/RGB565/YV12/I420p。

ps:实际解码器出来的都是YUV数据,如果得到RGB数据,通常也都是解码器后面加了一步YUV2RGB的转换,不过通常我们也会把这块功能算成是解码器的。不过不绝对,需要看lib的作者如何看待这个问题。

第二个问题:

1.纯粹的CPU(现在貌似很少有这种了),就是一个一个的往屏幕上画点了,一个pixel一个pixel的画,不太常见,也比较慢,因为操作内存太过频繁。有些库封装了overlay/bitblt等操作,虽然看起来像CPU在做,实际上已经调用了2D加速了。

2.用2D加速的

Overlay

以前看资料,老看到Overlay什么的东东,找了很久,似乎也没有谁专门给出一个标准定义,说什么才叫Overlay。说下我的理解,Overlay通常是一个硬件意义上的名词,因为屏幕上的东西,通常有很多层次,Overlay可以做的就是直接把这层放到所有图层上面。通常的用法是YUV数据直接给屏幕,Overlay硬件会替你做YUV2RGB转换。这个词貌似来自ms的directshow,有什么主表面,离屏表面,overlay之分,实际上就是硬件图层的意思。貌似有些硬件可以支持RGB Overlay,很少见。有些图形硬件可以支持多个Overlay图层,也就是说,你可以使用Overlay同时在屏幕上显示几个不同的视频。视频监控的宫格多半就是这样来的。

嵌入式里面,Overlay还有一种常见做法,比如:一些有很高优先级的提示,要给用户,这时就得把普通的提示框做成YUV的,然后提示显示出来,可以直接盖到所有的图层上去。

关于模拟Overlay,呵呵,凌乱了吧,实际上就是接口叫xxxOverlay,实际上是把YUV转成RGB,然后画点的方式显示,SDL中有这种接口。

最常见的Overlay类型是YV12,一是数据量小,二视频压缩的标准有关,因为Mpeg2/h264等标准,都强制要求这种格式,当然这两点是相符相成的。

优点就是快,缺点也比较明显,如果要做视频图像后处理,比如放大缩小,人脸识别等操作,会比较麻烦。

Bitblt

比较常见的2d加速方式,把内存数据的数据直接传输到屏幕,或者搬到另一块内存中(内存拷贝)。

blit是个有渊源的词语,这个词的本意就是块(block)移动(transfer)的缩写blt,因为这个缩写缺少元音不好读,所以后来加上了i,就变成blit。

实际上我搞不清这和DMA有什么区别,希望有人指点一下区别。难道区别仅仅是BitBlt可以同时缩放/旋转,而DMA不能?

另外与Android提出的CopyBit有区别么?我看没啥区别啊。

优点是在内存拷贝时,可以同时做缩放/旋转,缺点是只能用RGB格式。

(2014.03.30更新:

1.查了一些资料,看了一下bitblt实现原理,除去缩放/旋转的算法之外,涉及到内存搬移的应该是调用memcpy实现的,从这个角度来看,是用到了dma功能的,看来是没有什么区别的。只是memcpy的实现通常是考验硬件性能和程序员水平的地方。

2.从copybit规定的interface来看,实际就是bitblt,估计只是bitlt这个单词是ms提出的,google觉得不爽,起个新名子而已。

实际android到了4.0之后,已经取消掉了copybit HAL module,2d加速全部采用了GPU操作。在android 2.3代码里还残存着一些痕迹。)

3.GPU

其实OpenGL和D3D就是GPU在软件接口层面上的抽象。用opengl和d3d显示视频通常都是用texture方式来实现的,把一帧一帧图像生成纹理数据,然后贴到vertex上去。

简单解释一下就是,先建立顶点坐标,再建立纹理坐标,再把顶点坐标与纹理坐标一一映射,完成贴图。具体的要看一下OpenGL编程书籍了,这实在是一个复杂的题目。

先把屏幕四个点当成两个三角形(因为3d api用三角形来表示平面,当然多边形也支持,但遇到不支持的情况,用两个三角形就可以组成一个矩形),把数据的一个点一个点对应到这个矩形上,就显示了一帧。因为GPU通常是并行操作,像素生成率通常也足够高。

这块了解不够多。不多说了。

三,常见的库

这个通常又与OS有关系了,讨厌死了。

先说Windows,又分几个层次。先从底层说起。

纯api就是

Windows GDI,windows平台对图形硬件的抽象,很多年了,比较成熟,效率应该比较OK。

DirectDraw,这个封装的就是Overlay的操作接口,但是微软已经停止支持了,不建议使用。

D3D,微软的3D API,门槛比较高一些。

Direct2D,层级和GDI貌似差不多,Win7时代出现新玩意,看过一些资料,说这套API是取代GDI的,不过貌似微软已经尾大不调了。

上述几个API,VLC播放器里面都有一些具体的实现,可以看一下下。

另外就是DirectShow中的filter级别的。

VMR7,底层用DirectDraw封装的,资料说只有XP好用,更老更新的平台都不支持。

VMR9,底层用D3D实现,还在支持。

EVR,vista时代出现的东西,好像也是D3D做的(微软你到底要闹哪样。。。。这么多选择)

其实dshow还有什么overlay mixer,video render之类的filter,我觉得都没有跑出我上面说的范围。

说Linux吧。

X-window的api算一种,虽然一直用X,但对X的超多bug也很不满,从来没看过。。。(吐血)

DirectFB,通常在嵌入式平台才会使用,桌面平台上极少见到,抽象了几乎所有的2D加速机制,接口操作和DirectDraw几乎一模一样。

直接用FrameBuffer提供的接口,嵌入式多见,不过通常这些接口里面已经封装了Overlay/BitBlt接口,不要只见树木不见森林就好。

跨平台的

SDL,算是比较常用的,API的使用还比较简单,但是看代码真心觉得太乱了,不过人家是跨平台的,代码乱真心是难以避免。

最后有个比较惨痛的事实,因为你在写播放器时,这些API可能都没用,因为。。。。。你的图形库会再给你提供一套。。。。好吧,懂得原理,很多事情会简单一些。

6,render的一些概念和可用库的更多相关文章

  1. linux下一些可用库

    1. musl: 为了夸平台,采用小巧玲珑的libc进行静态编译.

  2. C++面试基础概念之动态库篇

    编写DLL所学所思(1)——导出函数 编写DLL所学所思(2)——导出类 C++ DLL导出类 知识大全 C++类库开发详解

  3. jQuery学习笔记之概念(1)

    jQuery学习笔记之概念(1) ----------------------学习目录-------------------- 1.概念 2.特点 3.选择器 4.DOM操作 5.事件 6.jQuer ...

  4. 最新的jQuery插件和JavaScript库

    每一个前端开发人员很清楚的重要性和功能的JavaScript库提供.它提供了一个简单的接口,用于构建快速动态的接口,而无需大量的代码. 谢谢你的超级从事jQuery开发者社区,人始终是创造新的和令人惊 ...

  5. c++标准库

    Technical Report 1不是正式的库只是一个草案,作为C++ 2003标准的附加库被大多数编译器厂商所支持,它是个过渡性质的库,其实现将会作为C++11标准的一部分.很多编译器对C++11 ...

  6. linux库

     将库函数打包成一个单元使之能够在运行时被多个进程共享的技术,这种技术能够节省磁盘空间和RAM. 一. 静态库:1.概念:    静态库就是一些目标文件的集合,以.a结尾.静态库在程序链接的时候使用, ...

  7. boost库的安装,使用,介绍,库分类

    1)首先去官网下载boost源码安装包:http://www.boost.org/ 选择下载对应的boost源码包.本次下载使用的是 boost_1_60_0.tar.gz (2)解压文件:tar - ...

  8. Linux 静态库与共享库的使用

    申明: 正如题如示,本篇讲的是Linux下是静态库与共享库,而Window下的动态链接库详细情况可见这篇文章:windows动态链接库 DLL 浅析.虽然原理,思想差不多,但是细节却各有不同. 一.静 ...

  9. 在linux下制作静态库和动态链接库的方法

    静态库 .o文件的集合 制作 ar -cr libxxx.a xxx1.o xxx2.o xxx3.o ... 编译 gcc main.c -l xxx [-L 库路径] (如果不加-L则在标准库路径 ...

随机推荐

  1. Redhat YUM U盘源配置

    Redhat YUM U盘源配置 1)在U盘创建目录 #mkdir /yum/Server 并从光盘Server.Packages 目录的所有文件拷贝到/yum/Server 2)安装 creater ...

  2. Magento模型和ORM基础

    对于任何一个MVC架构,模型(Model)层的实现都是占据了很大一部分.对于Magento来说,模型占据了一个更加重要的位置,因为它常常包含了一部分商业逻辑代码(可以说它对,也可以说它错).这些代码在 ...

  3. ThinkPHP函数详解:import方法

    import方法是ThinkPHP框架用于类库导入的封装实现,尤其对于项目类库.扩展类库和第三方类库的导入支持,import方法早期的版本可以和java的import方法一样导入目录和通配符导入,后来 ...

  4. Zepto源码解读

    /*******************************************************************************Zepto核心和dom操作******* ...

  5. Android的Manifest配置文件介绍

    一.关于AndroidManifest.xml       AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(ac ...

  6. unity3d最新面试题与参考答案汇总

    1.在类的构造函数前加上static会报什么错?为什么? 构造函数格式为 public+类名,如果加上static会报错(静态构造函数不能有访问修饰符)原因:静态构造函数不允许访问修饰符,也不接受任何 ...

  7. MVC小系列(七)【分部视图中的POST】

    MVC小系列(七)[分部视图中的POST] 在PartialView中进行表单提交的作用:1 这个表单不止一个地方用到,2 可能涉及到异步的提交问题 这两种情况都可能需要把表单建立在分部视图上, 使用 ...

  8. ios 可变参数(va_list,va_start,va_end)

    例如:UIAlertView的init方法中的otherButtonTitles:(NSString *)otherButtonTitles, ...等多个可变参数. ios实现传递不定长的多个参数的 ...

  9. maven打war包注意之xml、properties文件没打进去解决方法

    maven项目在ide中编译出的war包一般不会有很多问题. 但是经过集成环境打war包会出现war包中打不进xml.properties等文件.这样打war包不会报错,但是war包放进tomcat中 ...

  10. java中的JSON对象的使用

    申明:没工作之前都没听过JSON,可能是自己太菜了.可能在前台AJAX接触到JSON,这几天要求在纯java的编程中,返回JSON字符串形式. 网上有两种解析JSON对象的jar包:JSON-lib. ...