I recently updated my mac and the code that was normally running stopped functioning.
When I now run my program (a game) the window still has the right dimensions but the elements are displayed in the bottom-left quarter of my screen.
I don't understand where it comes from.
here is the .cpp that I used in the exemple:
#include "../../include/game.h"
int main(int argc, char **argv)
{
SDL_Window *window;
SDL_Renderer *render;
int w;
int h;
(void)argc;
(void)argv;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
window = SDL_CreateWindow("lul", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_W, WINDOW_H, 0);
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_GetWindowSize(window, &w, &h);
SDL_Surface *surface;
SDL_Texture *texture;
surface = IMG_Load("FondHome2.jpg");
texture = SDL_CreateTextureFromSurface(render, surface);
SDL_Event event;
bool close_requested = false;
while (!close_requested)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
close_requested = true;
}
}
SDL_RenderCopy(render, texture, NULL, NULL);
SDL_RenderPresent(render);
}
return(0);
}
and here is the .h used:
#ifndef GAME_H
# define GAME_H
# include <SDL2/SDL.h>
# include <SDL2/SDL_timer.h>
# include <SDL2/SDL_image.h>
# include <SDL2/SDL_ttf.h>
# include <fstream>
# include <iostream>
# include <string>
# include <vector>
# include <stdarg.h>
# include <math.h>
# define WINDOW_W 400
# define WINDOW_H 300
#endif
See content related to High-DPI differences when working with Retina displays on Mac: SDL_GL_GetDrawableSize. Pass the SDL_WINDOW_ALLOW_HIGHDPI flag to SDL_CreateWindow, and the SDL_Render API should do the right thing.
The problem is that without high DPI enabled, the actual width and height of your SDL_Window correspond to more pixels than you passed to SDL_CreateWindow (2X width and height, in this case). It seems like SDL_RenderCopy still thinks the target framebuffer is 400x300, which is correct when the DPI scaling factor is 1. When the image is drawn, only 1/4 of the physical space is covered.
I can't tell you exactly where the scaling issue happens without reading the SDL2 source, since it could be happening with an internal framebuffer or during the final blit, but the issue is the assumption of a DPI scaling factor of 1. Passing the SDL_WINDOW_ALLOW_HIGHDPI flag during window creation tells SDL to query the actual monitor DPI to be used.
Related issue: SDL 2.0 retina mac
Related
as title, I'm having problems trying to make SDL2 display frames from realsesense pipeline. I have no clue how to extract data from the frameset and process it in order to make it works with SDL2. I'm programming in C++. I've read all the documentation on Intel SDK website and tried a lot of different approches, nothing worked so far.
Here's some code I've wrote on a new project:
int main(int argc, char * argv[])
{
window window(1280, 720, "Tecnos Depth Cam Demo");
rs2::colorizer color_map;
rs2::pipeline pipe;
pipe.start();
while (true)
{
rs2::frameset data = pipe.wait_for_frames().apply_filter(color_map);
// Process data to work with SDL2 renderer (my problem)
}
}
At the end I managed to do it. Simply create a texture with SDL_CreateTexture and update it with the pixels data from get_data() function of Realsense library each frame. The tricky part is that you have to define a pixel format with:
SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_8888, BITS_PER_PIXEL, BYTES_PER_PIXEL)
Here a little code demo that I wrote on porpuse to show you:
#include <iostream>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include <librealsense2/rs.hpp>
#define WINDOW_WIDTH 1280
#define WINDOW_HEIGHT 720
#define BITS_PER_PIXEL 24
#define BYTES_PER_PIXEL 3
int main(int argc, char* argv[])
{
// Init
SDL_Init(SDL_INIT_EVERYTHING);
// Declarative section
SDL_Window* window = SDL_CreateWindow("Tutorial", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
SDL_Texture* textureCamera = SDL_CreateTexture(renderer, SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_8888, BITS_PER_PIXEL, BYTES_PER_PIXEL), SDL_TEXTUREACCESS_TARGET, WINDOW_WIDTH, WINDOW_HEIGHT);
rs2::pipeline camera;
rs2::frameset frames;
// Executive section
camera.start();
// Loop
while (true)
{
// Do whatever you like there
SDL_RenderClear(renderer);
// ...
frames = camera.wait_for_frames();
Uint8* pixels = (Uint8*)(frames.get_color_frame().get_data());
SDL_UpdateTexture(textureCamera, NULL, pixels, frames.get_color_frame().get_bytes_per_pixel() * WINDOW_WIDTH);
SDL_RenderCopy(renderer, textureCamera, NULL, NULL);
SDL_RenderPresent(renderer);
}
return EXIT_SUCCESS;
}
I hope I helped someone in trouble like me. For any question just ask me, I'll be more than happy to help! Lastly thanks to the stackoverflow community to always help even when it doesn't!
I'm trying to set up an SDL project with Visual Studio 2019 using this article:
https://www.wikihow.com/Set-Up-SDL-with-Visual-Studio
but the compiler is throwing me the errors 'one or more multiply defined symbols found' and
'_main already defined in main.obj'.
main.obj is a file in the debug folder of my project but when I try deleting it or the entire debug folder, VS recreates it when I run the project.
I've read that c++ can't have more than one main function but I can't open the main.obj file and I don't really want to delete the one in main.cpp
Here's the code I'm running and thanks for your help!
#include "SDL.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow
("An SDL2 window", // window's title
10, 25, // coordinates on the screen, in pixels, of the window's upper left corner
640, 480, // window's length and height in pixels
SDL_WINDOW_OPENGL);
SDL_Delay(3000); // window lasts 3 seconds
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Glad to know it works now. Maybe you had a messy file structure with your previous SDL installation. Anyways, I think it might be interesting to show how the SDL dependency can be removed from your main.cpp file, to avoid such problems in the future.
First, let's consider the example in your question. The example is not very useful in practice, but I'll show a better version after.
The main idea is hiding everything that has to do with SDL from your main.cpp and headers.
1. Simple Example
// MySDL.h - NO SDL STUFF
class MySDL
{
public:
MySDL() = default; // or whatever you need
void runtest() const; // here we'll run the 3sec window
};
Now, we can put all our SDL stuff in the cpp file:
// MySDL.cpp
#include "MySDL.h"
#include "SDL.h" // HERE WE INCLUDE SDL
void MySDL::runtest()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("yee haw", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
}
No SDL included in main.cpp, we just include our SDL interface MySDL.h.
// Now you can use your SDL interface like this
int main(int, char* [])
{
MySDL sdl;
sdl.runtest();
return 0;
}
2. Better Version
However, you would typically want something more sofisticated than a window which disappears in 3 seconds. Therefore, you might want to store class members which depends on SDL. But then, you would have to #include "SDL.h" in your MySDL.h header file, which would give you the same problems as described in your question and comments. To remove this dependency, we can use the pimpl idiom.
The header file now includes a pointer to our SDL implementation. This SDL implementation will be defined in the cpp file in order to remove the SDL dependency.
// MySDL.h
class MySDL
{
public:
MySDL() = default; // or whatever you need
~MySDL();
void doSmthWithYourWindow(/*args*/);
private:
// pointer to our SDLImplementation (defined in cpp file)
class SDLImplementation;
std::unique_ptr<SDLImplementation> _sdl;
};
In our cpp file, we define the SDLImplementation, and MySDL has access to that implementation through the _sdl pointer.
// MySDL.cpp
#include "MySDL.h"
#include "SDL.h"
// here we can store class members which depend on SDL
struct MySDL::SDLImplementation
{
SDLImplementation()
{
SDL_Init(SDL_INIT_EVERYTHING);
_window = SDL_CreateWindow("yee haw", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, SDL_WINDOW_SHOWN);
_renderer = SDL_CreateRenderer(_window, -1, 0);
SDL_SetRenderDrawColor(_renderer, 0, 255, 0, 255);
SDL_RenderClear(_renderer);
SDL_RenderPresent(_renderer);
}
// functionality of your SDL implementation
void turnWindowUpsideDown() { /* _window->turnUpsideDown(); */ }
// members depending on SDL
SDL_Window* _window;
SDL_Renderer* _renderer;
};
MySDL::~MySDL() = default;
void MySDL::doSmthWithYourWindow(/*args*/)
{
// here we have access to our SDL implementation
_sdl->turnWindowUpsideDown();
}
Just like before, we only include our MySDL.h interface in the main.cpp file.
int main(int, char* [])
{
MySDL sdl;
sdl.doSmthWithYourWindow();
return 0;
}
So I ended up deleting SDL and completely restarting with a different tutorial linked here:
https://www.youtube.com/watch?v=QQzAHcojEKg
Not really sure what the difference was but it worked. Anyways, thanks for your help and I'll put the new code here.
#include "SDL.h"
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("yee haw", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
return 0;
}
When using SDL2 (2.0.8), drawing a 2D rectangle or a line with SDL_RenderDrawRect or SDL_RenderDrawLine is not pixel perfect. There are some artifacts. Why is that? And is there a way to prevent that?
Code example:
#ifdef WIN32
#include "SDL.h"
#else
#include "SDL2/SDL.h"
#endif
int main(int argc, char* args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, 0,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_Event event;
bool quit = false;
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
{
quit = true;
break;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderDrawLine(renderer, 40, 10, 60, 10);
SDL_Rect rect{10, 10, 20, 20};
SDL_RenderDrawRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
return 0;
}
Environment:
Acer Laptop, Intel HD Graphics, NVIDIA GEFORCE 940m, Windows 10
In my Windows 10 display settings "Scale and Layout" was set to "125%". After Setting it to "100%" the rendering was pixel perfect.
Windows 10 display settings
Though this is just a workaraound. The real solution is to call the Windows API function "SetProcessDpiAwareness". I found the answer and code to do that on different Windows versions in this link:
SetProcessDpiAwareness
There are different methods to set the DPI awareness depending on the Windows OS version. It can be set programmatically or by Application Manifest. See the
Microsoft docs.
Setting "Scale and Layout" back to "125%" and calling that function at the begin of my application gives the expected result.
this dude is right. But SetProcessDpiAwareness is undefined in my case.
SetProcessDPIAware() work for me.
#ifdef _WIN32
#include <windows.h>
#endif
int main(int, char**)
{
#ifdef _WIN32
SetProcessDPIAware();// Fix DPI settings
#endif
//some code
}
I hope this code helps.
Take a look at this:
https://wiki.libsdl.org/SDL_HINT_RENDER_SCALE_QUALITY
Make sure to disable this and set it to 0. You may also wish to ensure anti-aliasting is disabled in your video drivers/NVIDIA Control Panel.
There are many upstream factors that may cause this.
This test program should create a blank window that stays open until you x-it-out. I copied it from SDL's documentation to make sure it is correct. It can be found here.
// Example program:
// Using SDL2 to create an application window
#include "SDL.h"
#include <stdio.h>
int main(int argc, char* argv[]) {
SDL_Window *window; // Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
//game loop, quitGame to quit
bool quitGame = false;
//var for checking events
SDL_Event event;
while(!quitGame) {
//Update particles
//Draw particles
//Check for events
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT)
quitGame = true;
}
}
// Close and destroy the window
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return 0;
}
It doesn't create a window and terminates immediately, but gives no errors.
I'm using Eclipse, mingw32, and the latest stable release of SDL2. SDL2's libraries and headers are within a file in my C drive. I am using a 64 bit system. I include the entire folder of SDL2's header files. The only library folder I have linked is the one within the 64 bit part of the SDL2 folder. The libraries I have linked are the ones suggested by HolyBlackCat, (in this order) mingw32, SDL2main, and SDL2. Any help is greatly appreciated. Thanks!
There's this extremely odd bug, which came seemingly out of nowhere, where my SDL 2 application has had a massive drop in frame rate (from ~60 to ~30). What's really odd about this bug is that while I move my cursor around quickly and outside of the window the frame rate speeds up back to normal.
What could be the issue? Or, how can I properly limit the framerate to exactly 60 (or whatever I please)?
EDIT: Here's the skeleton code which successfully replicates the problem:
#include <cstdio>
#include <SDL.h>
#define WIDTH 640
#define HEIGHT 480
#define FPS 60
using namespace std;
int main(int argc, char** args) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Cool Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Surface* winsurf = SDL_GetWindowSurface(window);
SDL_Renderer* winren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(winren, 255, 255, 255, 255);
bool quit = false;
int counter = 0;
int looptime = SDL_GetTicks();
while (!quit) {
SDL_RenderClear(winren);
SDL_Event e;
while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT)
quit = true;
printf("%d\n", counter++); // notice how quickly the counter speeds up
// while moving your cursor around outside
// of the window
if (SDL_GetTicks() - looptime < 1000/FPS)
SDL_Delay(1000/FPS - (SDL_GetTicks() - looptime));
looptime = SDL_GetTicks();
SDL_RenderPresent(winren);
}
SDL_Quit();
}
If anyone's interested, I fixed the problem by enabling Vsync. I added the SDL_RENDERER_PRESENTVSYNC flag to my call, like so:
SDL_Renderer* winren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
This makes animation much more fluid.