glGenTextures() dies from EXC_BAD_ACCES? O.o

Moderator
Posts: 373
Joined: 2006.08
Post: #1
Hey everyone...sorry to ask a question that's probably going to have a really obvious answer, but I haven't been able to solve this problem in the last couple of days, so, here goes:
I have some code that I'm porting from Windows to Mac OS X, and my texture class is having problems...especially the glGenTextures() function. On windows, I have a variable called m_uiTexID that is of type 'unsigned int'. I then call glGenTextures(1, &m_uiTexID), which works fine. When I try to compile the exact same code on the mac, it wont compile, because glGenTextures() is supposed to take a GLuint* as the second argument; I changed my m_uiTexID variable to type GLuint, but then my program dies half-way through loading the first texture and returns a EXC_BAD_ACCESS. The debugger says that it is the glGenTextures() code. I've also tried casting the unsigned int into a GLuint, but I had the same problem (although it did compile, at least).
So, here's the code:
First the texture.hpp:
Code:
#ifndef TEXTURE_HPP
#define TEXTURE_HPP

#include <fstream>   // The include file for file input/output.
#include <stdio.h>
#if defined(__APPLE_CC__)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#import <windows.h>        // Header File For Windows
#import <gl\gl.h>            // Header File For The OpenGL32 Library
#import <gl\glu.h>            // Header File For The GLu32 Library
#endif

#include <png.h>

#define PNG_HEADER_SIZE 8

#if defined(__APPLE_CC__)
class texture
#else
class __declspec(dllexport) texture
#endif
{
private:

    //unsigned int m_uiTexID;
    GLuint m_uiTexID;

public:

    texture();
    
    int imageWidth;
    int imageHeight;

    void loadPNG(const char* fileName);
    GLuint GetID();
};

#endif

and then the texture.cpp:
Code:
#include "texture.hpp"

    texture::texture()
    {
    imageWidth = 0;
    imageHeight = 0;
    }

void texture::loadPNG(const char* fileName)
{
    
void *data;

    //#if defined(__APPLE_CC__)
    //#else
FILE *PNG_file = fopen(fileName, "rb");
    if (PNG_file == NULL)
    {
        fprintf(stderr, "Can't open PNG file %s\n", fileName);
    }
    
    GLubyte PNG_header[PNG_HEADER_SIZE];
    
    fread(PNG_header, 1, PNG_HEADER_SIZE, PNG_file);
    if (png_sig_cmp(PNG_header, 0, PNG_HEADER_SIZE) != 0)
    {
        fprintf(stderr, "%s is not a PNG file\n", fileName);
    }
    
    png_structp PNG_reader
        = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (PNG_reader == NULL)
    {
        fprintf(stderr, "Can't start reading PNG file %s\n", fileName);
        fclose(PNG_file);
    }

    png_infop PNG_info = png_create_info_struct(PNG_reader);
    if (PNG_info == NULL)
    {
        fprintf(stderr, "Can't get info for PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, NULL, NULL);
        fclose(PNG_file);
    }

    png_infop PNG_end_info = png_create_info_struct(PNG_reader);
    if (PNG_end_info == NULL)
    {
        fprintf(stderr, "Can't get end info for PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
        fclose(PNG_file);
    }
    
    if (setjmp(png_jmpbuf(PNG_reader)))
    {
        fprintf(stderr, "Can't load PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
        fclose(PNG_file);
    }
    
    png_init_io(PNG_reader, PNG_file);
    png_set_sig_bytes(PNG_reader, PNG_HEADER_SIZE);
    
    png_read_info(PNG_reader, PNG_info);
    
    png_uint_32 width, height;
    width = png_get_image_width(PNG_reader, PNG_info);
    height = png_get_image_height(PNG_reader, PNG_info);
    
    png_uint_32 bit_depth, color_type;
    bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
    color_type = png_get_color_type(PNG_reader, PNG_info);
    
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
    //png_set_palette_to_rgb(PNG_reader);
    png_set_palette_to_rgb(PNG_reader);
    }
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    {
    png_set_gray_1_2_4_to_8(PNG_reader);
    }
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
    png_set_gray_to_rgb(PNG_reader);
    }
    if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
    {
    png_set_tRNS_to_alpha(PNG_reader);
    }
    else
    {
    png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
    }
    if (bit_depth == 16)
    {
        png_set_strip_16(PNG_reader);
    }
    
    png_read_update_info(PNG_reader, PNG_info);
    
    png_byte* PNG_image_buffer = (png_byte*)malloc(4 * width * height);
    png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
    
    unsigned int row;
    for (row = 0; row < height; ++row)
    {
        PNG_rows[height - 1 - row] = PNG_image_buffer + (row * 4 * width);
    }
    
    png_read_image(PNG_reader, PNG_rows);
    
    free(PNG_rows);
    
    png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
    fclose(PNG_file);
    
    imageWidth = width;
    imageHeight = height;
    data = PNG_image_buffer;
    
    
// Generate one texture and let m_uiTexID be our handle to it
    //glGenTextures(1, &m_uiTexID);
    glGenTextures(1, &m_uiTexID);
  
    // Here we set up the filtering.
    glBindTexture(GL_TEXTURE_2D, m_uiTexID);
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    // and here we feed our width, height and pixels to OpenGL
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
//#endif
}


// This will give you the texture's ID
GLuint texture::GetID()
{
return m_uiTexID;
}

If anyone could tell me how to fix this problem, that would be great Smile
Also: why is it that my function GetID() that's supposed to return a GLuint works fine if I have m_uiTexID set as an unsigned int, but glGenTextures doesn't?
Thanks ^_^
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #2
I think the most likely cause would be if you're calling your loadPNG method before you load your OpenGL context. If that's the case, OpenGL will cause your program to crash if you call any OpenGL function. The fix is simple: put your calls to loadPNG after you create the context. (or, if you're using multiple threads, you need to have it in the same thread as you have the OpenGL context)
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #3
ah, thank you! that was the problem, and easily fixed, too Smile (although now it's not displaying any of my textures...)
If you are making textures, annd initializing your window using GLUT, where do you enable BLENDING?
Thanks for the help Smile
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #4
You generally have a setup function that you call between initializing the OpenGL context and you begin your rendering loop where you initialize all of you settings, including blending.
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #5
I *sort of* did that, but I must've placed the call in the wrong place because it's still not working ;(
Here's the code below:
Code:
#include <stdlib.h>

#include <GLUT/glut.h>
#include "dll.hpp"
#include "CoreServices/CoreServices.h"

clientDLL* theGame;
AbsoluteTime theTime;
AbsoluteTime previousTime;
int  numOfFrames;
int elapsedTime;

using namespace std;

void display(void)
{
previousTime = UpTime();
elapsedTime = elapsedTime + (AbsoluteToDuration(previousTime) - AbsoluteToDuration(theTime));
//cout << "elapsedTime: " << elapsedTime << "\n";
if(elapsedTime >= 1000)
{
cout << "FPS: " << numOfFrames << "\n";
numOfFrames = 0;
elapsedTime = 0;
}

theTime = UpTime();
numOfFrames = numOfFrames + 1;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
    glLoadIdentity();                    // Reset The View
    glTranslatef(0.0f,0.0f,-6.0f);
    
    theGame->draw();
        
    glutSwapBuffers();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
}

void idle(void)
{
    glutPostRedisplay();
}

void initialize()
{
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);        // Turn Blending On
}

int main(int argc, char** argv)
{
numOfFrames = 0;
elapsedTime = 0;
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
    
    glutCreateWindow("MMORPG");
    
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    
    initialize();
    
    theGame = new clientDLL;
    
    glutMainLoop();
    return EXIT_SUCCESS;
}
Thanks for the help,
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
It looks like it's in the right place. You may want to check and make sure that you're handling the texturing correctly.

BTW, just a little advice: if you're only to the point of trying to get texturing working, you may want to change your title from "MMORPG" to something more like "Pong". Wink
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #7
good point LOL I already did make pong, though, just not on the Mac Rasp This game has multiplayer capabilities, and a program that I built to run on a server to handle it, though, so it's at least going to be muliplayer (I hope) XD
-wyrmmage

Oh, and texturing works fine on Windows Sad

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #8
You might want to show more code, such as where you draw the texture.

BTW, I noticed that in all of your error handling cases when loading the PNG, you don't return from the function. (which basically means you'll catch an error, close the file and free the memory, then continue as if nothing happened)
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #9
looks like GLUT doesn't provide default matrix modes of perspective calculations >.< Copying and pasting this section of code from my Windows program did the trick... Smile
Code:
glViewport(0,0,width,height);                        // Reset The Current Viewport
    
    windowMaxX = width;
    windowMaxY = height;

    glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
    glLoadIdentity();                                    // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);                            // Select The Modelview Matrix
    glLoadIdentity();                                    // Reset The Modelview Matrix

Thanks for the help, man; you solved two or three of my problems ^_^
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Pointer Warning in glGenTextures Pixelated 1 2,622 Apr 6, 2008 01:28 PM
Last Post: OneSadCookie
  glGenTextures question Jake 5 3,895 Sep 1, 2003 08:27 AM
Last Post: Jake
  glGenTextures and EXC_BAD_ACCESS BobbyWatson 1 4,833 Aug 31, 2002 01:48 PM
Last Post: BobbyWatson
  death by glGenTextures(), with TGA sealfin 7 4,489 Jul 18, 2002 07:02 AM
Last Post: sealfin