Wrong SDL origin axis in 1080x1920 resolution - c++

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;

Related

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.

SDL Pong Movement Bug

The problem with my code is that I am making a pong game in SDL 2.0 in c++. I did everything until creating the movement. When the player paddle moves, it leaves behind a trail in the same color as the paddle. I watched some videos on YouTube, but when they do the movement it's nice and clear and for me to fix this but I need to recolor the background every time the player moves, which makes it being all flashy and if I hold the button I don't see the paddle at all.
#include<iostream>
#include<SDL2/SDL.h>
#include<SDL2/SDL_image.h>
#include<windows.h>
#define width 800
#define height 600
using namespace std;
bool run = true;
class Player{
private:
SDL_Window* window = SDL_CreateWindow("Pong!", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE);
SDL_Surface* Screen = SDL_GetWindowSurface(window);
Uint32 screen_color = SDL_MapRGB(Screen->format, 0, 0, 0);
Uint32 In_game_RGB = SDL_MapRGB(Screen->format, 255, 255, 255);
SDL_Rect Pl;
SDL_Rect AI;
SDL_Rect Ball;
SDL_Rect ClearP;
SDL_Rect ClearAI;
public:
Player(){
//Player parameters
Pl.x = 60;Pl.y = 225;Pl.w = 25;Pl.h = 200;
//AI parameters
AI.x = 720;AI.y = 225;AI.w = 25;AI.h = 200;
//Ball parameters
Ball.x = width/2;Ball.y = height/2+10;Ball.w = 25;Ball.h = 25;
//Recoloring parameters
ClearP.x = 0;ClearP.y = 0; ClearP.w = 375;ClearP.h = height;
ClearAI.x = 425;ClearAI.y = 0;ClearAI.w = 375;ClearAI.h = height;
//Make the screen color black
SDL_FillRect(Screen, NULL, screen_color);
}
void scrUpdate(){
SDL_UpdateWindowSurface(window);
}
void drawPlayer(){
SDL_FillRect(Screen, &Pl, In_game_RGB);
}
void drawComputer(){
SDL_FillRect(Screen, &AI, In_game_RGB);
}
void ball(){
SDL_FillRect(Screen, &Ball, In_game_RGB);
}
void Movement(){
if(GetAsyncKeyState(VK_DOWN)){
Pl.y += 2;
SDL_FillRect(Screen,&ClearP,screen_color);
}
if(GetAsyncKeyState(VK_UP)){
SDL_FillRect(Screen,&ClearP,screen_color);
Pl.y -= 2;
}
}
};
void EventCheck(){
SDL_Event event;
if(SDL_PollEvent(&event)){
if(event.type == SDL_QUIT){
run = false;
}
}
}
int main( int argc, char *argv[] )
{
SDL_Init(SDL_INIT_EVERYTHING);
Player Play;
//Player Computer();
while(run){
Play.scrUpdate();
Play.drawPlayer();
Play.drawComputer();
Play.ball();
Play.Movement();
EventCheck();
}
SDL_Quit();
return EXIT_SUCCESS;
}
It would help to show some code or an example of what you have been doing, or a link to one of the videos you have been watching:
Youtube tutorial
but I suggest taking a look at:
screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE); and SDL_Flip(screen) as those have to do with screen buffering and drawing.
Another possibilty is that you are running an outdated version of SDL, or an incompatible one with your current system.
To be able to give a more complete and proper answer, I'd highly suggest adding more information about your code, screenshots of results and your version of SDL and operating system.
Also, you said it was flashy when you hold the paddle. I think it must be that you are performing your logic to move the paddle and you redraw the paddle once it's still. If you are redrawing the entire screen constantly, consider double buffering.

Switching Between windowed and full screen in OpenGL/GLFW 3.2

I am in the process of learning OpenGL on Linux but I can't get mode switching working (windowed to full screen and back).
The window appears to be going into full screen but but not looking correct. To switch modes a new window is being created and old one destroyed.
void OpenGLWindow::FullScreen(bool fullScreen, int width, int height)
{
GLFWwindow *oldHandle = m_window;
m_fullscreen = fullScreen;
m_width = width;
m_height = height;
m_window = glfwCreateWindow(width, height, m_caption.c_str(),
fullScreen ? m_monitor : NULL, m_window);
if (m_window == NULL)
{
glfwTerminate();
throw std::runtime_error("Failed to recreate window.");
}
glfwDestroyWindow(oldHandle);
m_camera->Invalidate();
// Use entire window for rendering.
glViewport(0, 0, width, height);
glfwMakeContextCurrent(m_window);
glfwSwapInterval(1);
if (m_keyboardHandler) SetKeyboardHandler(m_keyboardHandler);
}
Initial Window
Full Screen (incorrect)
Return to Windowed
Updates to Question
I have updated the code to use your code and getting the same issue. On your suggestion I am now updating the camera, but again no avail :(
void OpenGLCamera::Invalidate()
{
RecalculateProjection(m_perspProjInfo->Width(), m_perspProjInfo->Height());
m_recalculateViewMatrix = true;
m_recalculatePerspectiveMatrix = true;
m_recalculateProjectionMatrix = true;
}
void OpenGLCamera::RecalculateProjection(int width, int height)
{
float aspectRatio = float(width) / height;
float frustumYScale = cotangent(degreesToRadians(
m_perspProjInfo->FieldOfView() / 2));
float frustumXScale = frustumYScale;
if (width > height)
{
// Shrink the x scale in eye-coordinate space, so that when geometry is
// projected to ndc-space, it is widened out to become square.
m_projectionMatrix[0][0] = frustumXScale / aspectRatio;
m_projectionMatrix[1][1] = frustumYScale;
}
else {
// Shrink the y scale in eye-coordinate space, so that when geometry is
// projected to ndc-space, it is widened out to become square.
m_projectionMatrix[0][0] = frustumXScale;
m_projectionMatrix[1][1] = frustumYScale * aspectRatio;
}
}
Rabbid : When I resize:
Rabbid : When I go to full screen:
In the following, I'll describe a small but handy class, which deals with resizing a GLFW window and handles switch fullscreen window on and off.
All the used GLFW functions are well documented in the GLFW documentation.
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <array>
#include <stdexcept>
class OpenGLWindow
{
private:
std::array< int, 2 > _wndPos {0, 0};
std::array< int, 2 > _wndSize {0, 0};
std::array< int, 2 > _vpSize {0, 0};
bool _updateViewport = true;
GLFWwindow * _wnd = nullptr;
GLFWmonitor * _monitor = nullptr;
void Resize( int cx, int cy );
public:
void Init( int width, int height );
static void CallbackResize(GLFWwindow* window, int cx, int cy);
void MainLoop ( void );
bool IsFullscreen( void );
void SetFullScreen( bool fullscreen );
};
When creating the window, then the user function pointer (glfwSetWindowUserPointer) is set to the window management class. And the resize callback is set by glfwSetWindowSizeCallback. After the window is created its current size and position can be get by glfwGetWindowPos and glfwGetWindowSize.
void OpenGLWindow::Init( int width, int height )
{
_wnd = glfwCreateWindow( width, height, "OGL window", nullptr, nullptr );
if ( _wnd == nullptr )
{
glfwTerminate();
throw std::runtime_error( "error initializing window" );
}
glfwMakeContextCurrent( _wnd );
glfwSetWindowUserPointer( _wnd, this );
glfwSetWindowSizeCallback( _wnd, OpenGLWindow::CallbackResize );
_monitor = glfwGetPrimaryMonitor();
glfwGetWindowSize( _wnd, &_wndSize[0], &_wndSize[1] );
glfwGetWindowPos( _wnd, &_wndPos[0], &_wndPos[1] );
_updateViewport = true;
}
When the resize notification occurs, then the pointer to the window management class can be get by glfwGetWindowUserPointer:
static void OpenGLWindow::CallbackResize(GLFWwindow* window, int cx, int cy)
{
void *ptr = glfwGetWindowUserPointer( window );
if ( OpenGLWindow *wndPtr = static_cast<OpenGLWindow*>( ptr ) )
wndPtr->Resize( cx, cy );
}
Any change of the window size is notified and the new window size is stored (glfwGetWindowSize):
void OpenGLWindow::Resize( int cx, int cy )
{
_updateViewport = true;
}
When the window size has changed, then the viewport has to be suited to the window size (glViewport). This can be done in the main loop of the application:
void OpenGLWindow::MainLoop ( void )
{
while (!glfwWindowShouldClose(_wnd))
{
if ( _updateViewport )
{
glfwGetFramebufferSize( _wnd, &_vpSize[0], &_vpSize[1] );
glViewport( 0, 0, _vpSize[0], _vpSize[1] );
_updateViewport = false;
}
// ..... render the scene
glfwSwapBuffers(_wnd);
glfwPollEvents();
}
}
If the current window is in full screen mode, can be achieved by asking for the monitor that the window uses for full screen mode (glfwGetWindowMonitor):
bool OpenGLWindow::IsFullscreen( void )
{
return glfwGetWindowMonitor( _wnd ) != nullptr;
}
To switch the full screen mode on and off, glfwSetWindowMonitor has to be called, either with the monitor for the full screen mode, or with nullptr:
void OpenGLWindow::SetFullScreen( bool fullscreen )
{
if ( IsFullscreen() == fullscreen )
return;
if ( fullscreen )
{
// backup window position and window size
glfwGetWindowPos( _wnd, &_wndPos[0], &_wndPos[1] );
glfwGetWindowSize( _wnd, &_wndSize[0], &_wndSize[1] );
// get resolution of monitor
const GLFWvidmode * mode = glfwGetVideoMode(_monitor);
// switch to full screen
glfwSetWindowMonitor( _wnd, _monitor, 0, 0, mode->width, mode->height, 0 );
}
else
{
// restore last window size and position
glfwSetWindowMonitor( _wnd, nullptr, _wndPos[0], _wndPos[1], _wndSize[0], _wndSize[1], 0 );
}
_updateViewport = true;
}
I recommend you to not create a new Window with glfwCreateWindow when you just want to switch between windowed and fullscreen. Use glfwSetWindowMonitor instead.
When you create a window with fullscreen enabled, you have to pass arguments which are compatible with a video mode on the monitor. You can get the standard video mode on the primary monitor like this:
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
and to switch to fullscreen:
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
Just pass a nullptr-mode and your own values of course:
glfwSetWindowMonitor(window, nullptr, 0, 0, windowWidth, windowHeight, windowRefreshRate);
And don't forget to resize the viewport and update the camera.
Are you resizing the viewport and updating the camera when the user resizes the window?
There are a couple of issues with your code:
Assuming that glfwCreateWindow will set the resolution to width * height in fullscreen mode is not correct. The GLFW documentation states (emphasis mine):
For full screen windows, the specified size becomes the resolution of the window's desired video mode. As long as a full screen window is not iconified, the supported video mode most closely matching the desired video mode is set for the specified monitor.
Assuming that the window size is specified in "pixels" is not correct either.Quoting the relevant part of the documentation again:
While the size of a window is measured in screen coordinates, OpenGL works with pixels. The size you pass into glViewport, for example, should be in pixels. On some machines screen coordinates and pixels are the same, but on others they will not be. There is a second set of functions to retrieve the size, in pixels, of the framebuffer of a window.
Issues 1 and 2 can be solved by simply calling glfwGetFramebufferSize after the window was created. This leaves us with issue 3:
You call glViewport without having a current GL context -
resulting in undefined behavior, and especially in not setting the viewport at all. Now that is actually an interesting one, because the initial viewport for the new context will be the full new window, so that your mistakes 1 and 2 have no direct effect. They still might have some effect later if your code relies on m_width and m_height containing useful values, though.

Create a 32-bit root window in xlib

I've been at this for days now, but i just can't seem to figure out how to create a 32 bit root window so that I can use RGBA colors on the child window, and the child window cannot use 32-bit color depth (24-bit for RGB, and 8-bit for Alpha channel) if the parent, or in this case root window, does not have 32-bit color depth. I am using the following code to set the background of the root window to an RGB image which has a color depth of 24-bit, thus when I set XCreatePixmap to a color depth of 24 bit it just works, but i need this root window to have a color depth of 32-bit for alpha compositing:
/* displays an image or sets root background
* PUBLIC DOMAIN - CC0 http://creativecommons.org/publicdomain/zero/1.0/
* J.Mayo 2013
*
* gcc -Wall -W -g3 -o background background.c -lX11 -lImlib2
*
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <Imlib2.h>
struct screenAttributes {
int height;
int width;
};
struct screenAttributes screenAttr;
void initializeScreenAttributes(Screen *screen) {
screenAttr.height=screen->height;
screenAttr.width=screen->width;
}
int main(int argc, char **argv)
{
Imlib_Image img;
Display *dpy;
Pixmap pix;
Window root;
Screen *scn;
// Window topPanel;
int width, height;
const char *filename = "/sampleImage.png";
img = imlib_load_image(filename);
if (!img) {
fprintf(stderr, "%s:Unable to load image\n", filename);
goto usage;
}
imlib_context_set_image(img);
width = imlib_image_get_width();
height = imlib_image_get_height();
dpy = XOpenDisplay(NULL);
if (!dpy) return 0;
scn = DefaultScreenOfDisplay(dpy);
root = DefaultRootWindow(dpy);
pix = XCreatePixmap(dpy, root, width, height,32); //when depth is set to 24 it just works, but when it is set to 32 it fails.
//scale the image
initializeScreenAttributes(scn);
imlib_blend_image_onto_image(img,0,0,0,width,height,0,0,
screenAttr.width, screenAttr.height);
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
imlib_context_set_drawable(pix);
imlib_render_image_on_drawable(0, 0);
XSetWindowBackgroundPixmap(dpy, root, pix);
XClearWindow(dpy, root);
while (XPending(dpy)) {
XEvent ev;
XNextEvent(dpy, &ev);
}
XFreePixmap(dpy, pix);
imlib_free_image();
sleep(10);
//XFreePixmap(dpy, pix);
//imlib_free_image();
XCloseDisplay(dpy);
return 0;
usage:
fprintf(stderr, "usage: %s <image_file>\n", argv[0]);
return 1;
}
when I set XCreapePixmap to a color depth of 32-bit, I get:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor Opcode of failed request: 3 (X_ShmPutImage)
Serial number of failed request : 28
Current serial number in output stream: 29 xinit: connection to X server lost
So, In other words I'm not quite sure as to how to set the color depth of the root window to 32-bit and have a 24-bit RGB image set as the background of the root window.
Thanks!
P.S. I do not have any window managers or any desktop environment installed, so using any of the available tools in those is out of the question.
No. You don't have to have root window be depth 32 to have children be depth 32
too. Otherwise how on earth do you think windows can have alpha channels in a
compositor? How do you think this:
http://www.enlightenment.org/ss/e-5872c6ec3ddce1.54730231.png
is possible without 2 of those windows having 32bit depth? (the 2 on the left -
clock and translucent terminal). :)
The way translucency WORKS is a compositor intervenes (these days usually your
window manager) and is composites the 32bit windows on top (also possibly deals
with redrawing root window too at the bottom - it may depend though). so saying "I don't have a compositor/window manager so that's out of the question" is basically saying "I don't want to do the one and only thing I HAVE TO DO in order to get translucency" so I suggest you re-evaluate that position.
So what you want really is a compositor AND 32bit windows. Either use a
compositing window manager and then create 32bit windows, OR run a separate
compositor and your existing WM, or write your own compositor... (not going to
be much fun to get this right AND fast)...
Now to create an ARGB window you'll need help from XRender for the visual. Like the below where disp is your Xlib Display and parent is the parent Window (e.g. root):
Window win;
XSetWindowAttributes attr;
XWindowAttributes att;
XVisualInfo *xvi;
XVisualInfo vi_in;
int nvi, i, scr = 0;
XRenderPictFormat *fmt;
Visual *vis;
vi_in.screen = scr;
vi_in.depth = 32;
vi_in.class = TrueColor;
xvi = XGetVisualInfo(disp,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&vi_in,
&nvi);
if (!xvi) return 0;
vis = NULL;
for (i = 0; i < nvi; i++)
{
fmt = XRenderFindVisualFormat(disp, xvi[i].visual);
if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
{
vis = xvi[i].visual;
break;
}
}
XFree (xvi);
attr.backing_store = NotUseful;
attr.override_redirect = 0;
attr.colormap = XCreateColormap(disp, parent,
vis, AllocNone);
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = 0;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(disp, parent,
x, y, w, h, 0,
32,
InputOutput,
vis,
CWBackingStore |
CWOverrideRedirect |
CWColormap |
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
Code comes from here: https://git.enlightenment.org/core/efl.git/tree/src/lib/ecore_x/ecore_x_window.c#n1644
We used to have an XCB back-end and all this code in XCB, but we've given up on XCB after a decade or so. If you clone the above and dig through history you'll fine the ecore_x dir used to have xlib and xcb sub-dirs if you really want to dig that out.
This is why I wrote an xlib abstractor/detail filler because it's a lot less code to write if you hide common verbose Xlib usage behind simpler APIs.
Looks like you have exactly the same problem as I described here: How to upload 32 bit image to server-side pixmap
If you create 32-bit window and you have 24 bit root, you can't use DefaultVisualOfScreen / DefaultColormapOfScreen - they'l set visual/colormap that are valid for root (and thus, 24 bit).
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
I'm not very familiar with imlib api, but it looks you should be able to create colormap for your window/pixmap manually and pass it to imlib
The easiest way to create a 32-bit-deep window:
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
Window win = XCreateWindow(display, DefaultRootWindow(display),
0, 0, width, height, 0,
vinfo.depth, // <---------------!!!
InputOutput,
vinfo.visual, // <---------------!!!
mask, &attr);
You cannot have the root window to have the depth you want — it already exists and has the depth it has.
Would like to offer a simpler solution (basically the same as #n.m. solution, but has some more code):
Display *d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
XSetWindowAttributes attrs;
attrs.override_redirect = true;
XVisualInfo vinfo;
if (!XMatchVisualInfo(d, DefaultScreen(d), 32, TrueColor, &vinfo)) {
printf("No visual found supporting 32 bit color, terminating\n");
exit(EXIT_FAILURE);
}
attrs.colormap = XCreateColormap(d, root, vinfo.visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
// Window XCreateWindow(
// Display *display, Window parent,
// int x, int y, unsigned int width, unsigned int height, unsigned int border_width,
// int depth, unsigned int class,
// Visual *visual,
// unsigned long valuemask, XSetWindowAttributes *attributes
// );
Window overlay = XCreateWindow(
d, root,
0, 0, 200, 200, 0,
vinfo.depth, InputOutput,
vinfo.visual,
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
);
Basically, you need to specify a color map, background pixel (CWBackPixel) and border pixel, in addition to getting the proper visual. Instead of looping over all available visuals with XGetVisualInfo, XMatchVisualInfo does the work for you. Note that I am not performing error checks for this process, which you should implement in production

SDL renderer gives crap on my window (how to use renderer properly?)

so I got the following code(piece):
_Bool create_new_window(rectanglestruct *rectangle, colorstruct *colorfill, char *winname)
{
....
log_printf("creating main renderer for window ( window : %s )\n", ptr->winname);
// Setup renderer
SDL_Renderer *renderer = SDL_CreateRenderer( ptr->window, -1, SDL_RENDERER_ACCELERATED);
ptr->renderer = renderer;
if (colorfill != NULL)
{
log_printf("\n - background color set r=%d g=%d b=%d with opacity of %d\n", colorfill->r,colorfill->g,colorfill->b, colorfill->opacity);
// Set render color to red ( background will be rendered in this color )
SDL_SetRenderDrawColor( ptr->renderer, colorfill->r,colorfill->g,colorfill->b, colorfill->opacity );
log_printf("background rendered\n");
}
// Clear window
SDL_RenderClear( ptr->renderer );
SDL_ShowWindow(ptr->window);
SDL_RenderPresent( ptr->renderer );
getchar();
with
typedef struct SDL_Window SDL_Window;
typedef struct windowstruct {
char *winname;
SDL_Window *window;
SDL_Renderer *renderer;
struct windowstruct *next;
struct windowstruct *previous;
} windowstruct;
static windowstruct *root = NULL;
and
typedef struct colorstruct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t opacity;
} colorstruct;
With in main:
_Bool start_SDL(void)
// scope this
{
//draw background
colorstruct *colorfill = malloc(sizeof(rectanglestruct));
colorfill->r = 0xFF;
colorfill->g = 0xFF;
colorfill->b = 0xFF;
colorfill->opacity = 0xFF;
rectanglestruct *winplace = malloc(sizeof(rectanglestruct));
winplace->x = 0;
winplace->y = 0;
winplace->w = 300;
winplace->h = 300;
create_new_window(winplace, colorfill, "appscreen");
free(colorfill);
free(winplace);
}
and
_Bool start_SDL(void)
{
//Initialization flag
_Bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
log_printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
}
and I got the following output (after a couple of times):
The point is I thought that the renderer was just a copy of the screen like a buffer in which you can write and refresh on the screen. But I gues not?
No, SDL_Renderer implements SDL2 drawing, usually with hardware-accelerated backend. Your image is corrupt because you didn't issue redraw at appropriate time. If your window needs redraw (resized, overshadowed by other window or sceen borders) - you have to draw again and present result (this is in fact the same for every windowing library; even in GUI toolkits like Qt or GTK if your callback didn't return quickly, you can experience the same corruption). You can render to texture and then display it again if your image remains unchanged and calculations are heavy.
To do what you've said would require accumulating all data sent to renderer (may be high memory usage) and either calling update on regular intervals or on events, or taking away main loop from calling side (like most GUI toolkits do), which is against SDL design. Also, since SDL's main target are video games, scenes there are rarely static.
Before SDL2 there was no renderer and SDL only provided display surface to which you draw, but it is quite the same basic concept, it wouldn't update all by itself.
It doesn't mean it cannot be done with SDL, however - it gives you much more control. If you want to redraw only when it is really required - watch for SDL_WindowEvent.