SDL2 + OpenGL access violation - c++

This works fine:
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCR_WIDTH, SCR_HEIGHT, SDL_WINDOW_OPENGL);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GLContext mainContext = SDL_GL_CreateContext(window);
gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress);
SDL_Event event;
int running = 1;
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
...
return 0;
}
But if I wrap the initialization into a class I get an access violation when I call glCreateShader even though I'm not getting any error messages when initializing SDL and OpenGL:
int main(int argc, char** argv)
{
WindowManager wm;
if (!wm.Construct())
return 0;
SDL_Event event;
int running = 1;
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); //<---- access violation here
...
return 0;
}
Here is my WindowManager class with the relevant functions:
class WindowManager
{
public:
WindowManager() = default;
bool Construct()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0);
return false;
mWindow = SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width,
height, SDL_WINDOW_OPENGL);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
mContext = SDL_GL_CreateContext(mWindow);
if (!mWindow)
{
spdlog::error("WindowManager could not be created!");
return false;
}
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
{
spdlog::error("Failed to initialize GLAD!");
return false;
}
return true;
}
SDL_Window* mWindow;
SDL_GLContext mContext;
};
If anyone could some shine some light on what the issue could be I would greatly appreciate it!

Since I was compiling WindowManager into a dll and using it in a separate project, I essentially made two programs.
Program A had an initialized OpenGL context but Program B that was using WindowManager did not.
So I had to write a function to expose the glProcAddress to Program B in order to make raw OpenGL calls such as glCreateShader().

Related

Artifact of the black line in the client area

I have a black line artifact in the client area that disappears when the window is resized:
I called glViewport:
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <glad/glad.h>
#include <iostream>
SDL_Window *window;
const float maxFPS = 5.f;
void fatalError(const std::string &message)
{
std::cout << message << std::endl;
if (window)
{
SDL_DestroyWindow(window);
}
SDL_Quit();
exit(-1);
}
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fatalError("Failed to initialize");
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
const int winW = 300;
const int winH = 300;
window = SDL_CreateWindow("OpenGL, SDL2, C++",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
winW,
winH,
SDL_WINDOW_OPENGL);
if (!window)
{
fatalError("Failed to create the SDL window");
}
SDL_SetWindowResizable(window, SDL_TRUE);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext)
{
fatalError("Failed to create the SDL_GL context");
}
if (!gladLoadGL())
{
fatalError("Failed to initialize the GLAD library");
}
glViewport(0, 0, winW, winH);
glClearColor(0.5f, 0.5f, 1.f, 1.f);
SDL_Event event;
bool running = true;
while (running)
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
switch (event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
glViewport(0, 0, event.window.data1, event.window.data2);
break;
}
break;
}
}
float startTicks = SDL_GetTicks();
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
// Limit FPS to the max FPS
float frameTicks = SDL_GetTicks() - startTicks;
if (1000.f / maxFPS > frameTicks)
{
SDL_Delay(1000.f / maxFPS - frameTicks);
}
}
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
makefile
# build command: mingw32-make
# -mwindows - a key to hide the console
INC = -I"E:\Libs\SDL2-2.24.0-mingw-64bit\include" \
-I"E:\Libs\glad-0.1.36-mingw-64bit\include"
LIB = -L"E:\Libs\SDL2-2.24.0-mingw-64bit\lib" \
-L"E:\Libs\glad-0.1.36-mingw-64bit\lib"
all: main.o
g++ main.o $(LIB) -lSDL2.dll -lglad -o app.exe
main.o: main.cpp
g++ -c $(INC) main.cpp
The same topic on the official SDL2 forum: https://discourse.libsdl.org/t/artifact-of-the-black-line-in-the-client-area/39110
Not sure if it matters but the
docs says you should
call SDL_GL_SetAttribute before creating the window.
#Peter87 I tried it but everything the same:
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fatalError("Failed to initialize");
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
const int winW = 300;
const int winH = 300;
window = SDL_CreateWindow("OpenGL, SDL2, C++",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
winW,
winH,
SDL_WINDOW_OPENGL);
if (!window)
{
fatalError("Failed to create the SDL window");
}
SDL_SetWindowResizable(window, SDL_TRUE);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext)
{
fatalError("Failed to create the SDL_GL context");
}
It appears to be a SDL bug, though for me the effect was different (the window wasn't resizable at all).
Instead of calling SDL_SetWindowResizable(window, SDL_TRUE);, pass SDL_WINDOW_RESIZABLE when creating the window.

How to center an opengl window with glfw?

I wanna draw an opengl window in center of the screen,however I searched everywhere but didn't find any answer to it. Below is a common snippet code of creating a window But it always show up in most left-top position.How can I control it.
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(400,200,"LearnOpenGl",NULL,NULL);
if(window == NULL)
{
cout<<"Failed to create GLFW window!!"<<endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout<<"Failed to initialize GLAD!!"<<endl;
return -1;
}
glViewport(400, 400, 100, 200);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while(!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
}
Please use this function "glfwSetWindowPos".
Here is an example.
#Himanshu answered a question on how to get the max-width and max-height of a window aka window size How to get maximum possible window size when creating window in MFC?
So with that piece of code, you can center it like below:
int width=800;// could declare them as "const int" if you like
int hight=800;
GLFWwindow* window = glfwCreateWindow(width,hight, "OpenGL", NULL, NULL);
int max_width = GetSystemMetrics(SM_CXSCREEN);
int max_hieght = GetSystemMetrics(SM_CYSCREEN);
glfwSetWindowMonitor(window, NULL, (max_width/2)-(width/2), (max_hieght/2) - (height/2), width, height, GLFW_DONT_CARE);
Here is a sample from my game engine made using glad and glfw it uses the windows api to find to screen resolution and then centers the window accordingly.
#include <iostream>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
#include <Windows.h>
const unsigned int width = 1600;
const unsigned int height = 900;
const char* title = "Frog2D";
void getDesktopResolution(int& horizontal, int& vertical)
{
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
GetWindowRect(hDesktop, &desktop);
horizontal = desktop.right;
vertical = desktop.bottom;
}
int main()
{
glfwInit();
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); //borderless
int horizontal = 0;
int vertical = 0;
getDesktopResolution(horizontal, vertical);
GLFWwindow* window = glfwCreateWindow(width, height, title, NULL, NULL);
glfwSetWindowPos(window, horizontal / 2 - width / 2, vertical / 2 - height / 2);
return 0;
}

SDL2 textures don't work with pixel format ARGB2101010

I am trying to use a texture with the SDL_PIXELFORMAT_ARGB2101010 color format but I only get a black texture. The same program works when using the SDL_PIXELFORMAT_ARG88888 format.
None of SDL's variables are null. This is my code:
#include <SDL2/SDL.h>
int main(int argc, const char * argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *win = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, 0);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE);
SDL_Texture *tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB2101010, SDL_TEXTUREACCESS_STREAMING, bufferWidth, bufferHeight);
uint32_t* buffer = new uint32_t[bufferWidth * bufferHeight];
for(int bufferIdx = 0; bufferIdx < bufferWidth * bufferHeight; bufferIdx++) {
buffer[bufferIdx] = 0xc0ffffff;
}
SDL_Event event;
while(running) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT)
running = false;
}
SDL_UpdateTexture(tex, nullptr, buffer, bufferWidth * 4);
SDL_RenderCopy(ren, tex, nullptr, nullptr);
SDL_RenderPresent(ren);
}
}
This is some of my hardware and software:
AMD Radeon Pro 5500M GPU
SDL Version 2.0.14
MacOS 11.1
C++14
Compiled with default Xcode 12.3 settings

SDL_FINGERDOWN not registering correctly

I don't why SDL_FINGERDOWN records
even simple touch event. It should register on Sliding finger down as name says, right? I use android N for testing.
Here is my code
#include "SDL.h"
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
int r, g, b;
r = g = b = 0;
SDL_Window *window;
window = SDL_CreateWindow("S", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 720, 1320, SDL_WINDOW_RESIZABLE);
SDL_Surface *screen = SDL_GetWindowSurface(window);
Uint32 white = SDL_MapRGB(screen->format, 255, 255, 255);
SDL_FillRect(screen, NULL, white);
SDL_UpdateWindowSurface(window);
SDL_Event event;
bool running = true;
while (running)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_FINGERDOWN)
{
running = false;
break;
}
//end if
} //end inner while
}
SDL_DestroyWindow(window);
SDL_Quit();
}
You have misunderstood meaning of SDL_FINGERDOWN and SDL_FINGERUP.
When you land your finger on touch screen then that's event of type SDL_FINGERDOWN.When you lift up your finger from touch screen then that's event of type SDL_FINGERUP.

From SMFL to SDL 2.0

Here is some code in SMFL
RenderWindow window(VideoMode(320, 480), "The Game!");
Texture t1,t2,t3;
t1.loadFromFile("images/tiles.png");
t2.loadFromFile("images/background.png");
t3.loadFromFile("images/frame.png");
Sprite s(t1), background(t2), frame(t3);
Does SDL 2.0 has functions like this and how to convert them to SDL 2.0
yes, all is there:
https://programmersranch.blogspot.kr/2014/03/sdl2-animations-with-sprite-sheets.html
#include <SDL.h>
#include <SDL_image.h>
int main(int argc, char ** argv)
{
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
SDL_Window * window = SDL_CreateWindow("SDL2 Sprite Sheets",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640,
480, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface * image = IMG_Load("spritesheet.png");
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
image);
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return 0;
}