Fullscreening a window in SDL2 with openGL - c++

My program starts with a loading window while it is compiling shaders, loading textures etc. I then want to be able to launch a fullscreen application and use these resources. My understanding is that the openGL context must be the same before and after. I tried two methods for this: first of all I tried making a second window which was fullscreen, and used the SDL_GL_makecurrent command on this window to 'transfer' the context across (couldn't find where I read about this method), and secondly tried just fullscreening the loading window. Both of these methods resulted in the loading screen being moved to the top left corner of the screen. However opengl commands no longer ran properly in fullscreen, including clearing buffers which meant that the window contained the contents of my desktop/background applications.
Is there a proper way of doing this? Or is this a strange bug in sdl/opengl drivers?
Code to fullscreen original window:
//opengl commands work fine up to here
//now to fullscreen
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_SetWindowSize(window, 1366, 768); //tried this on either side of line above and without either line
glViewport(0, 0, 1366, 768); //update viewport
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
//window should be whited, other draw commands tried and all fail or distort
SDL_GL_SwapWindow(window);
Creating a new window and using previous context:
//Fine up to here
window2 = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1366, 768, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_SHOWN);
SDL_GL_MakeCurrent(window2, glContext); //created with SDL_GL_CreateContext(oldwindow);
//draw commands dont work
PS: running ubuntu
Update: In the second code, reusing the context in a new window, it returns an error saying 'invalid window' when it fails, which is most of the time but not always. When it fails, the screen ends up completely corrupted(black with weird white squares and patterns), ending the program will not clear the screen of this (although screenshots are perfectly fine?), but it can be restored by ctrl+f1 to terminal then ctrl+f7 back

I dont really know if its a bug. I experienced the same issue with sdl2 and opengl.
Create an regular window
attach to opengl context.
fullscreen
BOOM. black screen and crashed window.
I only noticed that issue in ubuntu.
Trought some tests i found a quick way to fix it:
Uint32 flags = 0;
flags |= SDL_WINDOW_RESIZABLE;
//bla bla bla your tags
flags |= SDL_WINDOW_OPENGL;
m_window = SDL_CreateWindow( "hello gl", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_screen.x, m_screen.y,flags);
m_glContext = SDL_GL_CreateContext(m_window);
//Set right the way the screen to fullscrene false
SDL_SetWindowFullscreen(m_window, SDL_FALSE);
Now the fullscreen seems to work without problem.

Related

SDL_Renderer: OpenGL texture just won't stick [duplicate]

I have been learning about SDL 2D programming for a while and now I wanted to create a program using SDL and OpenGL combined. I set it up like this:
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("SDL and OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
The program is for now just a black window with a white line displayed using OpenGl. Here is the code for the rendering:
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2d(1, 0);
glVertex2d(-1, 0);
glEnd();
SDL_GL_SwapWindow(window);
So the thing is, I would like to render textures additionally using pure SDL and a SDL_Renderer object, as I did before without OpenGL. I tried that out but it didn't work. Is it even possible to do that and how? What I did is creating a SDL_Renderer and then after drawing OpenGL stuff doing this:
SDL_Rect fillRect;
fillRect.w = 50;
fillRect.h = 50;
fillRect.x = 0;
fillRect.y = 0;
SDL_SetRenderDrawColor(renderer, 100, 200, 100, 0);
SDL_RenderFillRect(renderer, &fillRect);
SDL_RenderPresent(renderer);
But this does not work. The rectangle is not shown, although for some milliseconds it appears slightly. I feel like the OpenGL rendering is overwriting it.
SDL uses OpenGL (or in some cases Direct3D) and OpenGL has internal state which affects the GL calls in your program. The current version of SDL does not clearly indicate which states it changes or depends upon for any call and it does not include functions to reset to a known state. That means you should not mix SDL_Renderer with OpenGL yet.
However, if you really want this functionality now, you can try SDL_gpu (note: I'm the author). It does support mixing with OpenGL calls and custom shaders. You would want to specify which version of the OpenGL API you need (e.g. with GPU_InitRenderer(GPU_RENDERER_OPENGL_1, ...)) and reset the GL state that SDL_gpu uses each frame (GPU_ResetRendererState()). Check out the 3d demo in the SDL_gpu source repository for more.
https://github.com/grimfang4/sdl-gpu/blob/master/demos/3d/main.c
You can render to an SDL_Surface with SDL, and then convert it to a texture & upload it to the GPU using OpenGL.
Example code: http://www.sdltutorials.com/sdl-tip-sdl-surface-to-opengl-texture

Drawing 2D stuff with SDL_Renderer and OpenGL stuff with SDL_GLContext

I have been learning about SDL 2D programming for a while and now I wanted to create a program using SDL and OpenGL combined. I set it up like this:
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("SDL and OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
The program is for now just a black window with a white line displayed using OpenGl. Here is the code for the rendering:
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2d(1, 0);
glVertex2d(-1, 0);
glEnd();
SDL_GL_SwapWindow(window);
So the thing is, I would like to render textures additionally using pure SDL and a SDL_Renderer object, as I did before without OpenGL. I tried that out but it didn't work. Is it even possible to do that and how? What I did is creating a SDL_Renderer and then after drawing OpenGL stuff doing this:
SDL_Rect fillRect;
fillRect.w = 50;
fillRect.h = 50;
fillRect.x = 0;
fillRect.y = 0;
SDL_SetRenderDrawColor(renderer, 100, 200, 100, 0);
SDL_RenderFillRect(renderer, &fillRect);
SDL_RenderPresent(renderer);
But this does not work. The rectangle is not shown, although for some milliseconds it appears slightly. I feel like the OpenGL rendering is overwriting it.
SDL uses OpenGL (or in some cases Direct3D) and OpenGL has internal state which affects the GL calls in your program. The current version of SDL does not clearly indicate which states it changes or depends upon for any call and it does not include functions to reset to a known state. That means you should not mix SDL_Renderer with OpenGL yet.
However, if you really want this functionality now, you can try SDL_gpu (note: I'm the author). It does support mixing with OpenGL calls and custom shaders. You would want to specify which version of the OpenGL API you need (e.g. with GPU_InitRenderer(GPU_RENDERER_OPENGL_1, ...)) and reset the GL state that SDL_gpu uses each frame (GPU_ResetRendererState()). Check out the 3d demo in the SDL_gpu source repository for more.
https://github.com/grimfang4/sdl-gpu/blob/master/demos/3d/main.c
You can render to an SDL_Surface with SDL, and then convert it to a texture & upload it to the GPU using OpenGL.
Example code: http://www.sdltutorials.com/sdl-tip-sdl-surface-to-opengl-texture

Explanation of SDL2 windows/surfaces?

I made a short program to test out SDL2, though there are some things I don't understand how they work.
So I have created a window and a surface:
SDL_Window *window = nullptr;
SDL_Surface *windowSurface = nullptr;
Now I have this (the part I don't get):
window = SDL_CreateWindow("Window name", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windowSurface = SDL_GetWindowSurface(window);
So the first line: I use the SDL_createWindow() function to create a window called window I assume. The second line, I got no idea whats going on - explanation?
Finally I have this:
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
followed by some clean up code to set the pointers back to nullptr and exit the program/destroy windows etc.
The code you have pasted does the following things: Creates a SDL window called "Window name", sets its horizontal and vertical positions to center, sets the window size to 640 x 480 and marks it as shown.
The second line acquires the SDL surface bind to this window.
What this means is: Create Window , actually sets up and openGL window and a GPU texture (the Surface, althou SDL2 has seperate class for Textures), to which it is going to draw. Modifying the surface acquired with GetWindowSurface will modify the pixel on the window you have just created.
Bliting is applying a array of pixel to a target texture, in the meaning : hey i got this image/prerendered frame etc.. and I want to apply it to this surface so i can show it. Blit it.
I hope this is helpful : >
You can find more information for SDL here
Official SDL wiki
LazyFoo
LazyFoo provides a full tutorial and explanations of everything for the old SDL, but a lot of the things are the same in SDL2

SDL2 OpenGL window shrinking and changing mouse coordinates

After shrinking my applications to window size mouse coordinates won't change. Graphics work fine, just mouse coordinates are problem.
My applications native size is 1920x1080. But I wan't to shrink app to 1280x720.
Here is what I'm doing right now:
Create window with 1280x720 w/h
appWindow = SDL_CreateWindow(GAME_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOWPOS_CENTERED);
I set glViewport to match with window
glViewport(0,0,1280,720);
I make set glOrtho with native size 1920x1080
glOrtho(0, 1920, 1080, 0, -1, 1);
Like I already said, by doing this graphics do scale on new window size but mouse coordinates don't change and i need to know how to change them.
I am not sure i understand your question, but i think here is problem: glOrtho() is opengl comand not sdl, so it affects opengl graphics only. Mouse and windowing is controlled by SDL in your case.
I dont understand what you are trying to do by saying "My applications native size is 1920x1080. But I wan't to shrink app to 1280x720." if you want to resize window use SDL_SetWindowSize. And then adjust opengl viewport and projection with glViewport and glOrtho, so your opengl view and sdl window size is in sync.
Edit 1: If you want to render as it is now, by using larger view than windows, then you need to calculate mouse position by your self. sdl gives you mouse relative to window size not opengl view and projection. Math should be quite simple if you are just scaling the view.
Edit 2: in your case glOrtho(0, 1920, 1080, 0, -1, 1) projects 1920x1080 image to glViewport(0,0, 1280 ,720) view. So it scales down if i am not mistaken. So you need to scale mouse pos down to relative to scale ratio:
untested code:
mouseX= 1920.0/1280.0 * winMouse.x
mouseY= 1080.0/720.0 * winMouse.y;
I ussually experiment alot, so just try to understand what opengl does and experiment.

DWM being disabled causes front-buffer corruption in OpenGL window

I'm experiencing some weird graphical corruption with my SDL2 + OpenGL GUI application. Now I apologize if I'm not using the appropriate term to describe the situation. It seems that the front buffer is being invalidated and other applications are being drawn in the buffer?
Important note: this corruption only occurs in Windows XP or when using the Windows Basic theme in Windows 7.
The corruption can be reproduced in a few ways:
by moving the window around. It seems that the front buffer gets corrupted with the image of other applications in front or behind it.
if there's an application behind, it'll occasionally flash into the front buffer.
I can load up a google webpage in Chrome above the opengl application, close the chrome process, and then move the opengl application around and I'll see the google homepage covering the whole inside of the window.
by moving another application over the opengl window.
It seems that I also see the corruption when I'm moving other windows around, even if they don't overlap the opengl window, so long as I've already tried one of the ones posted just above.
inline int UI::RenderingThread()
{
UI::Window::Instance().RenderingThreadEnter();
while( UI::Window::Instance().RenderingThreadActive() )
{
unsigned int ticks = SDL_GetTicks();
UI::Window::Instance().RenderingThreadUpdate();
UI::Window::Instance().RenderingThreadRender();
ticks = SDL_GetTicks() - ticks;
if( ticks < 33 )
{
SDL_Delay( 33 - ticks );
}
}
UI::Window::Instance().RenderingThreadExit();
return 0;
}
As you probably guessed, I'm using multithreading and I have my rendering in a separate thread. Within the RenderingThreadRender() function, I only redraw if there's a change in content, or I've requested a redraw.
case SDL_WINDOWEVENT:
switch( sdl_event.window.event )
{
default:
UI::Window::Instance().Redraw();
break;
}
This is done to allow all SDL_WINDOWEVENT events to redraw in hopes that one of them would fix the problem. Unfortunately that has not solved the issue.
I'm hesitant to simply constantly redraw my application at 30 or 60 fps since I've noticed that by doing so, other application would be sluggish when moving them around.
Initialization:
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
this->window = SDL_CreateWindow( this->caption.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
UI::WindowSize::Instance().GetWindowWidth(), UI::WindowSize::Instance().GetWindowHeight(),
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, UI::WindowSize::Instance().GetWindowWidth(), UI::WindowSize::Instance().GetWindowHeight());
// Set the OpenGL view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, UI::WindowSize::Instance().GetWindowWidth(), UI::WindowSize::Instance().GetWindowHeight(), 0, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glDisable( GL_DITHER );
Rendering:
if( this->redraw )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// a few DrawArrays
SDL_GL_SwapWindow( this->window );
}
Does anyone have any idea what could be causing this issue, and how to fix it?
EDIT: Some more research has pointed me to the following two questions:
https://superuser.com/questions/316738/what-happens-with-the-off-screen-front-buffers-in-windows-7-when-dwm-is-disabled
C++ OpenGL window only tracks background
However, this doesn't solve my problem since I'm already using Double Buffering.
I've found the solution to my problem. It's unlikely that anyone will experience the same issue that I was having, but you never know. Essentially a C# Window of size equal or larger than my application, was being created before. This window was hidden, however because XP has a global framebuffer instead of a composition, there was a conflict causing the corruption.
All in all, if you're having a similar issue, make sure there isn't another context.