Search code examples
c++openglsdlglew

Segfault when calling glGenFramebuffers()?


I wanted to do some 2D on top of 3D so I could do a decent GUI. So I created the textures and so on.

I can compile the code, it generates no errors. But when I run the program all goes right until I call this:

glGenFramebuffers(1, &fb);

Then this appears:

error 139 segmentation fault (core dumped).

Does someone know what's wrong with the code?

std::cout << "test1" << std::endl;

unsigned int fb;
glGenFramebuffers(1, &fb);
std::cout << "test2" << std::endl;
glBindRenderbuffer(GL_RENDERBUFFER, fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture.getId(), 0);

The "test1" text is displayed, but the "test2" is not.

CODE:

game.cpp

#include "game.h"

game::game(){
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Surface* screen = SDL_SetVideoMode(1000, 600, 32, SDL_SWSURFACE|SDL_OPENGL);

    glClearColor(0.5, 0.5, 0.5, 1.0);
    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();
    gluPerspective(45, 1000.0/600.0, 1.0, 500.0);
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
}

game::~game(){
    SDL_Quit();
}

void game::start(){
    Uint32 start;
    SDL_Event event;

    texture renderTexture = texture();
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1000, 600, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);

    std::cerr << "test1" << std::endl;

    unsigned int fb;
    glGenFramebuffers(1, &fb);
    std::cerr << "test2" << std::endl;
    glBindRenderbuffer(GL_RENDERBUFFER, fb);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture.getId(), 0);

    bool running = true;
    while (running){
        start = SDL_GetTicks();

        while (SDL_PollEvent(&event)){
            switch (event.type){
                case SDL_QUIT:
                    running = false;
                    break;
            }
        }

        update();
        show(fb);
        showMenu();

        SDL_GL_SwapBuffers();
        if (1000/30 > (SDL_GetTicks()-start)){
            SDL_Delay(1000/30 - (SDL_GetTicks()-start));
        }
    }
}

void game::update(){

}

void game::show(unsigned int fb){

    glBindFramebuffer(GL_FRAMEBUFFER, fb);

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
}

void game::showMenu(){
    bindWindowAsRenderTarget();

    glViewport(0, 0, 1000, 600);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, 1000.0, 0.0, 600.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void game::bindWindowAsRenderTarget(){
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glViewport(0, 0, 1000, 600);
}

game.h

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

#include <iostream>

#include <SDL/SDL.h>

#include <GL/glew.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include "texture.h"

class game{
    void update();
    void show(unsigned int fb);
    void showMenu();

    void bindWindowAsRenderTarget();

    public:
        game();
        ~game();

        void start();
};

#endif // GAME_H_INCLUDED

main.cpp

#include "game.h"

int main(int argc, char** argv){
    game g;
    g.start();

    return 0;
}

texture.cpp

#ifndef TEXTURE_H_INCLUDED
#define TEXTURE_H_INCLUDED

#include <SDL/SDL.h>

#include <GL/glew.h>

#include <GL/gl.h>
#include <GL/glu.h>

class texture{
    unsigned int id;

    public:
        texture();
        ~texture();

        void loadImage(const char* filename);
        unsigned int getId();
};

#endif // TEXTURE_H_INCLUDED

texture.cpp

#include "texture.h"

texture::texture(){
    glGenTextures(1, &id);
    glBindTexture(GL_TEXTURE_2D, id);
}

texture::~texture(){
    glDeleteTextures(1, &id);
}

void texture::loadImage(const char* filename){
    SDL_Surface* img = SDL_LoadBMP(filename);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->w, img->h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, img->pixels);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    SDL_FreeSurface(img);
}

unsigned int texture::getId(){
    return id;
}

Solution

  • Dollars to donuts you're #includeing a GL extension loader (GLEW, GLAD, etc.) and then:

    1. Trying to init it before you have a current GL context (leaving function pointers like glGenFramebuffers() NULL), or
    2. Forgetting to init it entirely, or
    3. (Unlikely, unless you're doing something silly like trying to use OpenGL via remote desktop) correctly initing your extension loader but using a GL implementation that doesn't support core FBOs

    EDIT Oh hey it's #2.

    You need to call glewInit() after SDL_SetVideoMode(). You should also use the GLEW version checking functions to verify that the version of the underlying GL implementation supports core FBOs (they went in in OpenGL 2.1 IIRC).