SDL2程序仅在使用SDL_RENDERER_SOFTWARE创建渲染器时才有效

时间:2016-08-07 11:22:14

标签: c++ sdl sdl-2

我使用C ++和SDL2编写了一个程序:

  1. 创建一个窗口
  2. 获取窗口的表面
  3. 为窗口创建渲染器
  4. 将一些填充的矩形渲染到窗口
  5. 从窗口的表面创建纹理
  6. 清除屏幕
  7. 将一些填充的圆圈渲染到窗口
  8. 从窗口的表面
  9. 创建第二个纹理
  10. 进入事件循环,每次按下一个键:
  11. 如果当前正在显示圆圈,则使用SDL_RenderCopy()将方块纹理复制到窗口。
  12. 如果当前正在显示正方形,则将圆形纹理复制到窗口。
  13. 如果使用SDL_RENDERER_SOFTWARE标志创建渲染器,程序将完美运行。

    如果使用SDL_RENDERER_ACCELERATED标志创建渲染器,我发现虽然我可以直接渲染到屏幕,但如果我从窗口的表面创建了几个不同的纹理,然后尝试复制他们使用SDL_RenderCopy()回到窗口;我看到的只是一扇黑色的窗户。

    我无法找到任何失败的SDL电话。

    我想知道纹理格式和渲染器之间是否存在某些不兼容性 - 但我不确定如何跟进它。

    任何帮助或建议?

    我的环境是:

    • Windows 10
    • Visual Studio Community 2015
    • SDL2版本2.0.4

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    其他信息和源代码:

    我已经添加了减少的源代码来演示下面的问题。

    请注意,为了减小尺寸,我删除了所有错误检查并将相关代码合并到一个主要功能中。

    我得到的是,如果我取消注释第40行,该程序将按预期为我工作,以便我使用SDL_CreateRenderer标记调用SDL_RENDERER_SOFTWARE

    如果我取消评论任何其他SDL_CreateRenderer行(第41-43行:使用硬件加速),我会在最初渲染到屏幕时看到红色和蓝色方块。

    但是当我按下按键时,我不是在红色和蓝色方块之间轻弹,而是在看黑色的窗口。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    #include <SDL.h>
    #include <SDL_image.h>
    #include <stdio.h>
    #include <string>
    
    
    //Screen dimension constants
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    
    
    int main(int argc, char* args[])
    {
    
        //The window we'll be rendering to
        SDL_Window* gWindow = NULL;
    
        //The surface contained by the window
        SDL_Surface* gScreenSurface = NULL;
    
        //And two textures, one for a red square, on for a blue square
        SDL_Texture* texture_red = NULL;
        SDL_Texture* texture_blue = NULL;
    
        //The window renderer
        SDL_Renderer* gRenderer = NULL;
    
    
        //Initialize SDL
        SDL_Init(SDL_INIT_VIDEO);
    
        //Create window
        gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    
        //Get the screen surface
        gScreenSurface = SDL_GetWindowSurface(gWindow);
    
    
        //Create renderer for window
        gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_SOFTWARE);
        //gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
        //gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_PRESENTVSYNC);
        //gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    
        /*###########################################################################################
        # I can not figure out how to make this program work with hardware acceleration. It works   #
        # fine when I define the renderer using SDL_RENDERER_SOFTWARE, but doesn't display anything #
        # if I define the renerer using the SDL_RENDERER_ACCELERATED flag                           #
        ###########################################################################################*/
    
        //Initialize renderer color
        SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
    
    
        //Clear screen
        SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(gRenderer);
    
        //Render red filled quad
        SDL_Rect fillRect = { 100, 75, 100, 100 };
        SDL_SetRenderDrawColor(gRenderer, 0xFF, 0x00, 0x00, 0xFF);
        SDL_RenderFillRect(gRenderer, &fillRect);
    
        //Update the rendered image on screen
        SDL_RenderPresent(gRenderer);
    
        //Pause long enough to see it
        SDL_Delay(200);
    
        //Create texture_red texture from the screen surface
        texture_red = SDL_CreateTextureFromSurface(gRenderer, gScreenSurface);
    
    
        //Clear screen
        SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(gRenderer);
    
        //Render blue filled quad
        fillRect = { 225, 250, 100, 100 };
        SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0xFF, 0xFF);
        SDL_RenderFillRect(gRenderer, &fillRect);
    
        //Update the rendered image on screen
        SDL_RenderPresent(gRenderer);
    
        //Pause long enough to see it
        SDL_Delay(200);
    
        //Create texture_red texture from the screen surface
        texture_blue = SDL_CreateTextureFromSurface(gRenderer, gScreenSurface);
    
    
        //Main loop flag
        bool quit = false;
    
        //Flag to keep track of which colour we're currently looking at
        bool blue = true;
    
        //Event handler
        SDL_Event e;
    
        //While application is running
        while (!quit)
        {
            //Handle events on queue
            while (SDL_PollEvent(&e) != 0)
            {
                //User requests quit
                if (e.type == SDL_QUIT)
                {
                    quit = true;
                }
                //User presses a key
                else if (e.type == SDL_KEYDOWN)
                {
                    //Select surfaces based on key press
                    switch (e.key.keysym.sym)
                    {
    
                    case SDLK_ESCAPE:
                        quit = true;
                        break;
    
                    default:
                        if (blue)
                        {
                            //Copy surface used to store red image onto the screen surface
                            SDL_RenderCopy(gRenderer, texture_red, NULL, NULL);
    
                            //Update current colour flag
                            blue = false;
                        }
                        else
                        {
    
                            //Copy surface used to store blue image onto the screen surface
                            SDL_RenderCopy(gRenderer, texture_blue, NULL, NULL);
    
                            //Update current colour flag
                            blue = true;
                        }
    
                        //Update the screen with recent render activity
                        SDL_RenderPresent(gRenderer);
    
                        break;
                    }
                }
            }
        }
    
    
        //Deallocate surfaces
        SDL_FreeSurface(gScreenSurface);
    
        //Destroy window
        SDL_DestroyWindow(gWindow);
        gWindow = NULL;
    
        //Quit SDL subsystems
        SDL_Quit();
    
        return 0;
    }
    

2 个答案:

答案 0 :(得分:5)

SDL_GetWindowSurface() header comment明确禁止将其与SDL_Renderer功能一起使用:

/**
 *  \brief Get the SDL surface associated with the window.
 *
 *  \return The window's framebuffer surface, or NULL on error.
 *
 *  A new surface will be created with the optimal format for the window,
 *  if necessary. This surface will be freed when the window is destroyed.
 *
 *  \note You may not combine this with 3D or the rendering API on this window.
 *
 *  \sa SDL_UpdateWindowSurface()
 *  \sa SDL_UpdateWindowSurfaceRects()
 */
extern DECLSPEC SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window * window);

使用SDL_RENDERER_TARGETTEXTURE&amp; SDL_SetRenderTarget()如果您想捕获SDL_Renderer输出。

您可以使用SDL_GetRendererInfo()查询兼容的纹理格式。或者只是提前SDL_PIXELFORMAT_ARGB8888 like testrendertarget.c does,并希望最好:)

答案 1 :(得分:0)

尝试将SDL_RENDERER_PRESENTVSYNC添加到渲染器的标记中(由某人here建议)。

C ++似乎是您正在使用的编程语言,但对于那些寻找基于SDL2.0.8的完全无法使用GetWindowSurface()的C程序的人来说,请查看here:< / p>

主要是,

  • initWindowAndRenderer
  • 的drawText
  • 的drawImage
  • drawVideo
  • setBgColor
  • drawVideo
  • ...