From 01057be7522006cd7ff56762f74d3a21e997879d Mon Sep 17 00:00:00 2001 From: Matt Thompson Date: Fri, 16 Jan 2009 13:46:49 -0600 Subject: [PATCH] More texture fixes, including a flag to build power of 2 textures --- src/backend/texture.c | 103 ++++++++++++++++++++++++++++++++++++++------------ src/backend/texture.h | 29 ++++++++------ src/main.cpp | 8 +++- src/ui/common.cpp | 1 - src/ui/menu.cpp | 58 +++++++++++++++++----------- 5 files changed, 139 insertions(+), 60 deletions(-) diff --git a/src/backend/texture.c b/src/backend/texture.c index a8612cc..1459ca1 100644 --- a/src/backend/texture.c +++ b/src/backend/texture.c @@ -25,6 +25,20 @@ #include #include +/* Undefine the following if you're targeting + * hardware that supports non-power-of-2 textures. + * You'll save some video memory... + */ +//#define NONPOW2 + +#define FAIL_ON_GLMEM \ +{ \ + if (glGetError() == GL_OUT_OF_MEMORY) { \ + fprintf(stderr, "Out of memory!"); \ + exit(1); \ + } \ +} + void t_init() { static int init = 0; @@ -66,17 +80,24 @@ static int nearest_pow2(int s) return v; } -SDL_Surface *flip_surf(SDL_Surface *surf) +static SDL_Surface *flip_fit_surf(SDL_Surface *surf) { +#ifdef NONPOW2 + int w = surf->w; + int h = surf->h; +#else int w = nearest_pow2(surf->w); int h = nearest_pow2(surf->h); +#endif - // TODO: change all our code to work with pow2 - w = surf->w; - h = surf->h; +#ifdef DEBUG + if (w != surf->w || h != surf->h) { + printf("DEBUG: resizing surface from %dx%d to %dx%d for GL\n", + surf->w, surf->h, w, h); + } +#endif - SDL_Surface *n = SDL_CreateRGBSurface(SDL_SWSURFACE, - surf->w, surf->h, 32, + SDL_Surface *n = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000FF, 0x0000FF00, @@ -96,7 +117,7 @@ SDL_Surface *flip_surf(SDL_Surface *surf) Uint8 alpha = surf->format->alpha; // turn off alpha for the blit - if ((flags&SDL_SRCALPHA) == SDL_SRCALPHA) + if (flags&SDL_SRCALPHA) SDL_SetAlpha(surf, 0, 0); SDL_Rect src, dest; @@ -108,7 +129,7 @@ SDL_Surface *flip_surf(SDL_Surface *surf) SDL_BlitSurface(surf, &src, n, &dest); // turn alpha back on if we turned it off - if ((flags&SDL_SRCALPHA) == SDL_SRCALPHA) + if (flags&SDL_SRCALPHA) SDL_SetAlpha(surf, flags, alpha); // now, flip the image @@ -139,21 +160,17 @@ void t_load(struct texture *t, const char *filename) SDL_Surface *img = IMG_Load(filename); - if (!img) - { + if (!img) { fprintf(stderr, "Texture load error: %s\n", IMG_GetError()); return; } - if (img->format->BytesPerPixel < 2) - { + if (img->format->BytesPerPixel < 2) { fprintf(stderr, "Texture load error: %s is not true color\n", filename); return; } - SDL_Surface *tmp = flip_surf(img); - SDL_FreeSurface(img); - img = tmp; + SDL_Surface *tmp = flip_fit_surf(img); glGenTextures(1, &t->gl_handle); glBindTexture(GL_TEXTURE_2D, t->gl_handle); @@ -161,7 +178,11 @@ void t_load(struct texture *t, const char *filename) t->width = img->w; t->height = img->h; - t->u = t->v = 1.0; // TODO: change this when textures are scaled to pow2 + t->u = (float)img->w / tmp->w; + t->v = (float)img->h / tmp->h; + + SDL_FreeSurface(img); + img = tmp; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -174,13 +195,11 @@ void t_load(struct texture *t, const char *filename) int mipmap = 0; - if (!mipmap) - { + if (!mipmap) { glTexImage2D(GL_TEXTURE_2D, 0, img->format->BytesPerPixel, img->w, img->h, 0, mode, GL_UNSIGNED_BYTE, img->pixels); } - else - { + else { glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); gluBuild2DMipmaps(GL_TEXTURE_2D, img->format->BytesPerPixel, img->w, img->h, mode, GL_UNSIGNED_BYTE, img->pixels); @@ -188,20 +207,37 @@ void t_load(struct texture *t, const char *filename) SDL_FreeSurface(img); + FAIL_ON_GLMEM + t->ready = 1; } void t_unload(struct texture *t) { - if (t_ready(t)) - { + if (t_ready(t)) { glDeleteTextures(1, &t->gl_handle); } } void t_apply(struct texture *t) { + GLint lastmode; + glGetIntegerv(GL_MATRIX_MODE, &lastmode); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(t->u, t->v, 1.0); glBindTexture(GL_TEXTURE_2D, t->gl_handle); + glMatrixMode(lastmode); +} + +void t_clear() +{ + GLint lastmode; + glGetIntegerv(GL_MATRIX_MODE, &lastmode); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glBindTexture(GL_TEXTURE_2D, 0); + glMatrixMode(lastmode); } void t_set(struct texture *t, GLuint name, GLuint value) @@ -219,13 +255,28 @@ struct texture *t_screenshot() const struct video_info* vi = v_info(); - // TODO: figure out what old cards can't render non pow2 textures... +#ifdef NONPOW2 + int w = vi->width; + int h = vi->height; +#else + int w = nearest_pow2(vi->width); + int h = nearest_pow2(vi->height); +#endif + t->width = vi->width; t->height = vi->height; - t->u = t->v = 1.0; +#ifdef DEBUG + if (w != vi->width || h != vi->height) { + printf("DEBUG: resizing surface from %dx%d to %dx%d for GL\n", + vi->width, vi->height, w, h); + } +#endif - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, t->width, t->height, 0); + t->u = (float)t->width / w; + t->v = (float)t->height / h; + + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, w, h, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -233,6 +284,8 @@ struct texture *t_screenshot() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + FAIL_ON_GLMEM + t->ready = 1; return t; diff --git a/src/backend/texture.h b/src/backend/texture.h index 6ea6e10..9c2a20f 100644 --- a/src/backend/texture.h +++ b/src/backend/texture.h @@ -47,11 +47,13 @@ void t_unload(struct texture *t); void t_apply(struct texture *t); +void t_clear(); + void t_set(struct texture *t, GLuint name, GLuint value); struct texture *t_screenshot(); -/* C++ Texture and TextureFactory */ +/* C++ Texture */ #ifdef __cplusplus } @@ -85,56 +87,61 @@ public: return t; } - int getWidth() + inline int getWidth() { return m_tex->width; } - int getHeight() + inline int getHeight() { return m_tex->height; } - float getU() + inline float getU() { return m_tex->u; } - float getV() + inline float getV() { return m_tex->v; } - GLuint getHandle() + inline GLuint getHandle() { return m_tex->gl_handle; } - bool isReady() + inline bool isReady() { return (m_tex && t_ready(m_tex)); } - void set(GLuint name, GLuint value) + inline void set(GLuint name, GLuint value) { t_set(m_tex,name,value); } - void load(const char *file, bool mipmap=true) + inline void load(const char *file, bool mipmap=true) { t_load(m_tex,file); } - void unload() + inline void unload() { t_unload(m_tex); } - void apply() + inline void apply() { t_apply(m_tex); } + inline void clear() + { + t_clear(); + } + private: struct texture *m_tex; }; diff --git a/src/main.cpp b/src/main.cpp index 586b3b5..55f19b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,7 +58,13 @@ int menu_toggle(void *data) int fullscreen_toggle(void *data) { + Menu *menu = (Menu*)data; + v_fullscreen(1); + + Vec3f old = menu->getSize(); + menu->setSize(Vec3f(v_info()->width, v_info()->height, old.z())); + return KEEPOVERLAY; } @@ -123,7 +129,7 @@ int main(int argc, char **argv) main_menu.addChild(t); t = new Toggle("Fullscreen", full); - t->setCallback(fullscreen_toggle); + t->setCallback(fullscreen_toggle, &main_menu); t->setSize(button_size); t->setColor(0.6, 1.0, 0.6); main_menu.addChild(t); diff --git a/src/ui/common.cpp b/src/ui/common.cpp index d5443f2..ed089c3 100644 --- a/src/ui/common.cpp +++ b/src/ui/common.cpp @@ -78,7 +78,6 @@ void ui_draw_rect(float x, float y) float scale = UI_CORNER_SIZE; glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_DEPTH_TEST); diff --git a/src/ui/menu.cpp b/src/ui/menu.cpp index 1f4118a..9180749 100644 --- a/src/ui/menu.cpp +++ b/src/ui/menu.cpp @@ -16,6 +16,7 @@ ************************************************************************/ #include "menu.h" +#include "resource/texturefactory.h" #include "backend/video.h" #include "backend/input.h" #include "backend/shapes.h" @@ -55,6 +56,7 @@ Menu::Menu(std::string name, Menu::MENU_MODE m) m_keyrep.setDelay(150); m_keyrep.setTime(300); setMode(m); + setSize(Vec3f(v_info()->width, v_info()->height, 9.0)); setDefaults(); } @@ -67,7 +69,6 @@ void Menu::setDefaults() { m_entry_spacing = 2.0; // units step per entry m_entry_padding = 3.0; // units of padding around the entry - m_entry_distance = -9.0; // z distance from camera m_rot_target = 0.0; m_rot_accel = 0.05; m_rot_vel = 0.0; @@ -186,10 +187,14 @@ void Menu::draw() glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + //glDisable(GL_LIGHTING); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + if (m_mode == OVERLAY || m_mode == OVERLAY_ANIMATE) { // draw snapshot glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -207,15 +212,16 @@ void Menu::draw() glLoadIdentity(); float w, h, ratio; - w = m_background->getWidth(); - h = m_background->getHeight(); + w = m_size.x(); + h = m_size.y(); ratio = w/h; - static Texture image("data/ne/ne.png"); + TextureFactory *tf = TextureFactory::Instance(); + static Texture *image = tf->load("data/ne/ne.png"); float hx, hy; - hx = image.getWidth()*0.5; - hy = image.getHeight()*0.5; + hx = image->getWidth()*0.5; + hy = image->getHeight()*0.5; static float x= w*0.5 - hx; static float y= h*0.5 - hy; @@ -225,16 +231,25 @@ void Menu::draw() x += vx; y += vy; + bool onscreen = true; + if (x + hx < -w || x - hx > w) + onscreen = false; + if (y + hy < -h || y - hy > h) + onscreen = false; + + if (!onscreen) { + x = 0.0; + y = 0.0; + } + if (x - hx < -w || x + hx > w) vx = -vx; if (y - hy < -h || y + hy > h) vy = -vy; glTranslatef(x/w, y/h, 0.0); - //glScalef(0.1, 0.1, 1.0); - //glScalef(1.0/image.getWidth(), 1.0/image.getWidth(), 1.0); glScalef(1.0/ratio, 1.0, 1.0); - image.apply(); + image->apply(); draw_quad(); } @@ -249,7 +264,6 @@ void Menu::draw() glMatrixMode(GL_MODELVIEW); glDisable(GL_TEXTURE_2D); - glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 1.0); glLoadIdentity(); @@ -257,9 +271,9 @@ void Menu::draw() glVertex2f(-1.0,-0.1); glVertex2f(-0.9, 0.0); glVertex2f(-1.0, 0.1); - glVertex2f(1.0, 0.1); - glVertex2f(0.9, 0.0); - glVertex2f(1.0,-0.1); + glVertex2f( 1.0, 0.1); + glVertex2f( 0.9, 0.0); + glVertex2f( 1.0,-0.1); glEnd(); glMatrixMode(GL_PROJECTION); @@ -268,24 +282,24 @@ void Menu::draw() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glTranslatef(0,0,-10); + glTranslatef(0.0, 0.0, -10.0); for (int i=draw_start; i!=draw_end; i++) { //float r = m_rot_curr - m_entry_spacing*i; float r = m_rot_curr - i * m_entry_spacing; glPushMatrix(); - glRotatef(r*10,1,0,0); - glTranslatef(0,0,m_entry_distance); + glRotatef(r*10,1, 0.0, 0.0); + glTranslatef(0.0, 0.0, -m_size.z()); - glColor3f(1,1,1); + glColor3f(1.0, 1.0, 1.0); glBegin(GL_QUADS); //glColor4f(1,1,1,1); - glVertex2f(0,0); - glVertex2f(0,10); + glVertex2f(0.0, 0.0); + glVertex2f(0.0, 10.0); //glColor4f(1,1,1,0); - glVertex2f(10,10); - glVertex2f(10,0); + glVertex2f(10.0, 10.0); + glVertex2f(10.0, 0.0); glEnd(); if (i >= upper_bound && i <= lower_bound) -- 2.11.4.GIT