SDL2源代码分析3 渲染器(SDL Renderer)

本文主要分析SDL2中的渲染器(SDL_Renderer)及其创建函数SDL_CreateRenderer()。介绍了Direct3D、OpenGL和Software渲染器的创建过程,涉及硬件加速、渲染状态设置和Shader初始化等关键步骤。
摘要由CSDN通过智能技术生成

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

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

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_CreateWindow()。这篇文章继续分析SDL的源代码。本文分析SDL的渲染器(SDL_Renderer)。



SDL播放视频的代码流程如下所示。

初始化: 
SDL_Init(): 初始化SDL。 
SDL_CreateWindow(): 创建窗口(Window)。 
SDL_CreateRenderer(): 基于窗口创建渲染器(Render)。 
SDL_CreateTexture(): 创建纹理(Texture)。 
循环渲染数据: 
SDL_UpdateTexture(): 设置纹理的数据。 
SDL_RenderCopy(): 纹理复制给渲染器。 

SDL_RenderPresent(): 显示。

上篇文章分析了该流程中的第2个函数SDL_CreateWindow()。本文继续分析该流程中的第3个函数SDL_CreateRenderer()。

SDL_Renderer

SDL_Renderer结构体定义了一个SDL2中的渲染器。如果直接使用SDL2编译好的SDK的话,是看不到它的内部结构的。有关它的定义在头文件中只有一行代码,如下所示。

/** *  \brief A structure representing rendering state */struct SDL_Renderer;typedef struct SDL_Renderer SDL_Renderer;

在源代码工程中可以看到SDL_Renderer的定义,位于render\SDL_sysrender.h文件中。它的定义如下。

/* Define the SDL renderer structure */struct SDL_Renderer{
        const void *magic;    void (*WindowEvent) (SDL_Renderer * renderer, const SDL_WindowEvent *event);    int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);    int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);    int (*SetTextureColorMod) (SDL_Renderer * renderer,                               SDL_Texture * texture);    int (*SetTextureAlphaMod) (SDL_Renderer * renderer,                               SDL_Texture * texture);    int (*SetTextureBlendMode) (SDL_Renderer * renderer,                                SDL_Texture * texture);    int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,                          const SDL_Rect * rect, const void *pixels,                          int pitch);    int (*UpdateTextureYUV) (SDL_Renderer * renderer, SDL_Texture * texture,                            const SDL_Rect * rect,                            const Uint8 *Yplane, int Ypitch,                            const Uint8 *Uplane, int Upitch,                            const Uint8 *Vplane, int Vpitch);    int (*LockTexture) (SDL_Renderer * renderer, SDL_Texture * texture,                        const SDL_Rect * rect, void **pixels, int *pitch);    void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture);    int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture);    int (*UpdateViewport) (SDL_Renderer * renderer);    int (*UpdateClipRect) (SDL_Renderer * renderer);    int (*RenderClear) (SDL_Renderer * renderer);    int (*RenderDrawPoints) (SDL_Renderer * renderer, const SDL_FPoint * points,                             int count);    int (*RenderDrawLines) (SDL_Renderer * renderer, const SDL_FPoint * points,                            int count);    int (*RenderFillRects) (SDL_Renderer * renderer, const SDL_FRect * rects,                            int count);    int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,                       const SDL_Rect * srcrect, const SDL_FRect * dstrect);    int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,                       const SDL_Rect * srcquad, const SDL_FRect * dstrect,                       const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);    int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,                             Uint32 format, void * pixels, int pitch);    void (*RenderPresent) (SDL_Renderer * renderer);    void (*DestroyTexture) (SDL_Renderer * renderer, SDL_Texture * texture);    void (*DestroyRenderer) (SDL_Renderer * renderer);    int (*GL_BindTexture) (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);    int (*GL_UnbindTexture) (SDL_Renderer * renderer, SDL_Texture *texture);    /* The current renderer info */    SDL_RendererInfo info;    /* The window associated with the renderer */    SDL_Window *window;    SDL_bool hidden;    /* The logical resolution for rendering */    int logical_w;    int logical_h;    int logical_w_backup;    int logical_h_backup;    /* The drawable area within the window */    SDL_Rect viewport;    SDL_Rect viewport_backup;    /* The clip rectangle within the window */    SDL_Rect clip_rect;    SDL_Rect clip_rect_backup;    /* The render output coordinate scale */    SDL_FPoint scale;    SDL_FPoint scale_backup;    /* The list of textures */    SDL_Texture *textures;    SDL_Texture *target;    Uint8 r, g, b, a;                   /**< Color for drawing operations values */    SDL_BlendMode blendMode;            /**< The drawing blend mode */    void *driverdata;};

通过代码可以看出其中包含了一个“渲染器”应该包含的各种属性。这个结构体中的各个变量还没有深入研究,暂不详细分析。下面来看看如何创建这个SDL_Renderer。


SDL_CreateRenderer()

函数简介

SDL中使用SDL_CreateRenderer()基于窗口创建渲染器。SDL_CreateRenderer()原型如下。
SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,                                               int index, Uint32 flags);

参数含义如下。

window : 渲染的目标窗口。

index :打算初始化的渲染设备的索引。设置“-1”则初始化默认的渲染设备。

flags :支持以下值(位于SDL_RendererFlags定义中)

    SDL_RENDERER_SOFTWARE :使用软件渲染

    SDL_RENDERER_ACCELERATED :使用硬件加速

    SDL_RENDERER_PRESENTVSYNC:和显示器的刷新率同步

    SDL_RENDERER_TARGETTEXTURE :不太懂

返回创建完成的渲染器的ID。如果创建失败则返回NULL。


函数调用关系图

SDL_CreateRenderer()关键函数的调用关系可以用下图表示。


上述图片不太清晰,相册里面上传了一份原始的大图片:

http://my.csdn.net/leixiaohua1020/album/detail/1793385

打开上述相册里面的图片,右键选择“另存为”即可保存原始图片。


源码分析

SDL_CreateRenderer()的源代码位于render\SDL_render.c中,如下所示。

SDL_Renderer * SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags){
   #if !SDL_RENDER_DISABLED    SDL_Renderer *renderer = NULL;    int n = SDL_GetNumRenderDrivers();    const char *hint;    if (!window) {        SDL_SetError("Invalid window");        return NULL;    }    if (SDL_GetRenderer(window)) {        SDL_SetError("Renderer already associated with window");        return NULL;    }    hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);    if (hint) {        if (*hint == '0') {            flags &= ~SDL_RENDERER_PRESENTVSYNC;        } else {            flags |= SDL_RENDERER_PRESENTVSYNC;        }    }    if (index < 0) {        hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);        if (hint) {            for (index = 0; index < n; ++index) {                const SDL_RenderDriver *driver = render_drivers[index];                if (SDL_strcasecmp(hint, driver->info.name) == 0) {                    /* Create a new renderer instance */                    renderer = driver->CreateRenderer(window, flags);                    break;                }            }        }        if (!renderer) {            for (index = 0; index < n; ++index) {                const SDL_RenderDriver *driver = render_drivers[index];                if ((driver->info.flags & flags) == flags) {                    /* Create a new renderer instance */                    renderer = driver->CreateRenderer(window, flags);                    if (renderer) {                        /* Yay, we got one! */                        break;                    }                }            }        }        if (index == n) {            SDL_SetError("Couldn't find matching render driver");            return NULL;        }    } else {        if (index >= SDL_GetNumRenderDrivers()) {            SDL_SetError("index must be -1 or in the range of 0 - %d",                         SDL_GetNumRenderDrivers() - 1);            return NULL;        }        /* Create a new renderer instance */        renderer = render_drivers[index]->CreateRenderer(window, flags);    }    if (renderer) {        renderer->magic = &renderer_magic;        renderer->window = window;        renderer->scale.x = 1.0f;        renderer->scale.y = 1.0f;        if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {            renderer->hidden = SDL_TRUE;        } else {            renderer->hidden = SDL_FALSE;        }        SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer);        SDL_RenderSetViewport(renderer, NULL);        SDL_AddEventWatch(SDL_RendererEventWatch, renderer);        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,                    "Created renderer: %s", renderer->info.name);    }    return renderer;#else    SDL_SetError("SDL not built with rendering support");    return NULL;#endif}

SDL_CreateRenderer()中最重要的一个函数就是它调用了SDL_RenderDriver的CreateRenderer()方法。通过该方法可以创建一个渲染器。围绕着这个方法,包含了一些初始化工作以及一些收尾工作。下面针对这个最核心的函数进行分析。
我们首先来看一下SDL_RenderDriver这个结构体。从字面的意思可以看出它代表了“渲染器的驱动程序”。这个结构体的定义如下。
/* Define the SDL render driver structure */struct SDL_RenderDriver{
        SDL_Renderer *(*CreateRenderer) (SDL_Window * window, Uint32 flags);    /* Info about the renderer capabilities */    SDL_RendererInfo info;};

从代码中可以看出,这个结构体的成员比较简单,包含了一个函数指针CreateRenderer()和一个存储信息的SDL_RendererInfo类型的结构体info。CreateRenderer()是用于创建渲染器的函数,而SDL_RendererInfo则包含了该结构体的一些信息,可以看一下SDL_RendererInfo的定义。
/** *  \brief Information on the capabilities of a render driver or context. */typedef struct S
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值