SDL2程序仅在使用SDL_RENDERER_SOFTWARE创建Renderer时有效 [英] SDL2 program only works if Renderer is created with SDL_RENDERER_SOFTWARE

查看:670
本文介绍了SDL2程序仅在使用SDL_RENDERER_SOFTWARE创建Renderer时有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个程序使用C ++& SDL2其中:


  1. 创建一个窗口

  2. 获取窗口的表面

  3. 为窗口创建渲染器

  4. 将一些填充的矩形渲染到窗口上

  5. 从窗口的表面创建纹理

  6. 清除屏幕

  7. 在窗口上呈现一些已填充的圆形

  8. 从窗口表面创建第二个纹理

  9. 进入事件循环,其中每次按下一个键:

  10. 如果当前正在显示圆形,则使用SDL_RenderCopy()



  11. 如果正在显示正方形,则会将圆形纹理复制到窗口。 b

    如果渲染器是使用SDL_RENDERER_SOFTWARE标志创建的,程序可以正常工作。



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



    我找不到任何失败的SDL调用。



    我想知道纹理格式和渲染器之间是否有不兼容,但我不知道如何跟踪这个。



    任何帮助或建议? p>

    我的环境是:




    • Windows 10

    • Visual Studio Community 2015

    • SDL2版本2.0.4



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



    信息和源代码:



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



    注意,为了保持大小,我删除了所有的错误检查,并将相关的代码合并到一个单一的主要功能。



    我得到的是程序工作对我来说,如果我取消注释行40,以便我使用SDL_RENDERER_SOFTWARE标志调用SDL_CreateRenderer。



    如果我取消注释任何其他SDL_CreateRenderer行第41-43行:使用硬件加速),我看到红色和蓝色正方形,当他们最初呈现到屏幕。



    但是当我按键,而不是窗口在红​​色和蓝色正方形之间滑动,我在看一个黑色的窗口。



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

      #include< SDL .h> 
    #include< SDL_image.h>
    #include< stdio.h>
    #include< string>


    //屏幕维度常量
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;


    int main(int argc,char * args [])
    {

    //我们将渲染到的窗口
    SDL_Window * gWindow = NULL;

    //窗口包含的表面
    SDL_Surface * gScreenSurface = NULL;

    //两个纹理,一个用于红色正方形,一个用于蓝色方形
    SDL_Texture * texture_red = NULL;
    SDL_Texture * texture_blue = NULL;

    //窗口渲染器
    SDL_Renderer * gRenderer = NULL;


    //初始化SDL
    SDL_Init(SDL_INIT_VIDEO);

    //创建窗口
    gWindow = SDL_CreateWindow(SDL教程,SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_SHOWN);

    //获取屏幕表面
    gScreenSurface = SDL_GetWindowSurface(gWindow);


    //为窗口创建renderer
    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);

    / * ######################################## ################################################## #
    #我不知道如何使这个程序与硬件加速工作。它工作#
    #罚款当我使用SDL_RENDERER_SOFTWARE定义渲染器,但不显示任何#
    #如果我使用SDL_RENDERER_ACCELERATED标志定义renerer#
    ####### ################################################## ######################################### * /

    //初始化渲染器颜色
    SDL_SetRenderDrawColor(gRenderer,0xFF,0xFF,0xFF,0xFF);


    //清除屏幕
    SDL_SetRenderDrawColor(gRenderer,0xFF,0xFF,0xFF,0xFF);
    SDL_RenderClear(gRenderer);

    //渲染红色填充四边形
    SDL_Rect fillRect = {100,75,100,100};
    SDL_SetRenderDrawColor(gRenderer,0xFF,0x00,0x00,0xFF);
    SDL_RenderFillRect(gRenderer,& fillRect);

    //在屏幕上更新渲染的图像
    SDL_RenderPresent(gRenderer);

    //暂停足够长时间才能看到
    SDL_Delay(200);

    //从屏幕表面创建texture_red纹理
    texture_red = SDL_CreateTextureFromSurface(gRenderer,gScreenSurface);


    //清除屏幕
    SDL_SetRenderDrawColor(gRenderer,0xFF,0xFF,0xFF,0xFF);
    SDL_RenderClear(gRenderer);

    //渲染蓝色填充的四边形
    fillRect = {225,250,100,100};
    SDL_SetRenderDrawColor(gRenderer,0x00,0x00,0xFF,0xFF);
    SDL_RenderFillRect(gRenderer,& fillRect);

    //更新屏幕上渲染的图像
    SDL_RenderPresent(gRenderer);

    //暂停足够长时间才能看到
    SDL_Delay(200);

    //从屏幕表面创建texture_red纹理
    texture_blue = SDL_CreateTextureFromSurface(gRenderer,gScreenSurface);


    //主循环标志
    bool quit = false;

    //标记以跟踪我们当前正在查看的颜色
    bool blue = true;

    //事件处理程序
    SDL_Event e;

    //应用程序运行时
    while(!quit)
    {
    //处理队列上的事件
    while(SDL_PollEvent(& e) != 0)
    {
    //用户请求退出
    if(e.type == SDL_QUIT)
    {
    quit = true;
    }
    //用户按下一个键
    else if(e.type == SDL_KEYDOWN)
    {
    //根据按键选择曲面
    switch(e.key.keysym.sym)
    {

    case SDLK_ESCAPE:
    quit = true;
    break;

    默认值:
    if(蓝色)
    {
    //复制表面用于将红色图像存储到屏幕表面
    SDL_RenderCopy(gRenderer,texture_red, NULL,NULL);

    //更新当前颜色标志
    blue = false;
    }
    else
    {

    //复制用于将蓝色图像存储到屏幕表面的曲面
    SDL_RenderCopy(gRenderer,texture_blue,NULL,NULL) ;

    //更新当前颜色标志
    blue = true;
    }

    //使用最近的渲染活动更新屏幕
    SDL_RenderPresent(gRenderer);

    break;
    }
    }
    }
    }


    //取消分配表面
    SDL_FreeSurface(gScreenSurface);

    //销毁窗口
    SDL_DestroyWindow(gWindow);
    gWindow = NULL;

    //退出SDL子系统
    SDL_Quit();

    return 0;
    }


    解决方案

    SDL_GetWindowSurface() header comment 特别禁止在SDL_Renderer功能中使用它:

      / ** 
    * \brief获取SDL表面与窗口相关联。
    *
    * \return窗口的帧缓冲区表面,或错误时为NULL。
    *
    *将使用窗口的最佳格式创建新曲面,如果需要,将创建
    *。当窗口被破坏时,这个表面将被释放。
    *
    * \\\
    ote您不能将此与3D或此窗口上的呈现API组合。
    *
    * \sa SDL_UpdateWindowSurface()
    * \sa SDL_UpdateWindowSurfaceRects()
    * /
    extern DECLSPEC SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window * window);

    使用 SDL_RENDERER_TARGETTEXTURE SDL_SetRenderTarget() 如果要捕获SDL_Renderer输出



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


    I've written a program using C++ & SDL2 which:

    1. creates a window
    2. gets the window's surface
    3. creates a renderer for the window
    4. renders some filled rectangles onto the window
    5. creates a texture from the window's surface
    6. clears the screen
    7. renders some filled circles onto the window
    8. creates a second texture from the window's surface
    9. enters an event loop, where every time a key is pressed:
    10. if circles are currently being displayed, SDL_RenderCopy() is used to copy the squares texture to the window.
    11. else if squares are currently being displayed, the circles texture is copied to the window.

    The program works perfectly if the renderer is created with the SDL_RENDERER_SOFTWARE flag.

    If the renderer is created with the SDL_RENDERER_ACCELERATED flag, I find that while I can render direct to the screen, if I create a couple of different textures from the window's surface and then try to copy them back to the window using SDL_RenderCopy(); all I see is a black window.

    I can't find any failing SDL calls.

    I've wondered whether there might be some incompatibility between the texture format and the renderer - but I'm not sure how to follow this up.

    Any help or suggestions?

    My environment is :

    • Windows 10
    • Visual Studio Community 2015
    • SDL2 version 2.0.4

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

    Additional information and source code :

    I've added cut down source code to demonstrate the problem below.

    Note, to keep down the size, I've removed all of the error checking and consolidated the relevant code into a single main function.

    What I get is that the program works for me as expected if I un-comment line 40 so that I am calling SDL_CreateRenderer with the SDL_RENDERER_SOFTWARE flag.

    If I un-comment any of the other SDL_CreateRenderer lines instead (line 41-43 : to use hardware acceleration), I see the red and blue squares when they are initially rendered to screen.

    But as I press keys, instead of the window flicking between red and blue squares, I'm looking at a black window.

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

    #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;
    }
    

    解决方案

    The SDL_GetWindowSurface() header comment specifically prohibits using it with the SDL_Renderer functionality:

    /**
     *  \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);
    

    Use SDL_RENDERER_TARGETTEXTURE & SDL_SetRenderTarget() if you want to capture SDL_Renderer output.

    You can use SDL_GetRendererInfo() to query a compatible texture format. Or just blast ahead with SDL_PIXELFORMAT_ARGB8888 like testrendertarget.c does and hope for the best :)

    这篇关于SDL2程序仅在使用SDL_RENDERER_SOFTWARE创建Renderer时有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆