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来源分析3:渲染(SDL_Renderer)
===================================================== SDL源代码分析系列文章上市: SDL2源码分析1:初始化(SDL_Init()) SDL2 ...
- SDL2源代码分析7:显示(SDL_RenderPresent())
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- 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 ...
随机推荐
- PHP实现队列(Queue)数据结构
队列(Queue),是一种特殊的先进先出线性表,其只能在前端进行删除操作(一般称为出队),在后端进行插入操作(一般称为入队).进行删除操作的端称为队头,进行插入操作的端称为队尾.队列,是按照先进先出或 ...
- 怎样从host之外连接到docker container
启动docker的时候的指令使用 sudo docker -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock -d & 这样就能使dock ...
- HttpClient4的使用,模拟浏览器登陆新浪微博,发表微博和文字+图片微博
HttpClient4,最原始的需求就是使用其来模拟浏览器想服务器发起http请求,当然,他的功能不止于此,但是我需要的就是这个功能而已,jdk也有其自带的类似的api:UrlConnection,效 ...
- js检测浏览器中是否安装了flash播放插件
这两天工作中需要在网页中嵌入flash小游戏,我使用的是swfobject.js version:1.5.其他方面都很好,唯独版本检测这里一直没有搞通,后来实在无奈之下,改用js来检测浏览器的flas ...
- shell加法
echo 1597+1469+1468+2591+1260+1068+1019+993|bc http://bbs.chinaunix.net/thread-161085-1-1.html http: ...
- Java并发编程(您不知道的线程池操作)
Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...
- cocos2d-x3.0 实现HTTP请求GET、POST
HTTP请求实现 把以下代码拷贝到新创建的project中就能看到效果 HelloWorldScene.h #include "cocos2d.h" /*记得要引头文件*/ #in ...
- 用户手册User Guide的写法
下面的内容仅代表个人观点,是在工作中总结出来的,如果有错误之处,还请指教. 转载请注明来自博客园---”邦邦酱好“: http://www.cnblogs.com/bangbangjiang/p/36 ...
- springMVC整合JAXB
一.背景 由于项目中要用到将Java对象转为xml返回给调用者.选择使用JAXB,由于它是JDK自带的.不须要引入其它Jar包 它提供了高速而简便的方法将xml和对象互转的方法. 二.重要Class和 ...
- 利用Sambaserver在Ubuntu系统和Win7系统间共享目录
1 介绍 如今是网络化的时代,我们每一个人要更好的发展.离不开网络化.信息化的支持.利用网络的支持.在不同的操作系统间共享文件等信息,是计算机专业学生必备的一项技能. 本文所讲的就是怎样建立.设置.链 ...