SDL视频播放学习记录
SDL标准库组成
SDL_image—支持时下流行的图像格式:BMP、PPM、XPM、 PCX、GIF、JPEG、PNG、TGA。
SDL_mixer—更多的声音输出函数以及更多的声音格式支持。
SDL_net—网络支持。
SDL_ttf—TrueType字体渲染支持。
SDL_rtf—简单的RTF渲染支持。
SDL子系统
SDL将功能分成下列数个子系统(subsystem):
Video(图像)—图像控制以及线程(thread)和事件管理(event)
Audio(声音)—声音控制
Joystick(摇杆)—游戏摇杆控制
CD-ROM(光盘驱动器)—光盘媒体控制
Window Management(视窗管理)-与视窗程序设计集成
Event(事件驱动)-处理事件驱动
SDL渲染流程
**初始化:
SDL_Init(): 初始化SDL。
SDL_CreateWindow(): 创建窗口(Window)。
SDL_CreateRenderer(): 基于窗口创建渲染器(Render)。
SDL_CreateTexture(): 创建纹理(Texture)。
循环渲染数据:
SDL_UpdateTexture(): 设置纹理的数据。
SDL_RenderCopy(): 纹理复制给渲染器。
SDL_RenderPresent(): 显示。**
SDL初始化
fun:初始化函数
param:SDL_INIT_TIMER:定时器
SDL_INIT_AUDIO:音频
SDL_INIT_VIDEO:视频
SDL_INIT_JOYSTICK:摇杆
SDL_INIT_HAPTIC:触摸屏
SDL_INIT_GAMECONTROLLER:游戏控制器
SDL_INIT_EVENTS:事件
SDL_INIT_NOPARACHUTE:不捕获关键信号(这个不理解)
SDL_INIT_EVERYTHING:包含上述所有选项
(对应设备,如:SDL_VideoDevice)Err: SDL_SetError()
int SDLCALL SDL_Init(Uint32 flags)
(关于初始化流程的小说明)
1.判断传入的Flag与子系统内的宏定义,决定是否初始化子系统
2.调用函数SDL_PrivateShouldInitSubsystem()检查每个子系统是否需要初始化
3.每个初始化后调用函数SDL_PrivateSubsystemRefCountIncr(),增加子系统的引用计数
4.下表列出各个子系统的初始化函数
子系统名称 | 函数 |
---|---|
AUDIO(音频) | SDL_AudioInit() |
VIDEO(视频) | SDL_VideoInit() |
TIMERS(定时器) | SDL_TicksInit(),SDL_TimerInit() |
EVENTS(事件) | SDL_StartEventLoop() |
JOYSTICK(摇杆) | SDL_GameControllerInit() |
HAPTIC(触摸屏) | SDL_HapticInit() |
子系统初始化(如视频)
1.使用结构体VideoBootStrap创建SDL_VideoDevice
(SDL中有一个VideoBootStrap类型的静态数组bootstrap。用于存储SDL支持的视频驱动程序。多平台支持)
2.根据平台选择创建函数,如:windows ——WIN_CreateDevice()
3.创建对象SDL_VideoDevice
4.根据创建的设备执行VideoInit()(Win_VideoInit())
期中包含三个函数WIN_InitModes(),WIN_InitKeyboard(),WIN_InitMouse(),分别用于获得系统中的显示设备信息,初始化键盘,鼠标
SDL创建窗口
fun:创建一个SDL_Window,指定播放窗口
param:title :窗口标题
x :窗口位置x坐标。也可以设置为SDL_WINDOWPOS_CENTERED或SDL_WINDOWPOS_UNDEFINED。
y :窗口位置y坐标。同上。
w :窗口的宽
h :窗口的高
flags :支持下列标识。包括了窗口的是否最大化、最小化,能否调整边界等等属性。
::SDL_WINDOW_FULLSCREEN,
::SDL_WINDOW_OPENGL,
::SDL_WINDOW_HIDDEN,
::SDL_WINDOW_BORDERLESS,
::SDL_WINDOW_RESIZABLE,
::SDL_WINDOW_MAXIMIZED,
::SDL_WINDOW_MINIMIZED,
::SDL_WINDOW_INPUT_GRABBED,
::SDL_WINDOW_ALLOW_HIGHDPI.return: 返回创建完成的窗口的ID。如果创建失败则返回0。
SDL_Window * SDLCALL SDL_CreateWindow(const char *title,int x, int y, int w, int h, Uint32 flags);
(关于创建窗口的内部流程小说明)
进行一些保证平台兼容性的工作。
调用SDL_calloc()为SDL_Window结构体分配一块内存。同时设置一些基本属性,例如窗口的宽高,位置等等。
调用VideoDevice的CreateWindow()方法创建窗口。 ->win32的API,创建时进行优化,如:AdjustWindowRectEx(),SetWindowData()
(SDL中有一个SDL_VideoDevice类型的静态全局变量_this。SDL调用视频驱动的功能都是通过调用该指针完成的。)完成一些收尾工作,如设置标题,全屏窗口,rec。
创建SDL_Render
fun:创建一个SDL_Render渲染器
param:window : 渲染的目标窗口。
index :打算初始化的渲染设备的索引。设置“-1”则初始化默认的渲染设备。
flags :支持以下值(位于SDL_RendererFlags定义中)
SDL_RENDERER_SOFTWARE :使用软件渲染
SDL_RENDERER_ACCELERATED :使用硬件加速
SDL_RENDERER_PRESENTVSYNC:和显示器的刷新率同步
SDL_RENDERER_TARGETTEXTURE :SDL_SetRenderTarget ()函数使用标签,对应须将目标Target添加SDL_TEXTUREACCESS_TARGET标签return:返回创建完成的渲染器的ID。如果创建失败则返回NULL。
SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags);
(关于创建渲染器的小说明)
- 创建基本函数:调用SDL_RenderDriver的CreateRenderer()方法。
struct SDL_RenderDriver
{
SDL_Renderer (*CreateRenderer) (SDL_Window window, Uint32 flags);
/* Info about the renderer capabilities */
SDL_RendererInfo info;
};
(在SDL中有一个全局的SDL_RenderDriver类型的静态数组render_drivers,其中存储了SDL支持的所有渲染器。如:Direct3D,OpenGl,软件渲染器驱动程序SW_RenderDriver)
2.(例如D3D)为SDL_Renderer分配内存
加载Direct3D(9)
加载Direct3D通过函数D3D_LoadDLL()完成。调用该函数可以得到一个IDirect3D9类型的接口(创建Microsoft Direct3D 目标和配置环境的应用方法类)。渲染器接口函数赋值
SDL_Render结构体中有一系列的函数指针,包含了有关渲染器的各种功能。SDL通过调用这些函数指针就可以调用渲染器相应的功能。这是SDL支持多种渲染器的一个重要特点。创建Device
创建Direct3D的Device通过IDirect3D9_CreateDevice()函数来实现。设置渲染状态
设置渲染状态在函数D3D_InitRenderState(D3D_RenderData *data)中完成。创建Shader
创建Shader通过函数IDirect3DDevice9_CreatePixelShader()完成。
创建SDL_Texture
fun:基于渲染器创建一个纹理
param:renderer:目标渲染器。
format :纹理的格式。后面会详述。
access :可以取以下值(定义位于SDL_TextureAccess中)
SDL_TEXTUREACCESS_STATIC :变化极少
SDL_TEXTUREACCESS_STREAMING :变化频繁
SDL_TEXTUREACCESS_TARGET :暂时没有理解
w :纹理的宽
h :纹理的高return:创建成功则返回纹理的ID,失败返回0。
SDL_Texture * SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
(关于纹理创建的小说明)
检查输入参数的合理性。例如像素格式是否支持,宽和高是否小于等于0等等。
新建一个SDL_Texture。调用SDL_calloc()(实际上就是calloc())为新建的SDL_Texture分配内存。
调用SDL_Render的CreateTexture()方法创建纹理。这一步是整个函数的核心。
D3D_CreateTexture()
IDirect3DDevice9_CreateTexture();
GL_CreateTexture ()
创建纹理:glGenTextures(),glBindTexture()
设置参数:glTexParameteri()
SW_CreateTexture ()
SDL_CreateRGBSurface() ————(创建Surface)
更新纹理
fun:SDL使用SDL_UpdateTexture()设置纹理的像素数据。
param:texture:目标纹理。
rect:更新像素的矩形区域。设置为NULL的时候更新整个区域。
pixels:像素数据。
pitch:一行像素数据的字节数。return:成功的话返回0,失败的话返回-1。
int SDLCALL SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch);
(关于更新纹理的小说明)
- 检查输入参数的合理性。例如像素格式是否支持,宽和高是否小于等于0等等。
- 如果是一些特殊的格式,进行一定的处理:
a) 如果输入的像素数据是YUV格式的,则会调用SDL_UpdateTextureYUV()进行处理。
b) 如果输入的像素数据的像素格式不是渲染器支持的格式,则会调用SDL_UpdateTextureNative()进行处理。 - 调用SDL_Render的UpdateTexture()方法更新纹理。这一步是整个函数的核心。
4.渲染器更新纹理细则
(Direct 3D——D3D_UpdateTexture())
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch)
D3D函数调用D3D_UpdateTextureInternal()进行纹理更新,
该函数首先调用IDirect3DTexture9_LockRect()锁定纹理,然后使用SDL_memcpy()将新的像素数据拷贝至纹理(SDL_memcpy()实际上就是memcpy()), 最后使用IDirect3DTexture9_UnlockRect()解锁纹理。
(Software渲染器)
SW_UpdateTexture()
更新渲染器
fun:将纹理数据复制给渲染器
param:renderer:渲染目标。
texture:输入纹理。
srcrect:选择输入纹理的一块矩形区域作为输入。设置为NULL的时候整个纹理作为输入。
dstrect:选择渲染目标的一块矩形区域作为输出。设置为NULL的时候整个渲染目标作为输出。return:成功的话返回0,失败的话返回-1。
int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_Rect * dstrect);
(关于更新渲染器的小说明)
- 检查输入参数的合理性。
- 调用SDL_Render的RenderCopy ()方法复制纹理到渲染目标。这一步是整个函数的核心。
- (Direct3D更新细则)——D3D_RenderCopy()
D3D_ActivateRenderer():激活渲染器。其内部使用Direct3D的API函数IDirect3DDevice9_BeginScene()开始一个D3D的场景。
D3D_SetBlendMode():设置渲染器状态。其内部使用Direct3D的API函数IDirect3DDevice9_SetRenderState()设置渲染器的状态。
D3D_UpdateTextureScaleMode():设置纹理采样方式。其内部调用使用Direct3D的API函数IDirect3DDevice9_SetSamplerState()设置D3D的纹理采样方式。
IDirect3DDevice9_SetTexture():Direct3D的API,用于设置当前启用的纹理。
IDirect3DDevice9_SetPixelShader():Direct3D的API,用于设置使用的像素着色器。
IDirect3DDevice9_DrawPrimitiveUP():Direct3D的API,用于渲染。
上述几个函数中,前3个函数是SDL中的函数,后3个函数是Direct3D的API。 - (Software)——SW_RenderCopy()
显示
fun:显示画面
param:SDL_Renderer 渲染器
void SDL_RenderPresent(SDL_Renderer * renderer)
(关于显示的刷新的显示小说明)
(SDL_RenderPresent()调用SDL_Render的RenderPresent()方法显示图像。)
(Direct3D)–D3D_RenderPresent()
该函数调用了2个最关键Direct3D的API:
IDirect3DDevice9_EndScene():结束一个场景。
IDirect3DDevice9_Present():显示。
(Software)–SW_RenderPresent()
函数调用顺序示意:本函数->SDL_UpdateWindowSurface()->DL_UpdateWindowSurfaceRects()->(SDL_VideoDevice) UpdateWindowFramebuffer()->(Windows视频驱动) WIN_UpdateWindowFramebuffer()->BitBlt()
(之后对该函数进行详细的分析)