How to fix SDL_CreateWindow error "Window is too large" - sdl

I'm currently creating a window class for my game engine. When I call SDL_CreateWindow it returns the error "Window is too large". How do I fix this problem? In order to display a window for my game engine.
I've tried setting the window creation flag to SDL_WINDOW_ALLOW_HIGHDPI and the error is still reported back. I have also set the DPI Awareness in the manifest tool to High DPI Aware. I'm still not able to fix the issue. A code snippet of the Initialise Window function is included below.
SDL_DisplayMode displayMode;
for (int32_t i = 0; i < SDL_GetNumVideoDisplays(); i++)
{
int32_t displayModeCount = SDL_GetCurrentDisplayMode(i, &displayMode);
if (displayModeCount != 0)
{
std::printf("Could not get display mode for video display %d: %s", i, SDL_GetError());
}
else
{
m_width = displayMode.w;
m_height = displayMode.h;
std::printf("Display %d current display mode is %dx%dpx", i, displayMode.w, displayMode.h);
float DPI;
SDL_GetDisplayDPI(displayModeCount, nullptr, &DPI, nullptr);
x = static_cast<int32_t>(m_width * DPI / DPI);
y = static_cast<int32_t>(m_height * DPI / DPI);
}
}
uint32_t windowFlags = SDL_WINDOW_ALLOW_HIGHDPI;
m_pWindow = SDL_CreateWindow(m_title.c_str(), x, y, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowFlags);
if (m_pWindow == nullptr)
{
std::printf("Could not create window: %s", SDL_GetError());
}
Even with the SDL_WINDOW_ALLOW_HIGHDPI flag set it still prints out the error message and does not display the window. Any help regarding this issue is much appreciated.

Solved this issue by passing the x and y values to the to SDL_CreateWindow function instead off SDL_WINDOWPOS_CENTERED. Solved by keltar, see comment.

Related

Why isn't SDL_CreateWindow showing a window when called from another class?

Rewriting this to try to provide some clarity and update the code with some things that have changed.
I am restructuring a project that used SDL2, and have encountered issues trying to create a blank window. I have attempted to structure the project similarly to the original by separating all functionality dealing with SDL_Window into its own class. If I move the call to SDL_CreateWindow into the same class as the event loop or move the event loop to the same class as the window, the window is created and shown as expected, however as it is now, the window appears to be created successfully (SDL_CreateWindow is not returning NULL) and the program doesn't seem to be hanging, but it does not display a window while the program is running.
The SDL_Window is created in the Graphics class and stored in a member variable:
Graphics::Graphics(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
screen = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h,
flags);
status = 0;
if (screen == NULL)
status = 1;
}
Graphics is instantiated in the Window class and stored in a member variable.
Window::Window(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
g = Graphics(title, w,h, flags, status);
}
Window is instantiated in main, and if the window is created successfully, it starts the event loop.
{
int status;
Window window("Mirari", 640,480, SDL_WINDOW_SHOWN, status);
if (status == 0) {
window.eventLoop();
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s", SDL_GetError());
return 1;
}
}
The event loop itself to be thorough (update and draw are both currently empty functions).
void Window::eventLoop() {
SDL_Event ev;
bool running = true;
while (running) {
const int start_time = SDL_GetTicks();
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
//update();
//draw();
std::cout << "." << std::endl;
const int elapsed = SDL_GetTicks() - start_time;
if (elapsed < 1000 / FPS)
SDL_Delay(1000 / FPS - elapsed);
}
}
SDL is initialized with this static function and these flags.
void Window::init(unsigned int sdl_flags, IMG_InitFlags img_flags) {
SDL_Init(sdl_flags);
IMG_Init(img_flags);
TTF_Init();
}
...
Window::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER, IMG_INIT_PNG);
I know that a window can be created in a separate class because the first version of this project did that and it worked, I'm just not sure what has changed that is causing the window not to show up.
As said by some programmer dude, you design is not perfect and should be thought again.
Nevertheless, from what we can see on your code : If the Window constructor is called (and the SDL_Init was called before, which I assume so), then the windows should be created.
From there we only can guess what we can't see (as it's not part of what you are displaying) :
is the definition of SDL_WINDOWPOS_UNDEFINED, the same in both context ?
is the screen variable definition the same in both context ?
is the "screen" used in "update", or "draw" method, and, as uninitialized : it fails
... ?
As you probably are new to development, I suggest you adopt this habit very early : your code should check and report everything it does. A good program is easy to debug, as it says what's wrong
For instance, just after :
screen = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h, flags);
you may want to write something like :
if(!screen)
{
std::cout << "Failed to create window\n";
return -1;
}
or better :
if(!screen)
{
throw std::exception("Failed to create window\n");
}
And so on.
For instance, in your function update, you may want to have something like :
if(!screen)
{
throw std::exception("Unable to update the display as it is uninitialized\n");
}
I assume your application would not end without any comment... but that's a guess

Having trouble initializing bgfx (with an sdl2 window)

I'm attempting to create a window using SDL2 and initialize BGFX to use it. My current test is just to set the window to purple using a clear color.
I tried creating a window using CreateWindowEx as well, and was also unable to update the window with the clear color I specified in my call to bgfx::setViewClear. I've been scouring open source projects as well as the docs and samples, and I can't figure out what step of bgfx initialization/update I could be missing. Please help! I've attached my current approach as a small test main.
int main(int, char**) {
SDL_InitSubSystem(SDL_INIT_VIDEO);
const int width = 800;
const int height = 600;
SDL_Window* window = nullptr;
HWND nativeWindow;
// sdl2
{
window = SDL_CreateWindow(
"test_window",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
0
);
SDL_SysWMinfo windowManInfo;
SDL_VERSION(&windowManInfo.version);
if (SDL_GetWindowWMInfo(window, &windowManInfo)) {
nativeWindow = windowManInfo.info.win.window;
}
}
// bgfx
{
bgfx::PlatformData platformData;
platformData.ndt = nullptr;
platformData.nwh = nativeWindow;
bgfx::setPlatformData(platformData);
// prevent creation of a renderer thread
bgfx::renderFrame();
bgfx::Init init;
init.type = bgfx::RendererType::Count;
init.resolution.width = width;
init.resolution.height = height;
init.resolution.reset = BGFX_RESET_VSYNC;
bgfx::init(init);
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x443355FF /*purple*/, 1.f, 0);
}
while (1) {
// sdl events
{
SDL_Event _event;
while (SDL_PollEvent(&_event) > 0);
}
bgfx::frame();
}
bgfx::shutdown();
SDL_Quit();
return 0;
}
After asking around work/etc.. I finally got a solution, and there were actually a couple of things that I was missing.
Because I wasn't adding any render work to the frame, bgfx is 'smart' and doesn't actually do anything. Adding a call to bgfx::touch will add an empty primitve for rendering. After I added this I could see a small dot in the top-left of my window, which leads to the other call I was missing.
I never set my view! I was also only rendering to one pixel of my window. By adding a call to bgfx::setViewRect I was able to set a size for my window view and the clear color finally took.

Wrong SDL origin axis in 1080x1920 resolution

I am facing an issue with the SDL library and different resolution than 1920x1080.
I want to copy display an image of dimension 1080x608 at the center of a screen of resolution 1080x1920 (portrait).
I have only one plugged monitor screen.
I used the following command to switch screen from 1920x1080 to 1080x1920 :
xrandr --output DP-1 --mode 1920x1080 --rotate left --primary
I am using the following code to initialize the SDL renderer :
/**
* initialize everything so we are ready to display
*/
int SdlHandler::initialize(
unsigned int positionX,
unsigned int positionY,
unsigned int width,
unsigned int height,
bool showWindow,
std::string name) {
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return -1;
}
// Size if the window
this->width = width;
this->height = height;
this->positionX = positionX;
this->positionY = positionY;
// Create the SDL window
// 0 and 0 are the position in X and Y
unsigned int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
if (showWindow) {
flags |= SDL_WINDOW_SHOWN;
} else {
flags |= SDL_WINDOW_HIDDEN;
}
this->window = SDL_CreateWindow(name.c_str(), this->positionX, this->positionY, this->width, this->height, flags);
// If there had been a problem, leave
if (!this->window) {
return -1;
}
// Create a new renderer
this->renderer = SDL_CreateRenderer(this->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
// If there is an error creating it, just leave
if (!this->renderer) {
return -1;
}
// Setup the best for the SDL render quality
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
return 0;
}
Then, i call the SDL_RenderCopy function to display the image. I pass it the created renderer created with theSDL_CreateRenderer on the above code :
// Create a window at 0,0 of dimension 1080x1920
this->initialize(0, 0, 1080, 1920, true, SDL_BASE_DISPLAY_WINDOW);
// Create the SDL Rectangle that will contain the image, at the center of the window
SDL_Rect *howToDraw = new SDL_Rect();
howToDraw->x = this->positionX + floor((this->width - this->imageWidth) / 2);
howToDraw->y = this->positionY + floor((this->height - this->imageHeight) / 2);
howToDraw->w = this->imageWidth;
howToDraw->h = this->imageHeight;
SDL_RenderCopy(this->renderer, this->texture, NULL, howToDraw);
But the axis seems to be at the wrong position, igot the following result :
 EDIT AND SOLUTION
This was a bug related to Compton, the window manager, everything is working good without Compton ...
Since you are rotating your display using xrandr, we can consider this is a post processing step that will rotate everything after each framebuffer is rendered.
Because this post processing step takes a 1920x1080 image resolution as input, you should use the SDL at this resolution.
What if you change your code for:
// Create a window at 0,0 of dimension 1920x1080
this->initialize(0, 0, 1920, 1080, true, SDL_BASE_DISPLAY_WINDOW);
EDIT: I also understand that you want your image to start at the center of the window, but your are placing the middle of the image at the center of the window.
You should also try the following:
howToDraw->x = this->positionX + this->imageWidth / 2;

SDL will only draw a black screen when trying to print a picture C++

class Game {
public:
Game(int width, int height) {
gwidth = width;
gheight = height;
}
~Game() {
}
bool initGame() {
bool sucsess = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
sucsess = false;
}
//gTetrisSurface = SDL_LoadBMP("TetrisBg.bmp");
gWindow = SDL_CreateWindow("Petris V1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, gwidth, gheight, SDL_WINDOW_SHOWN);
gScreenSurface = SDL_GetWindowSurface(gWindow);
gMainBG = SDL_LoadBMP("test.bmp");
/**if (gMainBG == NULL) {
return false;
}**/
bool running = true;
//SDL_SetWindowFullscreen(gWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
while (running == true) {
SDL_BlitSurface(gMainBG, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface( gWindow );
}
return sucsess;
}
protected:
int gwidth, gheight;
SDL_Window* gWindow = NULL;
SDL_Surface* gScreenSurface = NULL;
SDL_Surface* gTetrisSurface = NULL;
SDL_Surface* gPongSurface = NULL;
SDL_Surface* gMainBG = NULL;
};
The thought behind this, is that this should be one huge surface, containing 2 other surfaces for 2 other games. Problem is, it wont seem to draw the BMP that i try to draw on it. Because of this my development got kinda stuck. Anyone see a possible sulotion for this problem? Thanks!
EDIT: I made it so it flushes the events, BUT, i did a bit of debugging, the problem seems to be that the img file returns NULL, why? It should be loaded with a bmp... (No error messages at all..)
From the documentation of SDL2:
https://wiki.libsdl.org/SDL_GetWindowSurface
This surface will be invalidated if the window is resized. After resizing a window this function must be called again to return a valid surface.
You may not combine this with 3D or the rendering API on this window.
My advice is to avoid using the window surface directly.
Instead, you should use a renderer and copy your own main surface to your background texture.
The SDL2 migration guide explains clearly the right way to copy surfaces and textures on the screen, especially the paragraph "If your game wants to do both".
The whole problem was that the BMP file was in the wrong folder.
If anyone have the same problem, the picture should either be in the same directory as the src (when debugging) or the solution (if building).
Hope this might help someone in the future, either way, thanks to those who tried coming up with other possibilites.
(Using visual studio)

Elementary inquiry about C++ (SDL2 library)

I'm fairly new to programming, so this question will probably be basic. I'm writing a very basic program in C++ with the SDL2 library (in Visual Studio 2013). When I was writing it, I came across a problem. I wrote the following:
int controles(){
//declare actions that will happen when a key is pressed
const Uint8 * estado = SDL_GetKeyboardState(NULL);
if (estado[SDL_SCANCODE_UP]){ y--; SDL_UpdateWindowSurface(ventana); }
if (estado[SDL_SCANCODE_DOWN]){ y++; SDL_UpdateWindowSurface(ventana); }
return 0;
}
The problem is that I need to update the window surface after the value of y is modified, but I get an error because ventana, the name of the window, is defined in another function. I tried to define ventana globally, but the program won't work then. I then thought the following; write a goto statement in graficos, the function where ventana is defined, in order to skip every other statement in that function, except for the one that updates the window surface. However, when I did that, the program doesn't even compile:
int graficos(int caso){
if (caso == 1) {goto reload;} //skip to reload if (1)
SDL_Init(SDL_INIT_VIDEO); //load SDL
//load graphics in memory
SDL_Window * ventana = SDL_CreateWindow("ventana", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Surface * superficie = SDL_GetWindowSurface(ventana);
SDL_Surface * pantallainicio = SDL_LoadBMP("pantallainicio.bmp");
SDL_Surface * paleta = SDL_LoadBMP("paleta.bmp");
SDL_Rect rpantallainicio = { 0, 0, 640, 480 };
SDL_Rect rpaleta = { x, y, 16, 16 };
//render graphics
SDL_BlitSurface(pantallainicio, NULL, superficie, &rpantallainicio);
SDL_BlitSurface(paleta, NULL, superficie, &rpaleta);
SDL_UpdateWindowSurface(ventana);
reload:SDL_UpdateWindowSurface(ventana);
return 0;
}
I get the following errors:
error C4533: initialization of 'rpaleta' is skipped by 'goto reload'
error C4533: initialization of 'rpantallainicio' is skipped by 'goto reload'
I hope I explained my issue well enough. What can I do? Is there a way to fix this? Or can I reference ventana in some other way? This issue might be very basic, sorry for that, and thanks in advance!
You can fix this issue by simply not using goto at all - use a sub-function instead. Also, extract the variable ventana, as you need it to be stored and usable by graficos whenever.
void init()
{
SDL_Init(SDL_INIT_VIDEO); //load SDL
//load graphics in memory
ventana = SDL_CreateWindow("ventana", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Surface * superficie = SDL_GetWindowSurface(ventana);
SDL_Surface * pantallainicio = SDL_LoadBMP("pantallainicio.bmp");
SDL_Surface * paleta = SDL_LoadBMP("paleta.bmp");
SDL_Rect rpantallainicio = { 0, 0, 640, 480 };
SDL_Rect rpaleta = { x, y, 16, 16 };
//render graphics
SDL_BlitSurface(pantallainicio, NULL, superficie, &rpantallainicio);
SDL_BlitSurface(paleta, NULL, superficie, &rpaleta);
}
int graficos(int caso)
{
if (caso != 1) { init(); } //skip to reload if (1)
SDL_UpdateWindowSurface(ventana);
return 0;
}
SDL_Window * ventana;
Use of goto should generally be avoided. Use subroutines or other alternatives where possible. Here, the code does exactly the same thing as originally intended, but the "extra" flow that occurs when caso is not 1 is wrapped in its own subroutine named 'init'.