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


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

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


     
    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()的源码位于renderSDL_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()。它的源码例如以下所看到的(位于renderdirect3dSDL_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(),它的源码例如以下所看到的(位于renderopenglSDL_render_gl.c)。

    static void GL_RenderPresent(SDL_Renderer * renderer)
    {
    GL_ActivateRenderer(renderer);
    
    
        SDL_GL_SwapWindow(renderer->window);
    }

    代码比較简单,仅仅有两行。关键的显示函数位于SDL_GL_SwapWindow()函数中。以下看一下SDL_GL_SwapWindow()的代码(位于videoSDL_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()函数的代码(位于videowindowsSDL_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(),它的源码例如以下所看到的(位于rendersoftwareSDL_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()的代码(位于videoSDL_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()。

    我们看一下该函数的代码(位于videowindowsSDL_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()性能。


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

  • 相关阅读:
    oracle安装
    Jmeter入门篇
    DOS常用命令
    SpringBoot中使用JNnit4(一)之Mockito的使用
    SpringBoot中使用JNnit4(入门篇)
    SpringBoot搭建
    SpringBoot中集成Swagger2
    jpa使用过程中出现问题记录[持续更新]
    Python逆向(五)—— Python字节码解读
    Python逆向(四)—— Python内置模块dis.py源码详解
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4795183.html
Copyright © 2020-2023  润新知