How to correctly refresh SDL2 window after resizing - c

I wrote a little SDL2 app that reacts on resizing by rearranging its contents. It works quite nice on Windows 10, but not on my Linux machine.
Here's the MCVE that (hopefully) reproduces the problem:
#include <SDL2/SDL.h>
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *w = SDL_CreateWindow("MCVE",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 250, 250,
SDL_WINDOW_ALLOW_HIGHDPI|SDL_WINDOW_RESIZABLE);
SDL_Renderer *r = SDL_CreateRenderer(w, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface *shape = SDL_CreateRGBSurface(0, 500, 500, 32, 0, 0, 0, 0);
SDL_Rect rect = { .x = 100, .y = 100, .h = 300, .w = 300 };
SDL_FillRect(shape, &rect, SDL_MapRGB(shape->format, 0xff, 0, 0));
SDL_Texture *t = SDL_CreateTextureFromSurface(r, shape);
SDL_RenderClear(r);
SDL_RenderCopy(r, t, 0, 0);
SDL_RenderPresent(r);
SDL_Event ev;
while (SDL_WaitEvent(&ev))
{
switch (ev.type)
{
case SDL_QUIT:
SDL_Quit();
return 0;
case SDL_WINDOWEVENT:
if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
SDL_RenderClear(r);
SDL_RenderCopy(r, t, 0, 0);
SDL_RenderPresent(r);
}
}
}
return 1;
}
compile command:
gcc -std=c11 -Wall -Wextra -Wno-unused-parameter -pedantic -osdlresize sdlresize.c -lSDL2main -lSDL2
Note any error checking and cleanup is skipped just for brevity, the real code is here for reference.
What I get on my Linux machine when resizing the window often looks like this:
In case you can't see the image: the content isn't properly refreshed, it shows some area to the right and the bottom with contents of whatever is below my window on the desktop.
Is there anything wrong in my handling of the SDL_WINDOWEVENT_SIZE_CHANGED? The same thing happens if I handle SDL_WINDOWEVENT_RESIZED instead...

Related

C program using SDL2 only sometimes draws Rect

When I call the following functions:
SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);
SDL_RenderClear(rend);
SDL_SetRenderDrawColor(rend, 100, 255, 80, 255);
SDL_RenderFillRect(rend, &canv);
SDL_RenderDrawRect(rend, &canv);
SDL_RenderPresent(rend);
SDL_Delay(6000);
it only sometimes draws the rectangle, at other times at keeps whatever was at the window location before, or draws the window entirely black. The above functions all return 0.
rend and canv are defined as follows:
Uint32 rend_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Renderer * rend = SDL_CreateRenderer(win, -1, rend_flags);
SDL_Rect canv;
canv.x = 0;
canv.y = 0;
canv.h = 640;
canv.w = 480;
And this is the makefile used:
CC=gcc
CFLAGS=-lSDL2
spectra: spectra.c
$(CC) -o spectra spectra.c $(CFLAGS)
So where did I go wrong, what am I overlooking?

Problem with SDL2 not running after compiling successfully

I'm having trouble running an SDL2 program, I compiled the program successfully using this command.
gcc -g main.c -o main.exe -IC:\\SDL2\\i686-w64-mingw32\\include -LC:\\SDL2\\i686-w64-mingw32\\lib -lmingw32 -lSDL2main -lSDL2 -Wall -Werror
Now that I'm trying to run it, I expect to get a window and to log hello in the console but nothing happens and the program exits immediately.
I'm using windows 10 and using the MinGw compiler.
This is the code.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
SDL_Log("hello");
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Hello, SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
bool running = true;
SDL_Event event;
while(running)
{
// Process events
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
// Clear screen
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

Why is SDL2 window fading out?

I want a quick fix to this issue:
I wrote a simple program to play around with the SDL2 libraries. A cyan box moves along a blue background from left to right. Then the window closes.
The problem is that the window's color "fades out" while the program is running. The contrast decreases significantly and it's annoying. Sometimes it happens when the box is in the middle of the window. Sometimes it happens when the box reaches the right side of the window. Sometimes it doesn't happen at all. This fading of colors seems to be sporadic and random. It is a run time issue. Theoretically, I do not see any issue with the code. What is wrong?
#include "SDL.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C"
#endif
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
window = SDL_CreateWindow("Boxes", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Rect myBox = { 200, 150, 50, 50 };
int go = 0;
while (go <= 590) {
myBox.x = go;
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
SDL_RenderFillRect(renderer, &myBox);
SDL_RenderPresent(renderer);
if (go == 0)
SDL_Delay(2000);
SDL_Delay(100);
go += 10;
}
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return EXIT_SUCCESS;
}
That's a classical SDL mistake.
You're not handling events that your window receives, and because of that your OS assumes that your program has hung up.
Inside of your while loop, add following:
SDL_Event e;
while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT)
return 0;

Basic C SDL2 program won't work with TCC while it does work with GCC (Linux)

I have the following C code (for clarity, I know it's not complete code and it should handle events and stuff like that):
#!/usr/bin/tcc -run -L/usr/lib/x86_64-linux-gnu -D_REENTRANT -DSDL_MAIN_HANDLED -I/usr/include/SDL2 -lSDL2 -lGL -lGLEW
#include <GL/glew.h>
#include <SDL.h>
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window *win = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_GLContext glContext = SDL_GL_CreateContext(win);
while (1)
{
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(win);
}
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(win);
return 0;
}
If I compile this with GCC (without the shebang line), and start the executable, it works fine, but I like the simplicity of the compile and run functionality of TCC and its speed.
However, the compiled executable gives me the following console output and then hangs forever and can't even be killed with CTRL-C:
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
I added the SDL_MAIN_HANDLED as suggested here but that didn't change anything.
Anyone?
How about proper handling of the possible errors of the SDL calls and also initializing glew?
#include <stdlib.h>
#include <SDL.h>
#include <GL/glew.h>
void exit_sdl_error(const char *message) {
SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "%s failed with SDL error %s", message, SDL_GetError());
exit(EXIT_FAILURE);
}
int main() {
const Uint32 init_flags = SDL_INIT_VIDEO;
const int gl_major = 4, gl_minor = 0;
if (!SDL_WasInit(init_flags)) {
if (SDL_Init(init_flags) != 0)
exit_sdl_error("Unable to initialize SDL");
if (SDL_InitSubSystem(init_flags) != 0)
exit_sdl_error("Unable to initialize sub system of SDL");
}
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl_major))
exit_sdl_error("Unable to set gl major version");
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl_minor))
exit_sdl_error("Unable to set gl minor version");
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE))
exit_sdl_error("Unable to set gl profile");
SDL_Window *window = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window) {
SDL_QuitSubSystem(init_flags);
exit_sdl_error("Unable to create window");
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext) {
SDL_DestroyWindow(window);
SDL_QuitSubSystem(init_flags);
exit_sdl_error("Unable to create context");
}
glewInit();
while (1)
{
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
}
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_QuitSubSystem(init_flags);
}

Evas and X11 example

I am trying to write a little application in order to understand how evas works with X11.
I haven't find a full example in the documentation only some parts that I try to use.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <Evas.h>
#include <Evas_Engine_Software_X11.h>
/*
gcc -o evas_software_x11 evas_software_x11.c $(pkg-config --libs --cflags x11 evas)
*/
#define WIDTH 640
#define HEIGHT 480
int main(int argc, char **argv)
{
Evas *canevas;
Evas_Engine_Info_Software_X11 *einfo;
Display * display;
Window win;
display = XOpenDisplay(NULL);
int s;
XEvent e;
s = DefaultScreen(display);
win = XCreateSimpleWindow( display,
RootWindow(display, s),
10,10,WIDTH,HEIGHT,1,
BlackPixel(display, s),
WhitePixel(display, s));
XSelectInput(display, win, ExposureMask | KeyPressMask);
evas_init();
/*Création et configuration du canevas*/
canevas = evas_new();
evas_output_method_set(canevas, evas_render_method_lookup("software_x11"));
evas_output_size_set(canevas, WIDTH, HEIGHT);
evas_output_viewport_set(canevas, 0, 0, WIDTH, HEIGHT);
einfo = NULL;
einfo = (Evas_Engine_Info_Software_X11 *) evas_engine_info_get(canevas);
if(!einfo)
{
printf("einfo not valide\n");
exit(EXIT_FAILURE);
}
einfo->info.display = display;
einfo->info.visual = DefaultVisual(display, DefaultScreen(display));
einfo->info.colormap = DefaultColormap(display, DefaultScreen(display));
einfo->info.drawable = win;
einfo->info.depth = DefaultDepth(display, DefaultScreen(display));
evas_engine_info_set(canevas, (Evas_Engine_Info *) einfo);
/*Création d'un fond et d'un rectangle pour l'exemple*/
Evas_Object * bg, *rect;
bg = evas_object_rectangle_add(canevas);
evas_object_move(bg, 0, 0);
evas_object_resize(bg, WIDTH, HEIGHT);
evas_object_color_set(bg, 0, 128, 0, 128); // 50% opaque vert
eavs_object_show(bg);
rect = evas_object_rectangle_add(canevas);
evas_object_move(rect, 20, 20);
evas_object_resize(rect, 100, 100);
evas_object_color_set(rect, 255, 0, 0, 255); // opaque rouge
eavs_object_show(rect);
evas_render(canevas);
while(1) {
XnextEvent(display, &e);
if (e.type == Expose)
{
}
if (e.type == KeyPress)
break;
}
evas_free(canevas);
evas_shutdown();
XCloseDisplay(d);
return EXIT_SUCCESS;
}
When I compile it I have this error:
gcc -o evas_software_x11 evas_software_x11.c $(pkg-config --libs --cflags evas x11)
evas_software_x11.c: In function ‘main’:
evas_software_x11.c:45:14: erreur: ‘struct <anonymous>’ has no member named ‘display’
einfo->info.display = display;
^
But the part einfo->info.display = display comes from the official documentation :
https://build.enlightenment.org/job/nightly_efl_gcc_x86_64/lastSuccessfulBuild/artifact/doc/html/group__Evas__Output__Method.html#details
Any idea on where I have done an error?
The documentation is not up to date.
The info structure have a member named connection instead of display ( see file
Evas_Engine_Software_X11.h and http://lists.enlightenment.fr/enlightenment-devel/att-27663/expedite_merge_1.diff ).

Resources