SDL2来源分析7:演出(SDL_RenderPresent())

SDL2来源分析7:演出(SDL_RenderPresent())

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

=====================================================

SDL源代码分析系列文章上市:

SDL2源码分析1:初始化(SDL_Init())

SDL2源码分析2:窗体(SDL_Window)

SDL2源码分析3:渲染器(SDL_Renderer)

SDL2源码分析4:纹理(SDL_Texture)

SDL2源码分析5:更新纹理(SDL_UpdateTexture())

SDL2源码分析6:拷贝到渲染器(SDL_RenderCopy())

SDL2源码分析7:显示(SDL_RenderPresent())

SDL2源码分析8:视频显示总结

=====================================================

上一篇文章分析了SDL纹理赋值给渲染目标的函数SDL_RenderCopy()。

这篇文章分析SDL显示视频最后的一个函数:SDL_RenderPresent()。

SDL2来源分析7:演出(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()关键函数的调用关系能够用下图表示。

 
SDL2来源分析7:演出(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()性能。

版权声明:本文博主原创文章。博客,未经同意不得转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/117099.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 【SSD目标检测】3:训练自己的数据集「建议收藏」

    【SSD目标检测】3:训练自己的数据集「建议收藏」前言:上一章已经详细介绍了SSD——多目标定位检测识别算法,该框架是Google开源的代码,所以自然有很多前辈做改进了。我也不过是站在前辈的肩膀上,这一章就是讲解如何训练自己的数据集,让SSD框架识别。源码也无偿奉上了哦!–—-—-—-—-—-—-—-—-—-—-—-—–—-—-—-—-—-—-—-——-—-—-—-—-—-—-—-—-—-—-—-—-—-——-需要的链接处(待完善)–…

    2022年10月22日
  • vue 图片上传 图片展示 bootstrap

    vue 图片上传 图片展示 bootstrap效果图html…………<--key=idPicUrl-->

  • apache 虚拟主机配置详解_如何配置虚拟主机

    apache 虚拟主机配置详解_如何配置虚拟主机apache2.4部分conf/httpd.conf1,Includeconf/extra/httpd-vhosts.conf,去掉注释;2,DocumentRoot"D:\apachespace",增加注释;3,所有&lt;directory&gt;&lt;/directory&gt;,增加注释;4,*ServerName :80,增加注释;conf/extra/httpd-vhosts.c…

  • pycharm安装教程2020.3.4_pycharm安装后无解释器

    pycharm安装教程2020.3.4_pycharm安装后无解释器第一步安装解释器,第二步安装pycharm1第一步安装解释器1.1什么是解释器:??就是将Python程序翻译成为计算机可以识别的01代码1.2安装解释器:解释器安装地址:https://www.python.org/downloads/release/python-372根据自己的操作系统安装适配的解释器:这里以Windows为例注意安装的时候我们需要需注意吧解释器添加到环境变量里面双击开始安装勾选addpythontopath,如果安装的时候没有勾选,请安装结束以后按

  • 微信小程序获取表单数据_小程序表单提交数据到哪里

    微信小程序获取表单数据_小程序表单提交数据到哪里微信小程序使用模板消息需要使用支付prepay_id或表单提交formId,要获得formId需要在form标签中声明属性report-submit="true"&#1

  • CNN训练前的准备:pytorch处理自己的图像数据(Dataset和Dataloader)

    CNN训练前的准备:pytorch处理自己的图像数据(Dataset和Dataloader)pytorch的torchvision给我们提供了很多已经封装好的数据集,但是我们经常得使用自己找到的数据集,因此,想要得到一个好的训练结果,合理的数据处理是必不可少的。

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号