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()性能。

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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 关于用户路径分析模型_spark用户行为路径

    关于用户路径分析模型_spark用户行为路径在网页或者营销渠道中,用户行为模型有比较多,基于渠道的,笔者觉得有:渠道类型渠道重要性渠道跳转与流失单渠道,多节点路径分析,漏斗功能多渠道归因分析这里多渠道指的是,单渠道多节点的场景比较好理解,就是进入某个web\小程序,在不同页面之间进行跳转,多渠道这里比较多的就是,同一用户在不同的较大的场景下的流转,比如在小红书种草->微信好友推荐->淘宝上买了。归因分析是通过一定的逻辑方法,计算每个渠道、或者触点对最终结果贡献程度的方法。有一套合理

    2022年8月24日
    11
  • hashmap底层实现原理和源码分析(python底层源码)

    HashMap是Java开发中常用的集合,那么从我们创建一个空集合到,put添加、get获取元素经历了那些步骤呢?说明:以下源码基于JDK1.7,32位0.HashMap底层的数据结构是数组加链表的形式,存储结构如下图:1.创建一个新的HashMap集合的构造函数://初始默认数组的大小staticfinalintDEFAULT_INITIAL_CAPACITY=1<<…

    2022年4月16日
    48
  • Kinect的学习笔记发展(一)Kinect引进和应用

    Kinect的学习笔记发展(一)Kinect引进和应用

    2021年12月17日
    43
  • spring boot 中使用 jpa以及jpa介绍

    最近在项目中使用了一下jpa,发现还是挺好用的。这里就来讲一下jpa以及在springboot中的使用。在这里我们先来了解一下jpa。1.什么是jpa呢?JPA顾名思义就是JavaPersistenceAPI的意思,是JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。2.jpa具有什么优势?2.1标准化JPA是JCP组织发布的Java

    2022年4月5日
    54
  • MVC3和MVC4中CRUD操作

    MVC3和MVC4中CRUD操作

    2022年1月23日
    48
  • python数字转字符串固定位数_python-将String转换为64位整数映射字符以自定…「建议收藏」

    python数字转字符串固定位数_python-将String转换为64位整数映射字符以自定…「建议收藏」您将4个不同“数字”的字符串解释为数字,因此以4为基数.如果您有一串实际数字,范围为0-3,则可以让int()真正快速地生成一个整数.defseq_to_int(seq,_m=str.maketrans(‘ACGT’,’0123′)):returnint(seq.translate(_m),4)上面的函数使用str.translate()用匹配的数字替换4个字符中的每个字符(我使用静态s…

    2022年9月25日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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