SDL2源代码分析7:显示(SDL_RenderPresent())
=====================================================
SDL源代码分析系列文章列表:
SDL2源代码分析5:更新纹理(SDL_UpdateTexture())
SDL2源代码分析6:复制到渲染器(SDL_RenderCopy())
SDL2源代码分析7:显示(SDL_RenderPresent())
=====================================================
上一篇文章分析了SDL纹理赋值给渲染目标的函数SDL_RenderCopy()。这篇文章分析SDL显示视频最后的一个函数:SDL_RenderPresent()。
SDL播放视频的代码流程如下所示。
初始化:
SDL_Init(): 初始化SDL。
SDL_CreateWindow(): 创建窗口(Window)。
SDL_CreateRenderer(): 基于窗口创建渲染器(Render)。
SDL_CreateTexture(): 创建纹理(Texture)。
循环渲染数据:
SDL_UpdateTexture(): 设置纹理的数据。
SDL_RenderCopy(): 纹理复制给渲染器。
SDL_RenderPresent(): 显示。
上篇文章分析了该流程中的第6个函数SDL_RenderCopy()。本文继续分析该流程中的最后一个函数SDL_RenderPresent()。
SDL_RenderPresent()
函数简介
SDL使用SDL_RenderPresent()显示画面。SDL_RenderPresent()的原型如下。
void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
参数renderer用于指定渲染器。
函数调用关系图
SDL_RenderPresent()关键函数的调用关系可以用下图表示。
上面的图片不太清晰,更清晰的图片上传到了相册里面:
http://my.csdn.net/leixiaohua1020/album/detail/1794103
把相册里面的图片保存下来就可以得到清晰的图片了。
源代码分析
SDL_RenderPresent()的源代码位于render\SDL_render.c中。如下所示。
void SDL_RenderPresent(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, );
/* Don't draw while we're hidden */
if (renderer->hidden) {
return;
}
renderer->RenderPresent(renderer);
}
从源代码中可以看出,SDL_RenderPresent()调用了SDL_Render的RenderPresent()方法显示图像。
下面我们详细看一下几种不同的渲染器的RenderPresent()的方法。
1. Direct3D
Direct3D 渲染器中对应RenderPresent()的函数是D3D_RenderPresent(),它的源代码如下所示(位于render\direct3d\SDL_render_d3d.c)。
static void D3D_RenderPresent(SDL_Renderer * renderer)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
HRESULT result;
if (!data->beginScene) {
IDirect3DDevice9_EndScene(data->device);
data->beginScene = SDL_TRUE;
}
result = IDirect3DDevice9_TestCooperativeLevel(data->device);
if (result == D3DERR_DEVICELOST) {
/* We'll reset later */
return;
}
if (result == D3DERR_DEVICENOTRESET) {
D3D_Reset(renderer);
}
result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
if (FAILED(result)) {
D3D_SetError("Present()", result);
}
}
从代码中可以看出,该函数调用了2个最关键Direct3D的API:
IDirect3DDevice9_EndScene():结束一个场景。
IDirect3DDevice9_Present():显示。
2. OpenGL
OpenGL渲染器中对应RenderPresent()的函数是GL_RenderPresent(),它的源代码如下所示(位于render\opengl\SDL_render_gl.c)。
static void GL_RenderPresent(SDL_Renderer * renderer)
{
GL_ActivateRenderer(renderer);
SDL_GL_SwapWindow(renderer->window);
}
代码比较简单,只有两行。关键的显示函数位于SDL_GL_SwapWindow()函数中。下面看一下SDL_GL_SwapWindow()的代码(位于video\SDL_video.c。感觉这里调用关系稍微有点乱…)。
void SDL_GL_SwapWindow(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, );
if (!(window->flags & SDL_WINDOW_OPENGL)) {
SDL_SetError("The specified window isn't an OpenGL window");
return;
}
if (SDL_GL_GetCurrentWindow() != window) {
SDL_SetError("The specified window has not been made current");
return;
}
_this->GL_SwapWindow(_this, window);
}
从上述代码中可以看出,SDL_GL_SwapWindow()调用了SDL_VideoDevice的GL_SwapWindow()函数。我们看一下在“Windows视频驱动”的情况下,该函数的代码。在“Windows视频驱动”的情况下,调用GL_SwapWindow()实际上是调用了WIN_GL_SwapWindow()函数。看一下WIN_GL_SwapWindow()函数的代码(位于video\windows\SDL_windowsopengl.c)。
void WIN_GL_SwapWindow(_THIS, SDL_Window * window)
{
HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
SwapBuffers(hdc);
}
代码中调用了简单的一个函数SwapBuffers(),完成了显示功能。
3. Software
Software渲染器中对应RenderPresent()的函数是SW_RenderPresent(),它的源代码如下所示(位于render\software\SDL_render_sw.c)。
static void SW_RenderPresent(SDL_Renderer * renderer)
{
SDL_Window *window = renderer->window;
if (window) {
SDL_UpdateWindowSurface(window);
}
}
从代码中可以看出,SW_RenderPresent()调用了一个函数SDL_UpdateWindowSurface()。我们看一下SDL_UpdateWindowSurface()的代码(位于video\SDL_video.c)。
int SDL_UpdateWindowSurface(SDL_Window * window)
{
SDL_Rect full_rect;
CHECK_WINDOW_MAGIC(window, -1);
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = window->w;
full_rect.h = window->h;
return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
}
SDL_UpdateWindowSurface()又调用了另一个函数SDL_UpdateWindowSurfaceRects()。继续看SDL_UpdateWindowSurfaceRects()的代码。
int SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
int numrects)
{
CHECK_WINDOW_MAGIC(window, -1);
if (!window->surface_valid) {
return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
}
return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
}
SDL_UpdateWindowSurfaceRects()调用了SDL_VideoDevice的UpdateWindowFramebuffer()函数。在“Windows视频驱动”的情况下,相当于调用了WIN_UpdateWindowFramebuffer()。我们看一下该函数的代码(位于video\windows\SDL_windowsframebuffer.c)
int WIN_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
BitBlt(data->hdc, 0, 0, window->w, window->h, data->mdc, 0, 0, SRCCOPY);
return 0;
}
经过一系列的寻找之后,终于找到了Software渲染器显示视频的“源头”:BitBlt()函数。
SDL2源代码分析7:显示(SDL_RenderPresent())的更多相关文章
- SDL2源代码分析8:视频显示总结
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- SDL2源代码分析6:复制到渲染器(SDL_RenderCopy())
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- SDL2源代码分析5:更新纹理(SDL_UpdateTexture())
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- SDL2源代码分析4:纹理(SDL_Texture)
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- SDL2源代码分析3:渲染器(SDL_Renderer)
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- SDL2源代码分析2:窗口(SDL_Window)
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- SDL2源代码分析1:初始化(SDL_Init())
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- 转:SDL2源代码分析
1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...
- SDL2源代码分析
1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...
随机推荐
- 安装yum源和gcc编译器遇到的问题
这两天我试着在VMware虚拟机里安装gcc,遇到了不少问题 1. 安装yum源 我搭建的是光盘yum源(有两种方法搭建yum源,另外一种是网络yum源,但至今没弄懂我的网络yum源为什么不成功) ...
- jquery post跨域请求数据
原先一直以为要实现跨域请求只能用jsonp,只能支持GET请求,后来了解到使用POST请求也可以实现跨域,但是需要在服务器增加Access-Control-Allow-Origin和Access-Co ...
- windows server 2003 远程桌面最大连接数调整与windows 2008远程桌面后,本地帐号自动锁定
调整windows server 2003 最大远程连接数的步骤如下: 第1步.开始-->控制面板-->添加或删除程序-->添加/删除windows组件-->选择"终 ...
- expect IDENTIFIER, actual IDENTIFIER 处理
涉及到注入数据库的报错,这是很常见的了. 但是期望IDENTIFIER,实际IDENTIFIER 的报错,你们知道是什么意思吗? 我已开始看到的时候,是mybatis报错发神经了,报错了报错.再跑一次 ...
- 阿里云部署mongdb(CentOS)
配置包管理系统 (yum). Xshell登录Linux查看操作系统版本信息 lsb release -a 可以在官网选择对应的版本 :官网的安装指导文档http://docs.mongodb.org ...
- Page Object设计模式实践
Page Object模式是使用Selenium的广大同行最为公认的一种设计模式.在设计测试时,把元素和方法按照页面抽象出来,分离成一定的对象,然后再进行组织. Page Object模式,创建一个对 ...
- MySQL LIKE 子句
MySQL LIKE 子句 我们知道在MySQL中使用 SQL SELECT 命令来读取数据, 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录. WHERE 子句中可以使用 ...
- Bootstrap3 代码-代码块
多行代码可以使用 <pre> 标签.为了正确的展示代码,注意将尖括号做转义处理. <p>Sample text here...</p> <pre>< ...
- mongo 存储过程
摘要 本文主要介绍mongo存储过程,mongo 存储过程其实就是JS方法,然后通过eval 方法来执行,但是这个方法在3.0 depreate了,也就是在未来的版本,这个功能可能不提供了.从目前的j ...
- python 反人类函数式编程模拟while和if控制流
比如下面这个简单明了的命令式程序,它不断捕捉用户输入的内容,然后对其求和.直到用户输入一个以'0'开头的字符串,停止捕捉. while 1: line = input() ': print(sum(m ...