mirror of
https://github.com/libretro/libretro-tyrquake.git
synced 2024-11-23 08:00:17 +00:00
textures: introduce new mipmap code
New mipmap code handles odd textures sizes so that we can start using NPoT textures where the hardware supports it. We've also removed some texture size limitations - the new code is only limited by the available space on the hunk. We're still unconditionally stretching to power of two, so this doesn't do anything noticable yet. One thing this fixes is generating the lowest level mipmaps where the texture is only one-pixel wide or tall - the old code didn't handle this special case properly. Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
parent
63ad422df3
commit
c723ebda22
3
Makefile
3
Makefile
@ -719,7 +719,8 @@ GL_OBJS := \
|
||||
gl_rmain.o \
|
||||
gl_rmisc.o \
|
||||
gl_rsurf.o \
|
||||
gl_warp.o
|
||||
gl_warp.o \
|
||||
textures.o
|
||||
|
||||
NQSW_OBJS :=
|
||||
|
||||
|
180
common/gl_draw.c
180
common/gl_draw.c
@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#include "sbar.h"
|
||||
#include "screen.h"
|
||||
#include "sys.h"
|
||||
#include "textures.h"
|
||||
#include "view.h"
|
||||
#include "wad.h"
|
||||
|
||||
@ -1033,130 +1034,63 @@ GL_FindTexture(const char *identifier)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_ResampleTexture
|
||||
================
|
||||
*/
|
||||
static void
|
||||
GL_ResampleTexture(const unsigned *in, int inwidth, int inheight,
|
||||
unsigned *out, int outwidth, int outheight)
|
||||
{
|
||||
int i, j;
|
||||
const 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_MipMap
|
||||
|
||||
Operates in place, quartering the size of the texture
|
||||
================
|
||||
*/
|
||||
static 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_Upload32
|
||||
===============
|
||||
*/
|
||||
void
|
||||
GL_Upload32(const unsigned *data, int width, int height, qboolean mipmap,
|
||||
qboolean alpha)
|
||||
static void
|
||||
GL_Upload32(qtexture32_t *texture, qboolean mipmap, qboolean alpha)
|
||||
{
|
||||
int samples;
|
||||
static unsigned scaled[1024 * 512]; // [512*256];
|
||||
int scaled_width, scaled_height;
|
||||
const int format = alpha ? gl_alpha_format : gl_solid_format;
|
||||
qtexture32_t *scaled;
|
||||
int width, height, mark;
|
||||
|
||||
for (scaled_width = 1; scaled_width < width; scaled_width <<= 1);
|
||||
for (scaled_height = 1; scaled_height < height; scaled_height <<= 1);
|
||||
/* find the scaled size */
|
||||
width = 1;
|
||||
while (width < texture->width)
|
||||
width <<= 1;
|
||||
height = 1;
|
||||
while (height < texture->height)
|
||||
height <<= 1;
|
||||
|
||||
scaled_width >>= (int)gl_picmip.value;
|
||||
scaled_height >>= (int)gl_picmip.value;
|
||||
width >>= (int)gl_picmip.value;
|
||||
width = qclamp(width, 1, (int)gl_max_size.value);
|
||||
height >>= (int)gl_picmip.value;
|
||||
height = qclamp(height, 1, (int)gl_max_size.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;
|
||||
mark = Hunk_LowMark();
|
||||
|
||||
if (scaled_width * scaled_height > sizeof(scaled) / 4)
|
||||
Sys_Error("%s: too big", __func__);
|
||||
|
||||
samples = alpha ? gl_alpha_format : gl_solid_format;
|
||||
if (scaled_width == width && scaled_height == height) {
|
||||
if (!mipmap) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, samples, scaled_width,
|
||||
scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
goto done;
|
||||
}
|
||||
memcpy(scaled, data, width * height * 4);
|
||||
} else
|
||||
GL_ResampleTexture(data, width, height, scaled, scaled_width,
|
||||
scaled_height);
|
||||
|
||||
glTexImage2D(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++;
|
||||
glTexImage2D(GL_TEXTURE_2D, miplevel, samples, scaled_width,
|
||||
scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
||||
}
|
||||
if (width != texture->width || height != texture->height) {
|
||||
scaled = QTexture32_Alloc(width, height);
|
||||
QTexture32_Stretch(texture, scaled);
|
||||
} else {
|
||||
scaled = texture;
|
||||
}
|
||||
|
||||
done:
|
||||
if (mipmap) {
|
||||
int miplevel = 0;
|
||||
while (1) {
|
||||
glTexImage2D(GL_TEXTURE_2D, miplevel, format,
|
||||
scaled->width, scaled->height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, scaled->pixels);
|
||||
if (scaled->width == 1 && scaled->height == 1)
|
||||
break;
|
||||
|
||||
QTexture32_MipMap(scaled);
|
||||
miplevel++;
|
||||
}
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format,
|
||||
scaled->width, scaled->height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, scaled->pixels);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
}
|
||||
|
||||
Hunk_FreeToLowMark(mark);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1168,37 +1102,17 @@ void
|
||||
GL_Upload8(const byte *data, int width, int height, qboolean mipmap,
|
||||
qboolean alpha)
|
||||
{
|
||||
static unsigned trans[640 * 480]; // FIXME, temporary
|
||||
int i, s;
|
||||
qboolean noalpha;
|
||||
int p;
|
||||
qtexture32_t *texture;
|
||||
int mark;
|
||||
|
||||
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];
|
||||
}
|
||||
mark = Hunk_LowMark();
|
||||
|
||||
if (alpha && noalpha)
|
||||
alpha = false;
|
||||
} else {
|
||||
if (s & 3)
|
||||
Sys_Error("%s: s&3", __func__);
|
||||
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]];
|
||||
}
|
||||
}
|
||||
texture = QTexture32_Alloc(width, height);
|
||||
QTexture32_8to32(data, width, height, width, alpha, texture);
|
||||
|
||||
GL_Upload32(trans, width, height, mipmap, alpha);
|
||||
GL_Upload32(texture, mipmap, alpha);
|
||||
|
||||
Hunk_FreeToLowMark(mark);
|
||||
}
|
||||
|
||||
/*
|
||||
|
385
common/textures.c
Normal file
385
common/textures.c
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2013 Kevin Shanahan
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "textures.h"
|
||||
#include "vid.h"
|
||||
#include "zone.h"
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/* Texture Format Transformations */
|
||||
/* --------------------------------------------------------------------------*/
|
||||
|
||||
qtexture32_t *
|
||||
QTexture32_Alloc(int width, int height)
|
||||
{
|
||||
const int memsize = offsetof(qtexture32_t, pixels[width * height]);
|
||||
qtexture32_t *texture = Hunk_Alloc(memsize);
|
||||
|
||||
if (texture) {
|
||||
texture->width = width;
|
||||
texture->height = height;
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void
|
||||
QTexture32_8to32(const byte *in, int width, int height, int stride,
|
||||
qboolean alpha, qtexture32_t *out)
|
||||
{
|
||||
qpixel32_t *pixel = out->pixels;
|
||||
int x, y;
|
||||
|
||||
if (alpha) {
|
||||
/* index 0 is a transparent colour */
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++, in++, pixel++)
|
||||
pixel->rgba = (*in) ? d_8to24table[*in] : 0;
|
||||
in += stride - width;
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++, in++, pixel++)
|
||||
pixel->rgba = d_8to24table[*in];
|
||||
in += stride - width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
QTexture32_Stretch
|
||||
TODO - should probably be doing bilinear filtering or something
|
||||
================
|
||||
*/
|
||||
void
|
||||
QTexture32_Stretch(const qtexture32_t *in, qtexture32_t *out)
|
||||
{
|
||||
int i, j;
|
||||
const qpixel32_t *inrow;
|
||||
qpixel32_t *outrow;
|
||||
unsigned frac, fracstep;
|
||||
|
||||
assert(!(out->width & 3));
|
||||
|
||||
fracstep = in->width * 0x10000 / out->width;
|
||||
outrow = out->pixels;
|
||||
for (i = 0; i < out->height; i++, outrow += out->width) {
|
||||
inrow = in->pixels + in->width * (i * in->height / out->height);
|
||||
frac = fracstep >> 1;
|
||||
for (j = 0; j < out->width; j += 4) {
|
||||
outrow[j] = inrow[frac >> 16];
|
||||
frac += fracstep;
|
||||
outrow[j + 1] = inrow[frac >> 16];
|
||||
frac += fracstep;
|
||||
outrow[j + 2] = inrow[frac >> 16];
|
||||
frac += fracstep;
|
||||
outrow[j + 3] = inrow[frac >> 16];
|
||||
frac += fracstep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/* Mipmaps - Handle all variations of even/odd dimensions */
|
||||
/* --------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
QTexture32_MipMap_1D_Even(qpixel32_t *pixels, int length)
|
||||
{
|
||||
const byte *in;
|
||||
byte *out;
|
||||
int i;
|
||||
|
||||
in = out = (byte *)pixels;
|
||||
|
||||
length >>= 1;
|
||||
for (i = 0; i < length; i++, out += 4, in += 8) {
|
||||
out[0] = ((int)in[0] + in[4]) >> 1;
|
||||
out[1] = ((int)in[1] + in[5]) >> 1;
|
||||
out[2] = ((int)in[2] + in[6]) >> 1;
|
||||
out[3] = ((int)in[3] + in[7]) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
QTexture32_MipMap_1D_Odd(qpixel32_t *pixels, int length)
|
||||
{
|
||||
const int inlength = length;
|
||||
const byte *in;
|
||||
byte *out;
|
||||
int i;
|
||||
|
||||
in = out = (byte *)pixels;
|
||||
|
||||
length >>= 1;
|
||||
|
||||
const float w1 = (float)inlength / length;
|
||||
for (i = 0; i < length; i++, out += 4, in += 8) {
|
||||
const float w0 = (float)(i - length) / inlength;
|
||||
const float w2 = (float)(i + 1) / inlength;
|
||||
|
||||
out[0] = w0 * in[0] + w1 * in[4] + w2 * in[8];
|
||||
out[1] = w0 * in[1] + w1 * in[5] + w2 * in[9];
|
||||
out[2] = w0 * in[2] + w1 * in[6] + w2 * in[10];
|
||||
out[3] = w0 * in[3] + w1 * in[7] + w2 * in[11];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
QTexture32_MipMap_EvenEven
|
||||
|
||||
Simple 2x2 box filter for textures with even width/height
|
||||
================
|
||||
*/
|
||||
static void
|
||||
QTexture32_MipMap_EvenEven(qpixel32_t *pixels, int width, int height)
|
||||
{
|
||||
int i, j;
|
||||
byte *in, *out;
|
||||
|
||||
in = out = (byte *)pixels;
|
||||
|
||||
width <<= 2;
|
||||
height >>= 1;
|
||||
for (i = 0; i < height; i++, in += width) {
|
||||
for (j = 0; j < width; j += 8, out += 4, in += 8) {
|
||||
out[0] = ((int)in[0] + in[4] + in[width + 0] + in[width + 4]) >> 2;
|
||||
out[1] = ((int)in[1] + in[5] + in[width + 1] + in[width + 5]) >> 2;
|
||||
out[2] = ((int)in[2] + in[6] + in[width + 2] + in[width + 6]) >> 2;
|
||||
out[3] = ((int)in[3] + in[7] + in[width + 3] + in[width + 7]) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
QTexture32_MipMap_OddOdd
|
||||
|
||||
With two odd dimensions we have a polyphase box filter in two
|
||||
dimensions, taking weighted samples from a 3x3 square in the original
|
||||
texture.
|
||||
================
|
||||
*/
|
||||
static void
|
||||
QTexture32_MipMap_OddOdd(qpixel32_t *pixels, int width, int height)
|
||||
{
|
||||
const int inwidth = width;
|
||||
const int inheight = height;
|
||||
const byte *in;
|
||||
byte *out;
|
||||
int x, y;
|
||||
|
||||
in = out = (byte *)pixels;
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
|
||||
/*
|
||||
* Take weighted samples from a 3x3 square on the original texture.
|
||||
* Weights for the centre pixel work out to be constant.
|
||||
*/
|
||||
const float wy1 = (float)height / inheight;
|
||||
const float wx1 = (float)width / inwidth;
|
||||
|
||||
for (y = 0; y < height; y++, in += inwidth << 2) {
|
||||
const float wy0 = (float)(height - y) / inheight;
|
||||
const float wy2 = (float)(1 + y) / inheight;
|
||||
|
||||
for (x = 0; x < width; x ++, in += 8, out += 4) {
|
||||
const float wx0 = (float)(width - x) / inwidth;
|
||||
const float wx2 = (float)(1 + x) / inwidth;
|
||||
|
||||
/* Set up input row pointers to make things read easier below */
|
||||
const byte *r0 = in;
|
||||
const byte *r1 = in + (inwidth << 2);
|
||||
const byte *r2 = in + (inwidth << 3);
|
||||
|
||||
out[0] =
|
||||
wx0 * wy0 * r0[0] + wx1 * wy0 * r0[4] + wx2 * wy0 * r0[8] +
|
||||
wx0 * wy1 * r1[0] + wx1 * wy1 * r1[4] + wx2 * wy1 * r1[8] +
|
||||
wx0 * wy2 * r2[0] + wx1 * wy2 * r2[4] + wx2 * wy2 * r2[8];
|
||||
out[1] =
|
||||
wx0 * wy0 * r0[1] + wx1 * wy0 * r0[5] + wx2 * wy0 * r0[9] +
|
||||
wx0 * wy1 * r1[1] + wx1 * wy1 * r1[5] + wx2 * wy1 * r1[9] +
|
||||
wx0 * wy2 * r2[1] + wx1 * wy2 * r2[5] + wx2 * wy2 * r2[9];
|
||||
out[2] =
|
||||
wx0 * wy0 * r0[2] + wx1 * wy0 * r0[6] + wx2 * wy0 * r0[10] +
|
||||
wx0 * wy1 * r1[2] + wx1 * wy1 * r1[6] + wx2 * wy1 * r1[10] +
|
||||
wx0 * wy2 * r2[2] + wx1 * wy2 * r2[6] + wx2 * wy2 * r2[10];
|
||||
out[3] =
|
||||
wx0 * wy0 * r0[3] + wx1 * wy0 * r0[7] + wx2 * wy0 * r0[11] +
|
||||
wx0 * wy1 * r1[3] + wx1 * wy1 * r1[7] + wx2 * wy1 * r1[11] +
|
||||
wx0 * wy2 * r2[3] + wx1 * wy2 * r2[7] + wx2 * wy2 * r2[11];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
QTexture32_MipMap_OddEven
|
||||
|
||||
Handle odd width, even height
|
||||
================
|
||||
*/
|
||||
static void
|
||||
QTexture32_MipMap_OddEven(qpixel32_t *pixels, int width, int height)
|
||||
{
|
||||
const int inwidth = width;
|
||||
const byte *in;
|
||||
byte *out;
|
||||
int x, y;
|
||||
|
||||
in = out = (byte *)pixels;
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
|
||||
/*
|
||||
* Take weighted samples from a 3x2 square on the original texture.
|
||||
* Weights for the centre pixels are constant.
|
||||
*/
|
||||
const float wx1 = (float)width / inwidth;
|
||||
for (y = 0; y < height; y++, in += inwidth << 2) {
|
||||
for (x = 0; x < width; x ++, in += 8, out += 4) {
|
||||
const float wx0 = (float)(width - x) / inwidth;
|
||||
const float wx2 = (float)(1 + x) / inwidth;
|
||||
|
||||
/* Set up input row pointers to make things read easier below */
|
||||
const byte *r0 = in;
|
||||
const byte *r1 = in + (inwidth << 2);
|
||||
|
||||
out[0] = 0.5 * (wx0 * r0[0] + wx1 * r0[4] + wx2 * r0[8] +
|
||||
wx0 * r1[0] + wx1 * r1[4] + wx2 * r1[8]);
|
||||
out[1] = 0.5 * (wx0 * r0[1] + wx1 * r0[5] + wx2 * r0[9] +
|
||||
wx0 * r1[1] + wx1 * r1[5] + wx2 * r1[9]);
|
||||
out[2] = 0.5 * (wx0 * r0[2] + wx1 * r0[6] + wx2 * r0[10] +
|
||||
wx0 * r1[2] + wx1 * r1[6] + wx2 * r1[10]);
|
||||
out[3] = 0.5 * (wx0 * r0[3] + wx1 * r0[7] + wx2 * r0[11] +
|
||||
wx0 * r1[3] + wx1 * r1[7] + wx2 * r1[11]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
QTexture32_MipMap_EvenOdd
|
||||
|
||||
Handle even width, odd height
|
||||
================
|
||||
*/
|
||||
static void
|
||||
QTexture32_MipMap_EvenOdd(qpixel32_t *pixels, int width, int height)
|
||||
{
|
||||
const int inwidth = width;
|
||||
const int inheight = height;
|
||||
const byte *in;
|
||||
byte *out;
|
||||
int x, y;
|
||||
|
||||
in = out = (byte *)pixels;
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
|
||||
/*
|
||||
* Take weighted samples from a 2x3 square on the original texture.
|
||||
* Weights for the centre pixels are constant.
|
||||
*/
|
||||
const float wy1 = (float)height / inheight;
|
||||
for (y = 0; y < height; y++, in += inwidth << 2) {
|
||||
const float wy0 = (float)(height - y) / inheight;
|
||||
const float wy2 = (float)(1 + y) / inheight;
|
||||
|
||||
for (x = 0; x < width; x++, in += 8, out += 4) {
|
||||
|
||||
/* Set up input row pointers to make things read easier below */
|
||||
const byte *r0 = in;
|
||||
const byte *r1 = in + (inwidth << 2);
|
||||
const byte *r2 = in + (inwidth << 3);
|
||||
|
||||
out[0] = 0.5 * (wy0 * ((int)r0[0] + r0[4]) +
|
||||
wy1 * ((int)r1[0] + r1[4]) +
|
||||
wy2 * ((int)r2[0] + r2[4]));
|
||||
out[1] = 0.5 * (wy0 * ((int)r0[1] + r0[5]) +
|
||||
wy1 * ((int)r1[1] + r1[5]) +
|
||||
wy2 * ((int)r2[1] + r2[5]));
|
||||
out[2] = 0.5 * (wy0 * ((int)r0[2] + r0[6]) +
|
||||
wy1 * ((int)r1[2] + r1[6]) +
|
||||
wy2 * ((int)r2[2] + r2[6]));
|
||||
out[3] = 0.5 * (wy0 * ((int)r0[3] + r0[7]) +
|
||||
wy1 * ((int)r1[3] + r1[7]) +
|
||||
wy2 * ((int)r2[3] + r2[7]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
QTexture32_MipMap
|
||||
|
||||
Check texture dimensions and call the approriate specialized mipmap function
|
||||
================
|
||||
*/
|
||||
void
|
||||
QTexture32_MipMap(qtexture32_t *in)
|
||||
{
|
||||
assert(in->width > 1 || in->height > 1);
|
||||
|
||||
if (in->width == 1) {
|
||||
if (in->height & 1)
|
||||
QTexture32_MipMap_1D_Odd(in->pixels, in->height);
|
||||
else
|
||||
QTexture32_MipMap_1D_Even(in->pixels, in->height);
|
||||
|
||||
in->height >>= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (in->height == 1) {
|
||||
if (in->width & 1)
|
||||
QTexture32_MipMap_1D_Odd(in->pixels, in->width);
|
||||
else
|
||||
QTexture32_MipMap_1D_Even(in->pixels, in->width);
|
||||
|
||||
in->width >>= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (in->width & 1) {
|
||||
if (in->height & 1)
|
||||
QTexture32_MipMap_OddOdd(in->pixels, in->width, in->height);
|
||||
else
|
||||
QTexture32_MipMap_OddEven(in->pixels, in->width, in->height);
|
||||
} else if (in->height & 1) {
|
||||
QTexture32_MipMap_EvenOdd(in->pixels, in->width, in->height);
|
||||
} else {
|
||||
QTexture32_MipMap_EvenEven(in->pixels, in->width, in->height);
|
||||
}
|
||||
|
||||
in->width >>= 1;
|
||||
in->height >>= 1;
|
||||
}
|
@ -59,8 +59,6 @@ extern unsigned char d_15to8table[65536];
|
||||
|
||||
extern float gldepthmin, gldepthmax;
|
||||
|
||||
void GL_Upload32(const unsigned *data, int width, int height,
|
||||
qboolean mipmap, qboolean alpha);
|
||||
void GL_Upload8(const byte *data, int width, int height,
|
||||
qboolean mipmap, qboolean alpha);
|
||||
int GL_LoadTexture(const char *identifier, int width, int height,
|
||||
|
56
include/textures.h
Normal file
56
include/textures.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2013 Kevin Shanahan and others
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TEXTURES_H
|
||||
#define TEXTURES_H
|
||||
|
||||
#include "qtypes.h"
|
||||
|
||||
typedef union {
|
||||
uint32_t rgba;
|
||||
struct {
|
||||
byte red;
|
||||
byte green;
|
||||
byte blue;
|
||||
byte alpha;
|
||||
};
|
||||
} qpixel32_t;
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
qpixel32_t pixels[];
|
||||
} qtexture32_t;
|
||||
|
||||
/* Allocate hunk space for a texture */
|
||||
qtexture32_t *QTexture32_Alloc(int width, int height);
|
||||
|
||||
/* Create 32 bit texture from 8 bit source */
|
||||
void QTexture32_8to32(const byte *in, int width, int height, int stride,
|
||||
qboolean alpha, qtexture32_t *out);
|
||||
|
||||
/* Stretch from in size to out size */
|
||||
void QTexture32_Stretch(const qtexture32_t *in, qtexture32_t *out);
|
||||
|
||||
/* Shrink texture in place to next mipmap level */
|
||||
void QTexture32_MipMap(qtexture32_t *in);
|
||||
|
||||
#endif /* TEXTURES_H */
|
Loading…
Reference in New Issue
Block a user