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>中 ...
随机推荐
- nginx负载均衡及详细配置
接上篇nginx配置,然后再准备两台web服务器: nginx服务器:192.168.0.241 web1:192.168.0.141 web2:192.168.0.142 一.两台web服务器先安装 ...
- Java连接FTP成功,但是上传是失败,报错:Connected time out
Java代码在本机上传文件到FTP服务器的时候成功,但是部署到测试服务器的时候出现,连接FTP成功但是上传失败,并且报Connected time out错误: 测试服务器和FTP服务都在阿里云上:( ...
- [坑况]饿了么你是这样的前端——vue+element ui 【this dependency was not found:'element-ui/lib/theme-chalk/index.css'】
element ui 坑况:今日pull代码,潇洒npm run dev ,被告知:this dependency was not found:'element-ui/lib/theme-chalk/ ...
- Linux系统之TroubleShooting(故障排除)(转)
尽管Linux系统非常强大,稳定,但是我们在使用过程当中,如果人为操作不当,仍然会影响系统,甚至可能使得系统无法开机,无法运行服务等等各种问题.那么这篇博文就总结一下一些常见的故障排除方法,但是不可能 ...
- 一个成功的 Git 分支模型(适用于商业应用开发)
在这篇文章中,我将推广一下大约一年前我介绍过的一些项目(公私皆有)中使用的开发模型,它们的结果都非常成功.有段时间我非常想写出来分享一下,但是我至今才抽出时间来.我不会言及任何项目细节,仅讨论分支策略 ...
- 一个页面从输入url到页面加载显示完成,中间都经历了什么
第一种解释: 一般会经历以下几个过程: 1.首先,在浏览器地址栏中输入url 2.浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容.若没有,则跳到第三步操作. 3 ...
- 预习视频day1
课前预习 编译型和解释型语言优缺点 python2,pyhon3的宏观(大环境下)区别 python的种类 python编码规则 变量命名规范,常量 注释 1.编译型语言:将源码一次性转化为二进制代码 ...
- JavaScript中的事件模型
JS中的事件 1.鼠标事件 onclick ondbclick onmouseover onmouseout 2.HTML事件 onload onunload onsubmit ...
- Mac入门
Mac入门 桌面 windows桌面有图标罗列 Mac桌面有Dock 菜单栏 感觉上和Windows系统的底部菜单栏有点像,但是却略有不同,Mac的菜单栏默认在顶部 左侧的一些功能是固定不变的,跟随当 ...
- Programming In Scala笔记-第十五章、Case Classes和模式匹配
本章主要分析case classes和模式匹配(pattern matching). 一.简单例子 接下来首先以一个包含case classes和模式匹配的例子来展开本章内容. 下面的例子中将模拟实现 ...