Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Fullscreen when using OpenGL  (Read 5401 times)

0 Members and 1 Guest are viewing this topic.

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Fullscreen when using OpenGL
« on: November 01, 2015, 07:51:02 am »
Hello all,

I recently started learning OpenGL and I'm having a problem when I want to toggle fullscreen on my sf::Window. I'm following the tutorials from open.gl and everything has been going smoothly but today I ran into this issue and haven't been able to solve it.

Here is the offending code:
#define GLEW_STATIC

#include <iostream>
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#include "Render/RenderUtils.h"
#include "Log.h"


using namespace moony;

int main()
{
    sf::VideoMode videoMode = sf::VideoMode(800, 600, 24);
    sf::ContextSettings contextSettings = sf::ContextSettings(24, 8, 2);
    sf::Window window(videoMode, "SFML OpenGL", sf::Style::Close, contextSettings);

    sf::Clock clock;

    bool isRunning = true;
    bool isFullscreen = false;

    // Initialize GLEW
    glewExperimental = GL_TRUE;
    glewInit();

    // Create the VertexArrayObject
    GLuint vertexArrayObject;
    glGenVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);

    // Create the VertexBufferObject
    GLuint vertexBufferObject;
    glGenBuffers(1, &vertexBufferObject);

    // Define a Polygon pos3 col3 tex2
    float vertices[] =
            {
                    -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-Left
                    0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-Right
                    0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-Right
                    -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-Left
            };

    // Bind VertexBufferObject and send Polygon data
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    GLuint elementBufferObject;
    glGenBuffers(1, &elementBufferObject);

    GLuint elements[] =
            {
                    0, 1, 2,
                    2, 3, 0
            };

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

    GLuint shaderProgram = loadShaderProgram("./shaders/shader.vert", "./shaders/shader.frag");

    if(!shaderProgram)
        return -1;

    GLint attribPosition = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(attribPosition);
    glVertexAttribPointer(attribPosition, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);

    GLint attribColor = glGetAttribLocation(shaderProgram, "color");
    glEnableVertexAttribArray(attribColor);
    glVertexAttribPointer(attribColor, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));

    GLint attribTexcoord = glGetAttribLocation(shaderProgram, "texcoord");
    glEnableVertexAttribArray(attribTexcoord);
    glVertexAttribPointer(attribTexcoord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));

    GLint uniformTime = glGetUniformLocation(shaderProgram, "time");

    GLuint textureObjects;
    glGenTextures(1, &textureObjects);
    glBindTexture(GL_TEXTURE_2D, textureObjects);

    sf::Image image_a;

    if(!image_a.loadFromFile("./textures/sample.png"))
        return -1;

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_a.getSize().x, image_a.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_a.getPixelsPtr());

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glUniform1i(glGetUniformLocation(shaderProgram, "texture_a"), 0);

    while(isRunning)
    {
        sf::Event event;

        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed : isRunning = false; break;
                default: break;
            }
        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::F))
        {
            isFullscreen = !isFullscreen;

            if(isFullscreen)
                window.create(sf::VideoMode::getFullscreenModes()[0], "", sf::Style::Fullscreen, contextSettings);
            else
                window.create(videoMode, "SFML OpenGL", sf::Style::Close, contextSettings);
        }

        window.setActive(true);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUniform1f(uniformTime, clock.getElapsedTime().asSeconds());

        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // Comment this and all goes well.

        window.display();
    }

    glDeleteProgram(shaderProgram);
    glDeleteBuffers(1, &elementBufferObject);
    glDeleteBuffers(1, &vertexBufferObject);
    glDeleteVertexArrays(1, &vertexArrayObject);

    window.close();

    return 0;
}

The commented line is the problem. When I run it and get to glDrawElements(...); I get a SIGSEGV but when I comment it out no problems toggling fullscreen. I'm new to OpenGL so if I've missed something obvious be patient with me. Thanks in advance.
« Last Edit: November 01, 2015, 08:24:21 am by Ricky »
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Fullscreen when using OpenGL
« Reply #1 on: November 01, 2015, 08:08:19 am »
Someone correct me if I am wrong, but when you recreate the window the context is destroyed/recreated and all your own GL objects are invalidated.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Re: Fullscreen when using OpenGL
« Reply #2 on: November 01, 2015, 08:22:58 am »
Someone correct me if I am wrong, but when you recreate the window the context is destroyed/recreated and all your own GL objects are invalidated.

I believe you are right. This code works because I basically put the GPU in the state it was after recreating the window.

#define GLEW_STATIC

#include <iostream>
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#include "Render/RenderUtils.h"
#include "Log.h"


using namespace moony;


void remakeContext()
{
    // Create the VertexArrayObject
    GLuint vertexArrayObject;
    glGenVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);

    // Create the VertexBufferObject
    GLuint vertexBufferObject;
    glGenBuffers(1, &vertexBufferObject);

    // Define a Polygon pos3 col3 tex2
    float vertices[] =
            {
                    -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-Left
                    0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-Right
                    0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-Right
                    -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-Left
            };

    // Bind VertexBufferObject and send Polygon data
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    GLuint elementBufferObject;
    glGenBuffers(1, &elementBufferObject);

    GLuint elements[] =
            {
                    0, 1, 2,
                    2, 3, 0
            };

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

    GLuint shaderProgram = loadShaderProgram("./shaders/shader.vert", "./shaders/shader.frag");

    if(!shaderProgram)
        return;

    GLint attribPosition = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(attribPosition);
    glVertexAttribPointer(attribPosition, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);

    GLint attribColor = glGetAttribLocation(shaderProgram, "color");
    glEnableVertexAttribArray(attribColor);
    glVertexAttribPointer(attribColor, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));

    GLint attribTexcoord = glGetAttribLocation(shaderProgram, "texcoord");
    glEnableVertexAttribArray(attribTexcoord);
    glVertexAttribPointer(attribTexcoord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));

    GLint uniformTime = glGetUniformLocation(shaderProgram, "time");

    GLuint textureObjects;
    glGenTextures(1, &textureObjects);
    glBindTexture(GL_TEXTURE_2D, textureObjects);

    sf::Image image_a;

    if(!image_a.loadFromFile("./textures/sample.png"))
        return;

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_a.getSize().x, image_a.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_a.getPixelsPtr());

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glUniform1i(glGetUniformLocation(shaderProgram, "texture_a"), 0);
}

int main()
{
    sf::VideoMode videoMode = sf::VideoMode(800, 600, 24);
    sf::ContextSettings contextSettings = sf::ContextSettings(24, 8, 2);
    sf::Window window(videoMode, "SFML OpenGL", sf::Style::Close, contextSettings);

    sf::Clock clock;

    bool isRunning = true;
    bool isFullscreen = false;

    // Initialize GLEW
    glewExperimental = GL_TRUE;
    glewInit();

    // Create the VertexArrayObject
    GLuint vertexArrayObject;
    glGenVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);

    // Create the VertexBufferObject
    GLuint vertexBufferObject;
    glGenBuffers(1, &vertexBufferObject);

    // Define a Polygon pos3 col3 tex2
    float vertices[] =
            {
                    -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-Left
                    0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-Right
                    0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-Right
                    -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-Left
            };

    // Bind VertexBufferObject and send Polygon data
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    GLuint elementBufferObject;
    glGenBuffers(1, &elementBufferObject);

    GLuint elements[] =
            {
                    0, 1, 2,
                    2, 3, 0
            };

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

    GLuint shaderProgram = loadShaderProgram("./shaders/shader.vert", "./shaders/shader.frag");

    if(!shaderProgram)
        return -1;

    GLint attribPosition = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(attribPosition);
    glVertexAttribPointer(attribPosition, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);

    GLint attribColor = glGetAttribLocation(shaderProgram, "color");
    glEnableVertexAttribArray(attribColor);
    glVertexAttribPointer(attribColor, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));

    GLint attribTexcoord = glGetAttribLocation(shaderProgram, "texcoord");
    glEnableVertexAttribArray(attribTexcoord);
    glVertexAttribPointer(attribTexcoord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));

    GLint uniformTime = glGetUniformLocation(shaderProgram, "time");

    GLuint textureObjects;
    glGenTextures(1, &textureObjects);
    glBindTexture(GL_TEXTURE_2D, textureObjects);

    sf::Image image_a;

    if(!image_a.loadFromFile("./textures/sample.png"))
        return -1;

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_a.getSize().x, image_a.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_a.getPixelsPtr());

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glUniform1i(glGetUniformLocation(shaderProgram, "texture_a"), 0);

    while(isRunning)
    {
        sf::Event event;

        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed : isRunning = false; break;
                default: break;
            }
        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::F))
        {
            isFullscreen = !isFullscreen;

            if(isFullscreen)
                window.create(sf::VideoMode::getFullscreenModes()[0], "", sf::Style::Fullscreen, contextSettings);
            else
                window.create(videoMode, "SFML OpenGL", sf::Style::Close, contextSettings);

            remakeContext();
        }

        window.setActive(true);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUniform1f(uniformTime, clock.getElapsedTime().asSeconds());

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // Comment this and all goes well.

        window.display();
    }

    glDeleteProgram(shaderProgram);
    glDeleteBuffers(1, &elementBufferObject);
    glDeleteBuffers(1, &vertexBufferObject);
    glDeleteVertexArrays(1, &vertexArrayObject);

    window.close();

    return 0;
}


No more crashing and everything works. I'm sure there is some memory leak problem in here and I really wish this wasn't the solution. It has to be more intuitive than this. Again, OpenGL noob so I'm probably very wrong.
« Last Edit: November 01, 2015, 08:25:25 am by Ricky »
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Fullscreen when using OpenGL
« Reply #3 on: November 01, 2015, 11:14:29 am »
SFML internally creates hidden OpenGL contexts, and all of them share their resources. This means that even if you recreate your window, the resources are not lost. The only exception being OpenGL objects that cannot be shared among contexts: VAO. So technically you would only have to recreate your VAO to avoid the problem.
Laurent Gomila - SFML developer

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: Fullscreen when using OpenGL
« Reply #4 on: November 01, 2015, 01:35:28 pm »
SFML internally creates hidden OpenGL contexts, and all of them share their resources. This means that even if you recreate your window, the resources are not lost. The only exception being OpenGL objects that cannot be shared among contexts: VAO. So technically you would only have to recreate your VAO to avoid the problem.

Very interesting comment. What is VAO? Vertex arrays?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Fullscreen when using OpenGL
« Reply #5 on: November 01, 2015, 02:08:29 pm »
Vertex Array Object (not the same as sf::VertexArray)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Re: Fullscreen when using OpenGL
« Reply #6 on: November 05, 2015, 04:36:08 am »
Okay so I solved the crashing, confirmed on some Windows 7 and XP virtual machines and actual hardware. I cut out VAOs all together because I want to target OpenGL 2.1 hardware and the 2.1 spec has all the features I need for this game I want to make. Now I have another issue and that is that on a physical Windows XP install, nothing gets drawn when in fullscreen mode, I just get a black screen. When switching out back into windowed mode drawing resumes as expected. Here is a small code sample that reproduces the issue for me.

#define SFML_STATIC

#include <iostream>
#include <glad/glad.h>
#include <SFML/Window.hpp>


int main(void)
{
    sf::VideoMode videoModeWindowed(640, 480);
    sf::VideoMode videoModeFullscreen = sf::VideoMode::getFullscreenModes()[0];

    sf::ContextSettings contextSettings(24, 8, 0, 2, 1);

    sf::Window window(videoModeFullscreen, "SFML OpenGL", sf::Style::Fullscreen, contextSettings);

    if(!gladLoadGL())
        return -1;

    GLfloat clearColor[] = {1.0f, 1.0f, 0.0f, 1.0f};

    bool running = true;
    bool fullscreen = true;
    int delay = 0;

    while(running)
    {
        sf::Event event;

        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed: running = false; break;
                default: break;
            }
        }

        // update
        if(window.hasFocus())
        {
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                running = false;
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::F) && !delay)
            {
                fullscreen = !fullscreen;

                if(fullscreen)
                    window.create(videoModeFullscreen, "SFML OpenGL", sf::Style::Fullscreen, contextSettings);
                else
                    window.create(videoModeWindowed, "SFML OpenGL", sf::Style::Close, contextSettings);

                delay = 500;
            }

            if(delay)
                delay--;
        }

        if(fullscreen)
        {
            clearColor[1] = 0.0f;
            clearColor[2] = 1.0f;
        }
        else
        {
            clearColor[1] = 1.0f;
            clearColor[2] = 0.0f;
        }

        // render

        glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


        window.display();
    }

    window.close();

    return 0;
}


I tested on Windows 8 hardware and on multiple Windows 7 hardware (not my PC) and no problems at all. When you are in windowed mode you should see a yellow screen and when in fullscreen mode you should see a magenta screen.

Here are the specs of the XP machine that is not complying:
Windows XP Home 32 bit
CPU AMD Sempron 140
GPU Nvidia GeForce 6150SE nForce 430 with latest driver (307.83)
Monitor resolution 1360x768
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Re: Fullscreen when using OpenGL
« Reply #7 on: November 10, 2015, 07:42:13 am »
I fixed it. There was actually a problem with the Windows XP installation and when I reinstalled Windows XP it worked. Cheers!  ;D
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.