diff options
Diffstat (limited to 'samples/quake/jni/gl_draw.cpp')
-rw-r--r-- | samples/quake/jni/gl_draw.cpp | 2127 |
1 files changed, 0 insertions, 2127 deletions
diff --git a/samples/quake/jni/gl_draw.cpp b/samples/quake/jni/gl_draw.cpp deleted file mode 100644 index 775ac77..0000000 --- a/samples/quake/jni/gl_draw.cpp +++ /dev/null @@ -1,2127 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// draw.c -- this is the only file outside the refresh that touches the -// vid buffer - -#include "quakedef.h" - -#define GL_COLOR_INDEX8_EXT 0x80E5 - - -cvar_t gl_nobind = CVAR2("gl_nobind", "0"); -cvar_t gl_max_size = CVAR2("gl_max_size", "1024"); -cvar_t gl_picmip = CVAR2("gl_picmip", "0"); - -byte *draw_chars; // 8*8 graphic characters -qpic_t *draw_disc; -qpic_t *draw_backtile; - -int translate_texture; -int char_texture; - -typedef struct -{ - int texnum; - float sl, tl, sh, th; -} glpic_t; - -typedef union -{ - qpic_t qpic; - struct { - // First part is from qpic - int width; - int height; - - glpic_t glpic; - } g; -} packedGlpic_t; - -typedef union -{ - byte buffer[sizeof(qpic_t) + sizeof(glpic_t)]; - packedGlpic_t pics; -} conback_t; - -conback_t conbackUnion; - -#define conback_buffer (conbackUnion.buffer) -packedGlpic_t *conback = &conbackUnion.pics; - -int gl_lightmap_format = 4; -int gl_solid_format = 3; -int gl_alpha_format = 4; - -#if 1 // Standard defaults -int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; -int gl_filter_max = GL_LINEAR; -#else -int gl_filter_min = GL_NEAREST_MIPMAP_NEAREST; -int gl_filter_max = GL_NEAREST; -#endif - -int texels; - -typedef struct -{ - int texnum; - char identifier[64]; - int width, height; - qboolean mipmap; -} gltexture_t; - -#define MAX_GLTEXTURES 1024 -gltexture_t gltextures[MAX_GLTEXTURES]; -int numgltextures; - -// GlQuake creates textures, but never deletes them. This approach works fine on -// computers with lots of RAM and/or swap, but not so well on our swapless -// RAM-constrained system. -// -// We work around this problem by adding a level of indirection. We -// hook GL_LoadTexture to store enough information to recreate a texture. -// Then we hook GL_BindTexture to consult a table to see whether a texture -// is currently in memory or not. If it isn't, we throw out some other -// texture and bring the required texture back into memory. In this way -// we can limit the working set of textures. -// -// The texture data is stored in a memory-mapped file that is backed by -// a file on the sd card. It is recreated each time the game is run. We -// don't bother deleting it. - -#define USE_TEXTURE_STORE - -#ifdef USE_TEXTURE_STORE - -#include <unistd.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <errno.h> -int errno_portable(); - -// Allow named textures to be evicted from memory. - -#define TEXTURE_STORE_NAME "glquake/texture.store" - -class textureStore { - -private: - static const GLuint UNUSED = (GLuint) -2; - static const GLuint PAGED_OUT = (GLuint) -1; - - struct entry - { - entry* next; - entry* prev; - GLuint real_texnum; // UNUSED, PAGED_OUT - byte* pData; // 0 ==> not created by us. - size_t size; - qboolean alpha; - int width; - int height; - qboolean mipmap; - - entry() { - next = 0; - prev = 0; - real_texnum = UNUSED; - pData = 0; - } - - - void unlink() { - if (next) { - next->prev = prev; - } - if (prev) { - prev->next = next; - } - next = 0; - prev = 0; - } - - void insertBefore(entry* e){ - if (e) { - prev = e->prev; - if ( prev ) { - prev->next = this; - } - next = e; - e->prev = this; - } - else { - prev = 0; - next = 0; - } - } - }; - -public: - - static textureStore* get() { - if (g_pTextureCache == 0) { - g_pTextureCache = new textureStore(); - } - return g_pTextureCache; - } - - // Equivalent of glBindTexture, but uses the virtual texture table - - void bind(int virtTexNum) { - if ( (unsigned int) virtTexNum >= TEXTURE_STORE_NUM_TEXTURES) { - Sys_Error("not in the range we're managing"); - } - mBoundTextureID = virtTexNum; - entry* e = &mTextures[virtTexNum]; - - if ( e->real_texnum == UNUSED) { - glGenTextures( 1, &e->real_texnum); - } - - if ( e->pData == 0) { - glBindTexture(GL_TEXTURE_2D, e->real_texnum); - return; - } - - update(e); - } - - void update(entry* e) - { - // Update the "LRU" part of the cache - unlink(e); - e->insertBefore(mFirst); - mFirst = e; - if (! mLast) { - mLast = e; - } - - if (e->real_texnum == PAGED_OUT ) { - // Create a real texture - // Make sure there is enough room for this texture - ensure(e->size); - - glGenTextures( 1, &e->real_texnum); - - glBindTexture(GL_TEXTURE_2D, e->real_texnum); - GL_Upload8 (e->pData, e->width, e->height, e->mipmap, - e->alpha); - } - else { - glBindTexture(GL_TEXTURE_2D, e->real_texnum); - } - } - - // Create a texture, and remember the data so we can create - // it again later. - - void create(int width, int height, byte* data, qboolean mipmap, - qboolean alpha) { - int size = width * height; - if (size + mLength > mCapacity) { - Sys_Error("Ran out of virtual texture space. %d", size); - }; - entry* e = &mTextures[mBoundTextureID]; - - // Call evict in case the currently bound texture id is already - // in use. (Shouldn't happen in Quake.) - // To Do: reclaim the old texture memory from the virtual memory. - - evict(e); - - e->alpha = alpha; - e->pData = mBase + mLength; - memcpy(e->pData, data, size); - e->size = size; - e->width = width; - e->height = height; - e->mipmap = mipmap; - e->real_texnum = PAGED_OUT; - mLength += size; - - update(e); - } - - // Re-upload the current textures because we've been reset. - void rebindAll() { - grabMagicTextureIds(); - for (entry* e = mFirst; e; e = e->next ) { - if (! (e->real_texnum == UNUSED || e->real_texnum == PAGED_OUT)) { - glBindTexture(GL_TEXTURE_2D, e->real_texnum); - if (e->pData) { - GL_Upload8 (e->pData, e->width, e->height, e->mipmap, - e->alpha); - } - } - } - } - -private: - - textureStore() { - grabMagicTextureIds(); - mFirst = 0; - mLast = 0; - mTextureCount = 0; - - char fullpath[MAX_OSPATH]; - sprintf(fullpath, "%s/%s", com_gamedir, TEXTURE_STORE_NAME); - - mFileId = open(fullpath, O_RDWR | O_CREAT, 0666); - if ( mFileId == -1 ) { - Sys_Error("Could not open texture store file %s: %d", fullpath, - errno_portable()); - } - - if (-1 == lseek(mFileId, TEXTURE_STORE_SIZE-1, SEEK_SET)) { - Sys_Error("Could not extend the texture store file size. %d", - errno_portable()); - } - char end; - end = 0; - if (-1 == write(mFileId, &end, 1)) { - Sys_Error("Could not write last byte of the texture store file. %d", - errno_portable()); - } - - mBase = (byte*) mmap((caddr_t)0, TEXTURE_STORE_SIZE, - PROT_READ | PROT_WRITE, MAP_PRIVATE, mFileId, 0); - - if (mBase == (byte*) -1) { - Sys_Error("Could not mmap file %s: %d", fullpath, errno_portable()); - } - mLength = 0; - mCapacity = TEXTURE_STORE_SIZE; - mRamUsed = 0; - mRamSize = LIVE_TEXTURE_LIMIT; - } - - ~textureStore() { - munmap(mBase, mCapacity); - COM_CloseFile(mFileId); - } - - void grabMagicTextureIds() { - // reserve these two texture ids. - glBindTexture(GL_TEXTURE_2D, UNUSED); - glBindTexture(GL_TEXTURE_2D, PAGED_OUT); - } - - void unlink(entry* e) { - if (e == mFirst) { - mFirst = e->next; - } - if (e == mLast) { - mLast = e->prev; - } - e->unlink(); - } - - void ensure(int size) { - while ( mRamSize - mRamUsed < (unsigned int) size) { - entry* e = mLast; - if(! e) { - Sys_Error("Ran out of entries"); - return; - } - evict(e); - } - mRamUsed += size; - } - - void evict(entry* e) { - unlink(e); - if ( e->pData ) { - glDeleteTextures(1, &e->real_texnum); - e->real_texnum = PAGED_OUT; - mRamUsed -= e->size; - } - } - - static const size_t TEXTURE_STORE_SIZE = 16 * 1024 * 1024; - static const size_t LIVE_TEXTURE_LIMIT = 1 * 1024 * 1024; - static const size_t TEXTURE_STORE_NUM_TEXTURES = 512; - - int mFileId; - byte* mBase; // Base address of the memory mapped file - size_t mLength; // How much of the mm file we are currently using - size_t mCapacity; // Total size of the memory mapped file - - // Keep track of texture RAM. - size_t mRamUsed; - size_t mRamSize; - - // The virtual textures - - - entry mTextures[MAX_GLTEXTURES]; - entry* mFirst; // LRU queue - entry* mLast; - size_t mTextureCount; // How many virtual textures have been allocated - - static textureStore* g_pTextureCache; - - int mBoundTextureID; -}; - -textureStore* textureStore::g_pTextureCache; - -#endif - - -void GL_Bind (int texnum) -{ - if (gl_nobind.value) - texnum = char_texture; - if (currenttexture == texnum) - return; - currenttexture = texnum; -#ifdef _WIN32 - bindTexFunc (GL_TEXTURE_2D, texnum); -#else - -#ifdef USE_TEXTURE_STORE - textureStore::get()->bind(texnum); -#else - glBindTexture(GL_TEXTURE_2D, texnum); -#endif - -#endif -} - - -/* -============================================================================= - - scrap allocation - - Allocate all the little status bar obejcts into a single texture - to crutch up stupid hardware / drivers - -============================================================================= -*/ - -#define MAX_SCRAPS 2 -#define BLOCK_WIDTH 256 -#define BLOCK_HEIGHT 256 - -int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; -byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4]; -qboolean scrap_dirty; -int scrap_texnum; - -// returns a texture number and the position inside it -int Scrap_AllocBlock (int w, int h, int *x, int *y) -{ - int i, j; - int best, best2; - int bestx; - int texnum; - - for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) - { - best = BLOCK_HEIGHT; - - for (i=0 ; i<BLOCK_WIDTH-w ; i++) - { - best2 = 0; - - for (j=0 ; j<w ; j++) - { - if (scrap_allocated[texnum][i+j] >= best) - break; - if (scrap_allocated[texnum][i+j] > best2) - best2 = scrap_allocated[texnum][i+j]; - } - if (j == w) - { // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > BLOCK_HEIGHT) - continue; - - for (i=0 ; i<w ; i++) - scrap_allocated[texnum][*x + i] = best + h; - - return texnum; - } - - Sys_Error ("Scrap_AllocBlock: full"); - return 0; -} - -int scrap_uploads; - -void Scrap_Upload (void) -{ - int texnum; - - scrap_uploads++; - - for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) { - GL_Bind(scrap_texnum + texnum); - GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true); - } - scrap_dirty = false; -} - -//============================================================================= -/* Support Routines */ - -typedef struct cachepic_s -{ - char name[MAX_QPATH]; - qpic_t pic; - byte padding[32]; // for appended glpic -} cachepic_t; - -#define MAX_CACHED_PICS 128 -cachepic_t menu_cachepics[MAX_CACHED_PICS]; -int menu_numcachepics; - -byte menuplyr_pixels[4096]; - -int pic_texels; -int pic_count; - - -/* -================ -GL_LoadPicTexture -================ -*/ -int GL_LoadPicTexture (qpic_t *pic) -{ - return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true); -} - - -qpic_t *Draw_PicFromWad (const char *name) -{ - packedGlpic_t *pp; - - pp = (packedGlpic_t*) W_GetLumpName (name); - - qpic_t* p = & pp->qpic; - glpic_t* gl = & pp->g.glpic; - - // load little ones into the scrap - if (p->width < 64 && p->height < 64) - { - int x, y; - int i, j, k; - int texnum; - - texnum = Scrap_AllocBlock (p->width, p->height, &x, &y); - scrap_dirty = true; - k = 0; - for (i=0 ; i<p->height ; i++) - for (j=0 ; j<p->width ; j++, k++) - scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k]; - texnum += scrap_texnum; - gl->texnum = texnum; - gl->sl = (x+0.01)/(float)BLOCK_WIDTH; - gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH; - gl->tl = (y+0.01)/(float)BLOCK_WIDTH; - gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH; - - pic_count++; - pic_texels += p->width*p->height; - } - else - { - gl->texnum = GL_LoadPicTexture (p); - gl->sl = 0; - gl->sh = 1; - gl->tl = 0; - gl->th = 1; - } - return p; -} - - -/* -================ -Draw_CachePic -================ -*/ -qpic_t *Draw_CachePic (const char *path) -{ - cachepic_t *pic; - int i; - qpic_t *dat; - glpic_t *gl; - - for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++) - if (!strcmp (path, pic->name)) - return &pic->pic; - - if (menu_numcachepics == MAX_CACHED_PICS) - Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); - menu_numcachepics++; - strcpy (pic->name, path); - -// -// load the pic from disk -// - dat = (qpic_t *)COM_LoadTempFile (path); - if (!dat) - Sys_Error ("Draw_CachePic: failed to load %s", path); - SwapPic (dat); - - // HACK HACK HACK --- we need to keep the bytes for - // the translatable player picture just for the menu - // configuration dialog - if (!strcmp (path, "gfx/menuplyr.lmp")) - memcpy (menuplyr_pixels, dat->data, dat->width*dat->height); - - pic->pic.width = dat->width; - pic->pic.height = dat->height; - - glpic_t temp; - gl = &temp; - gl->texnum = GL_LoadPicTexture (dat); - gl->sl = 0; - gl->sh = 1; - gl->tl = 0; - gl->th = 1; - - memcpy(pic->pic.data, &temp, sizeof(temp)); - - return &pic->pic; -} - - -void Draw_CharToConback (int num, byte *dest) -{ - int row, col; - byte *source; - int drawline; - int x; - - row = num>>4; - col = num&15; - source = draw_chars + (row<<10) + (col<<3); - - drawline = 8; - - while (drawline--) - { - for (x=0 ; x<8 ; x++) - if (source[x] != 255) - dest[x] = 0x60 + source[x]; - source += 128; - dest += 320; - } - -} - -typedef struct -{ - const char *name; - int minimize, maximize; -} glmode_t; - -glmode_t modes[] = { - {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, - {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} -}; - -/* -=============== -Draw_TextureMode_f -=============== -*/ -void Draw_TextureMode_f (void) -{ - int i; - gltexture_t *glt; - - if (Cmd_Argc() == 1) - { - for (i=0 ; i< 6 ; i++) - if (gl_filter_min == modes[i].minimize) - { - Con_Printf ("%s\n", modes[i].name); - return; - } - Con_Printf ("current filter is unknown???\n"); - return; - } - - for (i=0 ; i< 6 ; i++) - { - if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) ) - break; - } - if (i == 6) - { - Con_Printf ("bad filter name\n"); - return; - } - - gl_filter_min = modes[i].minimize; - gl_filter_max = modes[i].maximize; - - // change all the existing mipmap texture objects - for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) - { - if (glt->mipmap) - { - GL_Bind (glt->texnum); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - } -} - -/* -=============== -Draw_Init -=============== -*/ -void Draw_Init (void) -{ - int i; - qpic_t *cb; - byte *dest, *src; - int x, y; - char ver[40]; - glpic_t *gl; - int start; - byte *ncdata; - int f, fstep; - - - Cvar_RegisterVariable (&gl_nobind); - Cvar_RegisterVariable (&gl_max_size); - Cvar_RegisterVariable (&gl_picmip); - - // 3dfx can only handle 256 wide textures - if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || - strstr((char *)gl_renderer, "Glide")) - Cvar_Set ("gl_max_size", "256"); - - Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f); - - // load the console background and the charset - // by hand, because we need to write the version - // string into the background before turning - // it into a texture - draw_chars = (byte*) W_GetLumpName ("conchars"); - for (i=0 ; i<256*64 ; i++) - if (draw_chars[i] == 0) - draw_chars[i] = 255; // proper transparent color - - // now turn them into textures - char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true); - - start = Hunk_LowMark(); - - cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp"); - if (!cb) - Sys_Error ("Couldn't load gfx/conback.lmp"); - SwapPic (cb); - - // hack the version number directly into the pic -#if defined(__linux__) - sprintf (ver, "(Linux %2.2f, gl %4.2f) %4.2f", (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION); -#else - sprintf (ver, "(gl %4.2f) %4.2f", (float)GLQUAKE_VERSION, (float)VERSION); -#endif - dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver); - y = strlen(ver); - for (x=0 ; x<y ; x++) - Draw_CharToConback (ver[x], dest+(x<<3)); - -#if 0 - conback->width = vid.conwidth; - conback->height = vid.conheight; - - // scale console to vid size - dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback"); - - for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth) - { - src = cb->data + cb->width * (y*cb->height/vid.conheight); - if (vid.conwidth == cb->width) - memcpy (dest, src, vid.conwidth); - else - { - f = 0; - fstep = cb->width*0x10000/vid.conwidth; - for (x=0 ; x<vid.conwidth ; x+=4) - { - dest[x] = src[f>>16]; - f += fstep; - dest[x+1] = src[f>>16]; - f += fstep; - dest[x+2] = src[f>>16]; - f += fstep; - dest[x+3] = src[f>>16]; - f += fstep; - } - } - } -#else - conback->g.width = cb->width; - conback->g.height = cb->height; - ncdata = cb->data; -#endif - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - gl = &conback->g.glpic; - gl->texnum = GL_LoadTexture ("conback", conback->g.width, conback->g.height, ncdata, false, false); - gl->sl = 0; - gl->sh = 1; - gl->tl = 0; - gl->th = 1; - conback->g.width = vid.width; - conback->g.height = vid.height; - - // free loaded console - Hunk_FreeToLowMark(start); - - // save a texture slot for translated picture - translate_texture = texture_extension_number++; - - // save slots for scraps - scrap_texnum = texture_extension_number; - texture_extension_number += MAX_SCRAPS; - - // - // get the other pics we need - // - draw_disc = Draw_PicFromWad ("disc"); - draw_backtile = Draw_PicFromWad ("backtile"); -} - - - -/* -================ -Draw_Character - -Draws one 8*8 graphics character with 0 being transparent. -It can be clipped to the top of the screen to allow the console to be -smoothly scrolled off. -================ -*/ -void Draw_Character (int x, int y, int num) -{ - byte *dest; - byte *source; - unsigned short *pusdest; - int drawline; - int row, col; - float frow, fcol, size; - - if (num == 32) - return; // space - - num &= 255; - - if (y <= -8) - return; // totally off screen - - row = num>>4; - col = num&15; - - frow = row*0.0625; - fcol = col*0.0625; - size = 0.0625; - - GL_Bind (char_texture); - -#ifdef USE_OPENGLES - DrawQuad(x, y, 8, 8, fcol, frow, size, size); -#else - glBegin (GL_QUADS); - glTexCoord2f (fcol, frow); - glVertex2f (x, y); - glTexCoord2f (fcol + size, frow); - glVertex2f (x+8, y); - glTexCoord2f (fcol + size, frow + size); - glVertex2f (x+8, y+8); - glTexCoord2f (fcol, frow + size); - glVertex2f (x, y+8); - glEnd (); -#endif -} - -/* -================ -Draw_String -================ -*/ -void Draw_String (int x, int y, const char *str) -{ - while (*str) - { - Draw_Character (x, y, *str); - str++; - x += 8; - } -} - -/* -================ -Draw_DebugChar - -Draws a single character directly to the upper right corner of the screen. -This is for debugging lockups by drawing different chars in different parts -of the code. -================ -*/ -void Draw_DebugChar (char num) -{ -} - -/* -============= -Draw_AlphaPic -============= -*/ -void Draw_AlphaPic (int x, int y, packedGlpic_t *ppic, float alpha) -{ - byte *dest, *source; - unsigned short *pusdest; - int v, u; - glpic_t *gl; - - if (scrap_dirty) - Scrap_Upload (); - gl = & ppic->g.glpic; - glDisable(GL_ALPHA_TEST); - glEnable (GL_BLEND); -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glCullFace(GL_FRONT); - glColor4f (1,1,1,alpha); - GL_Bind (gl->texnum); -#ifdef USE_OPENGLES - DrawQuad(x, y, ppic->g.width, ppic->g.height, gl->sl, gl->tl, gl->sh - gl->sl, gl->th - gl->tl); -#else - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (x+pic->width, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, y+pic->height); - glEnd (); -#endif - glColor4f (1,1,1,1); - glEnable(GL_ALPHA_TEST); - glDisable (GL_BLEND); -} - - -/* -============= -Draw_Pic -============= -*/ -void Draw_Pic (int x, int y, qpic_t *pic) -{ - byte *dest, *source; - unsigned short *pusdest; - int v, u; - glpic_t *gl; - - if (scrap_dirty) - Scrap_Upload (); - glpic_t temp; - memcpy(&temp, pic->data, sizeof(temp)); - gl = & temp; - glColor4f (1,1,1,1); - GL_Bind (gl->texnum); -#ifdef USE_OPENGLES - DrawQuad(x, y, pic->width, pic->height, gl->sl, gl->tl, gl->sh - gl->sl, gl->th - gl->tl); -#else - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (x+pic->width, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, y+pic->height); - glEnd (); -#endif -} - - -/* -============= -Draw_TransPic -============= -*/ -void Draw_TransPic (int x, int y, qpic_t *pic) -{ - byte *dest, *source, tbyte; - unsigned short *pusdest; - int v, u; - - if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || - (unsigned)(y + pic->height) > vid.height) - { - Sys_Error ("Draw_TransPic: bad coordinates"); - } - - Draw_Pic (x, y, pic); -} - - -/* -============= -Draw_TransPicTranslate - -Only used for the player color selection menu -============= -*/ -void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation) -{ - int v, u, c; - unsigned trans[64*64], *dest; - byte *src; - int p; - - GL_Bind (translate_texture); - - c = pic->width * pic->height; - - dest = trans; - for (v=0 ; v<64 ; v++, dest += 64) - { - src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width]; - for (u=0 ; u<64 ; u++) - { - p = src[(u*pic->width)>>6]; - if (p == 255) - dest[u] = p; - else - dest[u] = d_8to24table[translation[p]]; - } - } - - glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glColor3f (1,1,1); -#ifdef USE_OPENGLES - DrawQuad(x, y, pic->width, pic->height, 0, 0, 1, 1); -#else - glBegin (GL_QUADS); - glTexCoord2f (0, 0); - glVertex2f (x, y); - glTexCoord2f (1, 0); - glVertex2f (x+pic->width, y); - glTexCoord2f (1, 1); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (0, 1); - glVertex2f (x, y+pic->height); - glEnd (); -#endif -} - - -/* -================ -Draw_ConsoleBackground - -================ -*/ -void Draw_ConsoleBackground (int lines) -{ - int y = (vid.height * 3) >> 2; - - if (lines > y) - Draw_Pic(0, lines - vid.height, &conback->qpic); - else - Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y); -} - - -/* -============= -Draw_TileClear - -This repeats a 64*64 tile graphic to fill the screen around a sized down -refresh window. -============= -*/ - -typedef union ByteToInt_t { - byte b[4]; - int i; -} ByteToInt; - -void Draw_TileClear (int x, int y, int w, int h) -{ - glColor3f (1,1,1); - ByteToInt b; - memcpy(b.b, draw_backtile->data, sizeof(b.b)); - GL_Bind (b.i); -#ifdef USE_OPENGLES - DrawQuad(x, y, w, h, x/64.0, y/64.0, w/64.0, h/64.0); -#else - glBegin (GL_QUADS); - glTexCoord2f (x/64.0, y/64.0); - glVertex2f (x, y); - glTexCoord2f ( (x+w)/64.0, y/64.0); - glVertex2f (x+w, y); - glTexCoord2f ( (x+w)/64.0, (y+h)/64.0); - glVertex2f (x+w, y+h); - glTexCoord2f ( x/64.0, (y+h)/64.0 ); - glVertex2f (x, y+h); - glEnd (); -#endif -} - - -/* -============= -Draw_Fill - -Fills a box of pixels with a single color -============= -*/ -void Draw_Fill (int x, int y, int w, int h, int c) -{ - glDisable (GL_TEXTURE_2D); - glColor3f (host_basepal[c*3]/255.0, - host_basepal[c*3+1]/255.0, - host_basepal[c*3+2]/255.0); - -#ifdef USE_OPENGLES - DrawQuad_NoTex(x, y, w, h); -#else - glBegin (GL_QUADS); - - glVertex2f (x,y); - glVertex2f (x+w, y); - glVertex2f (x+w, y+h); - glVertex2f (x, y+h); - - glEnd (); -#endif - glColor3f (1,1,1); - glEnable (GL_TEXTURE_2D); -} -//============================================================================= - -/* -================ -Draw_FadeScreen - -================ -*/ -void Draw_FadeScreen (void) -{ - glEnable (GL_BLEND); - glDisable (GL_TEXTURE_2D); - glColor4f (0, 0, 0, 0.8); -#ifdef USE_OPENGLES - DrawQuad_NoTex(0, 0, vid.width, vid.height); -#else - glBegin (GL_QUADS); - - glVertex2f (0,0); - glVertex2f (vid.width, 0); - glVertex2f (vid.width, vid.height); - glVertex2f (0, vid.height); - - glEnd (); -#endif - glColor4f (1,1,1,1); - glEnable (GL_TEXTURE_2D); - glDisable (GL_BLEND); - - Sbar_Changed(); -} - -//============================================================================= - -/* -================ -Draw_BeginDisc - -Draws the little blue disc in the corner of the screen. -Call before beginning any disc IO. -================ -*/ -void Draw_BeginDisc (void) -{ - if (!draw_disc) - return; -#ifdef USE_OPENGLES - // !!! Implement this -#else - glDrawBuffer (GL_FRONT); - Draw_Pic (vid.width - 24, 0, draw_disc); - glDrawBuffer (GL_BACK); -#endif -} - - -/* -================ -Draw_EndDisc - -Erases the disc icon. -Call after completing any disc IO -================ -*/ -void Draw_EndDisc (void) -{ -} - -/* -================ -GL_Set2D - -Setup as if the screen was 320*200 -================ -*/ -void GL_Set2D (void) -{ - glViewport (glx, gly, glwidth, glheight); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); -#ifdef USE_OPENGLES - glOrthof (0, vid.width, vid.height, 0, -99999, 99999); -#else - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); -#endif - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - - glDisable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - glDisable (GL_BLEND); - glEnable (GL_ALPHA_TEST); -// glDisable (GL_ALPHA_TEST); - - glColor4f (1,1,1,1); -} - -//==================================================================== - -/* -================ -GL_FindTexture -================ -*/ -int GL_FindTexture (const char *identifier) -{ - int i; - gltexture_t *glt; - - for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) - { - if (!strcmp (identifier, glt->identifier)) - return gltextures[i].texnum; - } - - return -1; -} - -/* -================ -GL_ResampleTexture -================ -*/ -void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight) -{ - int i, j; - unsigned *inrow; - unsigned frac, fracstep; - - fracstep = inwidth*0x10000/outwidth; - for (i=0 ; i<outheight ; i++, out += outwidth) - { - inrow = in + inwidth*(i*inheight/outheight); - frac = fracstep >> 1; - for (j=0 ; j<outwidth ; j+=4) - { - out[j] = inrow[frac>>16]; - frac += fracstep; - out[j+1] = inrow[frac>>16]; - frac += fracstep; - out[j+2] = inrow[frac>>16]; - frac += fracstep; - out[j+3] = inrow[frac>>16]; - frac += fracstep; - } - } -} - -/* -================ -GL_Resample8BitTexture -- JACK -================ -*/ -void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight) -{ - int i, j; - unsigned char *inrow; - unsigned frac, fracstep; - - fracstep = inwidth*0x10000/outwidth; - for (i=0 ; i<outheight ; i++, out += outwidth) - { - inrow = in + inwidth*(i*inheight/outheight); - frac = fracstep >> 1; - for (j=0 ; j<outwidth ; j+=4) - { - out[j] = inrow[frac>>16]; - frac += fracstep; - out[j+1] = inrow[frac>>16]; - frac += fracstep; - out[j+2] = inrow[frac>>16]; - frac += fracstep; - out[j+3] = inrow[frac>>16]; - frac += fracstep; - } - } -} - - -/* -================ -GL_MipMap - -Operates in place, quartering the size of the texture -================ -*/ -void GL_MipMap (byte *in, int width, int height) -{ - int i, j; - byte *out; - - width <<=2; - height >>= 1; - out = in; - for (i=0 ; i<height ; i++, in+=width) - { - for (j=0 ; j<width ; j+=8, out+=4, in+=8) - { - out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2; - out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2; - out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2; - out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2; - } - } -} - -#ifdef SUPPORT_8BIT_MIPMAPGENERATION -/* -================ -GL_MipMap8Bit - -Mipping for 8 bit textures - -The "in" and "out" arguments can point to the same buffer if desired -================ -*/ -void GL_MipMap8Bit (byte *in, byte* out, int width, int height) -{ - int i, j; - unsigned short r,g,b; - byte *at1, *at2, *at3, *at4; - -// width <<=2; - height >>= 1; - for (i=0 ; i<height ; i++, in+=width) - { - for (j=0 ; j<width ; j+=2, out+=1, in+=2) - { - at1 = (byte *) (d_8to24table + in[0]); - at2 = (byte *) (d_8to24table + in[1]); - at3 = (byte *) (d_8to24table + in[width+0]); - at4 = (byte *) (d_8to24table + in[width+1]); - - r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5; - g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5; - b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5; - - out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)]; - } - } -} - -#endif // SUPPORT_8BIT_MIPMAPGENERATION - -void glTexImage2DHelper( GLenum target, - GLint level, - GLint internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const GLvoid *pixels ) -{ - // In full OpenGL The internalformat can be 1..4, to indicate how many components of the data are valid. - // OpenGL ES requires the internalformat argument match the format for glTexImage2D. - - glTexImage2D(target, level, format, width, height, border, format, type, pixels); -} - - -// Uncomment to enable manual MipMap generation -#define USE_MANUAL_MIPMAP_GEN - -// Uncomment one of the following: - -// #define USE_16BPP_WITH_8888_ALPHA -// #define USE_16BPP_WITH_5551_ALPHA // <--- This has bugs on the simulator and the device. (Device has all alpha images invisible.) -#define USE_16BPP_WITH_4444_ALPHA // <--- This has bugs on the simulator, works in device -// #define USE_32BPP -// #define USE_32BPP_MANUAL_MIPMAP_GEN - -#ifdef USE_MANUAL_MIPMAP_GEN - -inline unsigned int average4(unsigned int a, unsigned int b, - unsigned int c, unsigned int d, - unsigned int shift, unsigned int mask) { - unsigned int aElem = (a >> shift) & mask; - unsigned int bElem = (b >> shift) & mask; - unsigned int cElem = (c >> shift) & mask; - unsigned int dElem = (d >> shift) & mask; - unsigned int avgElem = ((aElem + bElem + cElem + dElem) >> 2) & mask; - return avgElem << shift; -} - -inline unsigned int average2(unsigned int a, unsigned int b, - unsigned int shift, unsigned int mask) { - unsigned int aElem = (a >> shift) & mask; - unsigned int bElem = (b >> shift) & mask; - unsigned int avgElem = ((aElem + bElem) >> 1) & mask; - return avgElem << shift; -} - -inline unsigned int average4444(unsigned int a, unsigned int b) { - return - average2(a,b,0,0xf) | - average2(a,b,4,0xf) | - average2(a,b,8,0xf) | - average2(a,b,12,0xf); -} - -inline unsigned int average565(unsigned int a, unsigned int b) { - return - average2(a,b,0,0x1f) | - average2(a,b,5,0x3f) | - average2(a,b,11,0x1f); -} - -inline unsigned int average2_8888(unsigned int a, unsigned int b) { - return - average2(a,b,0,0xff) | - average2(a,b,8,0xff) | - average2(a,b,16,0xff) | - average2(a,b,24,0xff); -} - -inline unsigned int average4_8888(unsigned int a, unsigned int b, - unsigned int c, unsigned int d) { - return - average4(a,b,c,d,0,0xff) | - average4(a,b,c,d,8,0xff) | - average4(a,b,c,d,16,0xff) | - average4(a,b,c,d,24,0xff); -} - -#endif - -// pData is 8 bpp 32-bit color - - -void sendTexture(int mipLevel, int width, int height, unsigned int* pData, qboolean alpha) { - if (alpha) { -#if defined(USE_16BPP_WITH_8888_ALPHA) - // 8888 - glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData); -#elif defined(USE_16BPP_WITH_5551_ALPHA) - // 5551 - glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 0); - glTexSubImage2D(GL_TEXTURE_2D, mipLevel, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pData); -#else - // 4444 - glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0); - glTexSubImage2D(GL_TEXTURE_2D, mipLevel, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pData); -#endif - } - else { -#if 0 - // 8888 - glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData); -#else - // 565 - static unsigned short scaled[1024*512]; // [512*256]; - glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); - // Some OpenGL ES implementations do not have to be able to convert from GL_RGBA to GL_RGB format, so - // we must do it manually here: - unsigned char* pSrc = (unsigned char*) pData; - unsigned short* pDest = scaled; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - *pDest++ = ((pSrc[0] >> 3) << 11) | - ((pSrc[1] >> 2) << 5) | - (pSrc[2] >> 3); - pSrc += 4; - } - } - glTexSubImage2D(GL_TEXTURE_2D, mipLevel, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, scaled); -#endif - } -} - -/* -=============== -GL_Upload32 -=============== -*/ -void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha) -{ - int samples; - int scaled_width, scaled_height; - static unsigned scaled[1024*512]; // [512*256]; - - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; - - scaled_width >>= (int)gl_picmip.value; - scaled_height >>= (int)gl_picmip.value; - - if (scaled_width > gl_max_size.value) - scaled_width = (int) gl_max_size.value; - if (scaled_height > gl_max_size.value) - scaled_height = (int) gl_max_size.value; - - if (scaled_width * scaled_height > (int) sizeof(scaled)/4) - Sys_Error ("GL_LoadTexture: too big"); - - samples = alpha ? gl_alpha_format : gl_solid_format; - - texels += scaled_width * scaled_height; - - if (scaled_width == width && scaled_height == height) - { -#if 0 // Disable this optimization, we want to be able to easily switch texture formats - if (!mipmap) - { - glTexImage2DHelper (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - goto done; - } -#endif - memcpy (scaled, data, width*height*4); - } - else - GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); - -#if defined(USE_16BPP_WITH_8888_ALPHA) || defined(USE_16BPP_WITH_5551_ALPHA) || defined(USE_16BPP_WITH_4444_ALPHA) - // Upload as 16 bpp - -#ifdef USE_MANUAL_MIPMAP_GEN -#else - // Use automatic MIPMAP generation - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1); - } -#endif - - sendTexture(0, scaled_width, scaled_height, scaled, alpha); - -#ifdef USE_MANUAL_MIPMAP_GEN - if (mipmap) { - // Compute mip levels - int mipWidth = scaled_width; - int mipHeight = scaled_height; - int mipLevel = 1; - while (mipWidth > 1 || mipHeight > 1) { - if (mipWidth > 1 && mipHeight > 1) { - // Scale horizontally and vertically - int srcWidth = mipWidth; - mipWidth >>= 1; - mipHeight >>= 1; - const unsigned int* pIn = (const unsigned int*) scaled; - unsigned int* pOut = (unsigned int*) scaled; - for(int y = 0; y < mipHeight; y++) { - for (int x = 0; x < mipWidth; x++) { - *pOut++ = average4_8888(pIn[0], pIn[1], - pIn[srcWidth], pIn[srcWidth+1]); - pIn += 2; - } - pIn += srcWidth; - } - } - else { - // Scale horizontally: - if (mipWidth > 1) { - mipWidth >>= 1; - const unsigned int* pIn = (const unsigned int*) scaled; - unsigned int* pOut = (unsigned int*) scaled; - unsigned int numTexels = mipHeight * mipWidth; - for(unsigned int i = 0; i < numTexels; i++) { - *pOut++ = average2_8888(pIn[0], pIn[1]); - pIn += 2; - } - } - // Scale vertically: - if (mipHeight > 1) { - mipHeight >>= 1; - const unsigned int* pIn = (const unsigned int*) scaled; - unsigned int* pOut = (unsigned int*) scaled; - for(int y = 0; y < mipHeight; y++) { - for (int x = 0; x < mipWidth; x++) { - *pOut++ = average2_8888(pIn[0], pIn[mipWidth]); - pIn += 1; - } - pIn += mipWidth; - } - } - } - - sendTexture(mipLevel, mipWidth, mipHeight, scaled, alpha); - mipLevel++; - } - } - -#else - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 0); - } -#endif - -#elif defined(USE_32BPP) - // 8888 - // Use automatic MIPMAP generation - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1); - } - glTexImage2DHelper (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 0); - } -#else - glTexImage2DHelper (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - if (mipmap) - { - int miplevel; - - miplevel = 0; - while (scaled_width > 1 || scaled_height > 1) - { - GL_MipMap ((byte *)scaled, scaled_width, scaled_height); - scaled_width >>= 1; - scaled_height >>= 1; - if (scaled_width < 1) - scaled_width = 1; - if (scaled_height < 1) - scaled_height = 1; - miplevel++; - glTexImage2DHelper (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - } - } -#endif -done: ; - - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } -} - -#ifdef USE_OPENGLES - -void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha) -{ - int i, s, bytesUsed; - qboolean noalpha; - int p; - static unsigned j; - static unsigned char compressedTextureBuffer[1024*512]; // [512*256]; - unsigned char* pTex = compressedTextureBuffer; - int scaled_width, scaled_height; - int miplevel = 0; - - int originalScaledWidth; - int originalScaledHeight; - - s = width*height; - // if there are no transparent pixels, make it a 3 component - // texture even if it was specified as otherwise - if (alpha) - { - noalpha = true; - for (i=0 ; i<s ; i++) - { - if (data[i] == 255) - noalpha = false; - } - - if (alpha && noalpha) - alpha = false; - } - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; - - scaled_width >>= (int)gl_picmip.value; - scaled_height >>= (int)gl_picmip.value; - - if (scaled_width > gl_max_size.value) - scaled_width = (int) gl_max_size.value; - if (scaled_height > gl_max_size.value) - scaled_height = (int) gl_max_size.value; - - if (scaled_width * scaled_height > ((int) (sizeof(compressedTextureBuffer) * 3 / 4))) - Sys_Error ("GL_LoadTexture: too big"); - - // Copy the palette - - int entrySize = alpha ? 4 : 3; - int paletteSize = entrySize * 256; - { - byte* pDest = compressedTextureBuffer; - const byte* pSrc = host_basepal; - if(alpha) - { - for(int i = 0; i< 255; i++) - { - *pDest++ = *pSrc++; - *pDest++ = *pSrc++; - *pDest++ = *pSrc++; - *pDest++ = 0xff; - } - // Entry 255 is transparent - *pDest++ = 0x00; - *pDest++ = 0x00; - *pDest++ = 0x00; - *pDest++ = 0x00; - } - else - { - memcpy(pDest, pSrc, paletteSize); - } - } - - bytesUsed = paletteSize; - pTex += paletteSize; - - texels += scaled_width * scaled_height; - - if (scaled_width == width && scaled_height == height) - { - memcpy (pTex, data, scaled_width*scaled_height); - } - else - GL_Resample8BitTexture (data, width, height, pTex, scaled_width, scaled_height); - - bytesUsed += scaled_width * scaled_height; - - miplevel = 0; - - originalScaledWidth = scaled_width; - originalScaledHeight = scaled_height; - - if (mipmap) - { -#ifdef SUPPORT_8BIT_MIPMAPGENERATION - miplevel = 1; - while (scaled_width > 1 || scaled_height > 1) - { - byte* pDest = (byte*) pTex + scaled_width * scaled_height; - GL_MipMap8Bit ((byte *)pTex, pDest, scaled_width, scaled_height); - pTex = pDest; - scaled_width >>= 1; - scaled_height >>= 1; - if (scaled_width < 1) - scaled_width = 1; - if (scaled_height < 1) - scaled_height = 1; - bytesUsed += scaled_width * scaled_height; - miplevel++; - } -#else - Sys_Error("Unsupported attempt to generate 8 bit mip mapped texture. #define SUPPORT_8BIT_MIPMAPGENERATION"); -#endif - } - - GLint internalFormat = alpha ? GL_PALETTE8_RGBA8_OES : GL_PALETTE8_RGB8_OES; - glCompressedTexImage2D (GL_TEXTURE_2D, -miplevel, internalFormat, - originalScaledWidth, originalScaledHeight, - 0, bytesUsed, compressedTextureBuffer); - - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } -} - -#else - -void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha) -{ - int i, s; - qboolean noalpha; - int p; - static unsigned j; - int samples; - static unsigned char scaled[1024*512]; // [512*256]; - int scaled_width, scaled_height; - - s = width*height; - // if there are no transparent pixels, make it a 3 component - // texture even if it was specified as otherwise - if (alpha) - { - noalpha = true; - for (i=0 ; i<s ; i++) - { - if (data[i] == 255) - noalpha = false; - } - - if (alpha && noalpha) - alpha = false; - } - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; - - scaled_width >>= (int)gl_picmip.value; - scaled_height >>= (int)gl_picmip.value; - - if (scaled_width > gl_max_size.value) - scaled_width = gl_max_size.value; - if (scaled_height > gl_max_size.value) - scaled_height = gl_max_size.value; - - if (scaled_width * scaled_height > (int) sizeof(scaled)) - Sys_Error ("GL_LoadTexture: too big"); - - samples = 1; // alpha ? gl_alpha_format : gl_solid_format; - - texels += scaled_width * scaled_height; - - if (scaled_width == width && scaled_height == height) - { - if (!mipmap) - { - glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data); - goto done; - } - memcpy (scaled, data, width*height); - } - else - GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height); - - glCompressedTexImage2D (GL_TEXTURE_2D, 0, GL_PALETTE8_RGB8_OES, scaled_width, scaled_height, 0, s, scaled); - if (mipmap) - { -#ifdef SUPPORT_8BIT_MIPMAPGENERATION - int miplevel; - - miplevel = 0; - while (scaled_width > 1 || scaled_height > 1) - { - GL_MipMap8Bit ((byte *)scaled, (byte*) scaled, scaled_width, scaled_height); - scaled_width >>= 1; - scaled_height >>= 1; - if (scaled_width < 1) - scaled_width = 1; - if (scaled_height < 1) - scaled_height = 1; - miplevel++; - glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled); - } -#else - Sys_Error("Unsupported attept to generate 8 bit mip mapped texture."); -#endif - } -done: ; - - - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } -} - -#endif // ! OPENGL_ES - -/* -=============== -GL_Upload8 -=============== -*/ -void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha) -{ -static unsigned trans[640*480]; // FIXME, temporary - int i, s; - qboolean noalpha; - int p; - - s = width*height; - // if there are no transparent pixels, make it a 3 component - // texture even if it was specified as otherwise - if (alpha) - { - noalpha = true; - for (i=0 ; i<s ; i++) - { - p = data[i]; - if (p == 255) - noalpha = false; - trans[i] = d_8to24table[p]; - } - - if (alpha && noalpha) - alpha = false; - } - else - { - if (s&3) - Sys_Error ("GL_Upload8: s&3"); - for (i=0 ; i<s ; i+=4) - { - trans[i] = d_8to24table[data[i]]; - trans[i+1] = d_8to24table[data[i+1]]; - trans[i+2] = d_8to24table[data[i+2]]; - trans[i+3] = d_8to24table[data[i+3]]; - } - } - - if (VID_Is8bit() && (data!=scrap_texels[0]) -#if !defined(USE_OPENGLES) - && !alpha -#endif - ) { - GL_Upload8_EXT (data, width, height, mipmap, alpha); - return; - } - GL_Upload32 (trans, width, height, mipmap, alpha); -} - -/* -================ -GL_LoadTexture -================ -*/ -int GL_LoadTexture (const char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha) -{ - qboolean noalpha; - int i, p, s; - gltexture_t *glt; - - // see if the texture is allready present - if (identifier[0]) - { - for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) - { - if (!strcmp (identifier, glt->identifier)) - { - if (width != glt->width || height != glt->height) - Sys_Error ("GL_LoadTexture: cache mismatch"); - return gltextures[i].texnum; - } - } -#ifdef USE_OPENGLES - // Surely we want to remember this new texture. - // Doing this costs 1% fps per timedemo on a DX7 PC, - // probably because of the linear search through the - // texture cache, but it saves 10 MB of VM growth per - // level load. It also makes the GL_TEXTUREMODE - // console command work correctly. - numgltextures++; -#endif - } - else { - glt = &gltextures[numgltextures]; - numgltextures++; - } - - strcpy (glt->identifier, identifier); - glt->texnum = texture_extension_number; - glt->width = width; - glt->height = height; - glt->mipmap = mipmap; - - GL_Bind(texture_extension_number); - -#ifdef USE_TEXTURE_STORE - - textureStore::get()->create(width, height, data, mipmap, alpha); - -#else - - GL_Upload8 (data, width, height, mipmap, alpha); - -#endif - - texture_extension_number++; - return texture_extension_number-1; -} - - -/****************************************/ - -static GLenum oldtarget = TEXTURE0_SGIS; - -void GL_SelectTexture (GLenum target) -{ - if (!gl_mtexable) - return; -#ifdef USE_OPENGLES - glActiveTexture(target); -#else - qglSelectTextureSGIS(target); -#endif - if (target == oldtarget) - return; - cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture; - currenttexture = cnttextures[target-TEXTURE0_SGIS]; - oldtarget = target; -} - -// OpenGL ES compatible DrawQuad utility - -#define BEGIN_QUAD glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); -#define END_QUAD glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - -void DrawQuad_NoTex(float x, float y, float w, float h) -{ - BEGIN_QUAD - - float vertex[2*4] = {x,y,x+w,y, x+w, y+h, x, y+h}; - short index[4] = {0, 1, 2, 3}; - glVertexPointer( 2, GL_FLOAT, 0, vertex); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, index); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - END_QUAD -} - -void DrawQuad(float x, float y, float w, float h, float u, float v, float uw, float vh) -{ - BEGIN_QUAD - - float texcoord[2*4] = {u, v, u + uw, v, u + uw, v + vh, u, v + vh}; - float vertex[2*4] = {x,y,x+w,y, x+w, y+h, x, y+h}; - unsigned short index[4] = {0, 1, 2, 3}; - glTexCoordPointer( 2, GL_FLOAT, 0, texcoord); - glVertexPointer( 2, GL_FLOAT, 0, vertex); - glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, index); - - END_QUAD -} - -#ifdef USE_OPENGLES - -// Reimplementation of OpenGL functions that are missing in OpenGL ES - -void glColor3f(GLfloat r, GLfloat g, GLfloat b) -{ - glColor4f(r, g, b, 1.0f); -} - -void glColor4fv(GLfloat* pColor) -{ - glColor4f(pColor[0], pColor[1], pColor[2], pColor[3]); -} - -float gVertexBuffer[VERTEXARRAYSIZE]; -float gColorBuffer[VERTEXARRAYSIZE]; -float gTexCoordBuffer[VERTEXARRAYSIZE]; - -// Called when we've lost the OpenGL context and have to recreate it. -extern void GL_Init(); -extern void R_InitParticleTexture2(); -extern void GL_UploadLightmaps(); -extern void R_ReloadSky(); - -void GL_ReInit() { - GL_Init(); - textureStore::get()->rebindAll(); - scrap_dirty = true; - R_InitParticleTexture2(); - GL_UploadLightmaps(); - R_ReloadSky(); -} - -#endif - -#ifdef DEBUG_OPENGL_CALLS -void checkGLImp(const char* state, const char* file, int line) { - GLenum error = glGetError(); - if (error != GL_NO_ERROR) { - Sys_Error("%s: error 0x%04X at %s:%d\n", state, error, file, line); - } -} - -#endif |