SDL2程序仅在使用SDL_RENDERER_SOFTWARE创建Renderer时有效 [英] SDL2 program only works if Renderer is created with SDL_RENDERER_SOFTWARE
问题描述
我写了一个程序使用C ++& SDL2其中:
- 创建一个窗口
- 获取窗口的表面
- 为窗口创建渲染器
- 将一些填充的矩形渲染到窗口上
- 从窗口的表面创建纹理
- 清除屏幕
- 在窗口上呈现一些已填充的圆形
- 从窗口表面创建第二个纹理
- 进入事件循环,其中每次按下一个键:
- 如果当前正在显示圆形,则使用SDL_RenderCopy()
- 如果正在显示正方形,则会将圆形纹理复制到窗口。 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:
- creates a window
- gets the window's surface
- creates a renderer for the window
- renders some filled rectangles onto the window
- creates a texture from the window's surface
- clears the screen
- renders some filled circles onto the window
- creates a second texture from the window's surface
- enters an event loop, where every time a key is pressed:
- if circles are currently being displayed, SDL_RenderCopy() is used to copy the squares texture to the window.
- 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 withSDL_PIXELFORMAT_ARGB8888
liketestrendertarget.c
does and hope for the best :)这篇关于SDL2程序仅在使用SDL_RENDERER_SOFTWARE创建Renderer时有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!