summaryrefslogtreecommitdiff
path: root/samples/quake/jni/gl_draw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/quake/jni/gl_draw.cpp')
-rw-r--r--samples/quake/jni/gl_draw.cpp2127
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