#include #include #include #include "SDL.h" #include "SDL_opengl.h" #include "SDL_image.h" #include #include "glpong.h" #include "text.h" #include "fps.h" static int GLPong_Init(GLPong_t * GLPong); static void GLPong_Deinit(GLPong_t * GLPong); static int GLPong_HandleEvents(void); static INLINE unsigned int NextPow2(unsigned int value); static GLuint SDL_GL_SurfaceToTexture(SDL_Surface * surface); static GLuint SDL_GL_NPOTSurfaceToTexture(SDL_Surface * surface, GLfloat * wratio, GLfloat * hratio); int main(int argc, char * argv[]) { GLPong_t GLPong = { NULL, NULL, GLPONG_WIDTH, GLPONG_HEIGHT }; unsigned int frames = 0; int action; int done = 0; if (argc) { if (argv) {} } if (GLPong_Init(&GLPong) < 0) { fprintf(stderr, "Bailing out.\n"); return -1; } #ifdef DEBUG printf("%d balls\n", length(GLPong.balls)); #endif GLPong_BallAdd(&GLPong.balls); /* start with one ball */ #ifdef DEBUG printf("%d balls\n", length(GLPong.balls)); #endif GLPong_FPSInit(); while ( !done ) { action = GLPong_HandleEvents(); switch (action) { case GLPONG_EXIT: /* exit */ done = 1; break; case GLPONG_ADDBALL: /* add another ball */ GLPong_BallAdd(&GLPong.balls); break; case GLPONG_DELETEBALL: /* GLPong_BallDelete(GLPong.balls, GLPong.balls);*/ break; } GLPong_BallMoveAll(&GLPong.balls); /* begin drawing */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLPong_BallDrawAll(GLPong.balls); frames++; if (frames == 30) { frames = 0; } GLPong_TextDrawFPS(GLPong_FPSCount()); SDL_GL_SwapBuffers(); /* end drawing */ SDL_Delay(10); } /* clean up */ GLPong_Deinit(&GLPong); return 0; } static int GLPong_Init(GLPong_t * GLPong) { SDL_Surface * temp = NULL; srand(time(NULL)); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); return -1; } atexit(SDL_Quit); SDL_WM_SetCaption("glPong", "glPong"); SDL_ShowCursor(SDL_DISABLE); temp = IMG_Load("ball.png"); if (!temp) { fprintf(stderr, "Unable to open ball.png\n"); return -1; } SDL_WM_SetIcon(temp, NULL); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); GLPong->Surface = SDL_SetVideoMode(GLPong->w, GLPong->h, 32, SDL_OPENGL); if (!GLPong->Surface) { fprintf(stderr, "Cannot SetVideoMode: %s\n", SDL_GetError()); return -1; } if (GLPong_TextInit() == -1) { fprintf(stderr, "Cannot initialize GLC context: %d\n", glcGetError()); return -1; } glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, GLPong->w, 0.0f, GLPong->h, 0.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); printf("OpenGL Vendor: %s\n", (const char *)glGetString(GL_VENDOR)); printf("OpenGL Renderer: %s\n", (const char *)glGetString(GL_RENDERER)); printf("OpenGL Version: %s\n", (const char *)glGetString(GL_VERSION)); printf("OpenGL Extensions: %s\n", (const char *)glGetString(GL_EXTENSIONS)); ball_texture = SDL_GL_NPOTSurfaceToTexture(temp, NULL, NULL); SDL_FreeSurface(temp); GLPong_BallInit(); return 0; } static void GLPong_Deinit(GLPong_t * GLPong) { GLPong_BallDeleteAll(GLPong->balls); GLPong_BallDeinit(); GLPong_TextDeinit(); } static int GLPong_HandleEvents(void) { SDL_Event Event; if (SDL_PollEvent(&Event) != 0) { if (Event.type == SDL_QUIT) { return GLPONG_EXIT; } if (Event.type == SDL_KEYDOWN) { if (Event.key.keysym.sym == SDLK_d) { return GLPONG_DELETEBALL; } else if (Event.key.keysym.sym == SDLK_ESCAPE) { return GLPONG_EXIT; } else if (Event.key.keysym.sym == SDLK_SPACE) { return GLPONG_ADDBALL; } else if (Event.key.keysym.sym == SDLK_p) { for (;;) { SDL_Delay(10); if (SDL_PollEvent(&Event) != 0) { if (Event.type == SDL_QUIT) { return GLPONG_EXIT; } else if (Event.type == SDL_KEYDOWN){ if (Event.key.keysym.sym == SDLK_ESCAPE) { return GLPONG_EXIT; } else if (Event.key.keysym.sym == SDLK_p) { break; } } } } } } } return GLPONG_NOACTION; } static INLINE unsigned int NextPow2(unsigned int value) { #if (defined __i386__ || defined __x86_64__) \ && (defined __GNUC__) unsigned int x; __asm( "dec %1 \n\t" /* so that if the number is a power of * two we don't change it */ "movl $2,%0 \n\t" "bsr %1,%1 \n\t" "shl %b1,%0 \n\t" : "=r" (x) : "c" (value) ); #else unsigned int x = 2; while (x < value) { x *= 2; } #endif return x; } static GLuint SDL_GL_SurfaceToTexture(SDL_Surface * surface) { GLuint texture; SDL_Surface * temp = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, 32, BMASK, GMASK, RMASK, AMASK ); SDL_Surface * tempalpha = SDL_DisplayFormatAlpha(surface); SDL_SetAlpha(tempalpha, 0, SDL_ALPHA_TRANSPARENT); SDL_BlitSurface(tempalpha, NULL, temp, NULL); SDL_FreeSurface(tempalpha); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); SDL_LockSurface(temp); glTexImage2D(GL_TEXTURE_2D, 0, 4, temp->w, temp->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp->pixels); SDL_UnlockSurface(temp); SDL_FreeSurface(temp); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); return texture; } static GLuint SDL_GL_NPOTSurfaceToTexture(SDL_Surface * surface, GLfloat * wratio, GLfloat * hratio) { SDL_Surface * pow2 = NULL; int w = NextPow2(surface->w); int h = NextPow2(surface->h); if (wratio) { *wratio = (GLfloat)surface->w / (GLfloat)h; } if (hratio) { *hratio = (GLfloat)surface->h/(GLfloat)h; } if ((w != surface->w) || (h != surface->h)) { pow2 = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask); SDL_BlitSurface(surface, NULL, pow2, NULL); return SDL_GL_SurfaceToTexture(pow2); } else { return SDL_GL_SurfaceToTexture(surface); } }