- memcpy(out, row1, outwidth3);
- }
- }
- }
- else
- {
- int i, j, f, inwidth3 = inwidth * 3;
- unsigned frac, fracstep;
- byte *inrow, *out;
- out = outdata;
-
- fracstep = inwidth*0x10000/outwidth;
- for (i = 0;i < outheight;i++)
- {
- inrow = (byte *)indata + inwidth3*(i*inheight/outheight);
- frac = fracstep >> 1;
- j = outwidth - 4;
- while (j >= 0)
- {
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- j -= 4;
- }
- if (j & 2)
- {
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- out += 2;
- }
- if (j & 1)
- {
- f = (frac >> 16)*3;*out++ = inrow[f+0];*out++ = inrow[f+1];*out++ = inrow[f+2];frac += fracstep;
- out += 1;
- }
- }
- }
- }
- else
- Sys_Error("R_ResampleTexture: unsupported bytesperpixel %i\n", bytesperpixel);
-#undef row1
-#undef row2
-}
-
-// in can be the same as out
-static void R_MipReduce(byte *in, byte *out, int *width, int *height, int destwidth, int destheight, int bytesperpixel)
-{
- int x, y, nextrow;
- nextrow = *width * bytesperpixel;
- if (*width > destwidth)
- {
- *width >>= 1;
- if (*height > destheight)
- {
- // reduce both
- *height >>= 1;
- if (bytesperpixel == 4)
- {
- for (y = 0;y < *height;y++)
- {
- for (x = 0;x < *width;x++)
- {
- out[0] = (byte) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
- out[1] = (byte) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
- out[2] = (byte) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
- out[3] = (byte) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
- out += 4;
- in += 8;
- }
- in += nextrow; // skip a line
- }
- }
- else if (bytesperpixel == 3)
- {
- for (y = 0;y < *height;y++)
- {
- for (x = 0;x < *width;x++)
- {
- out[0] = (byte) ((in[0] + in[3] + in[nextrow ] + in[nextrow+3]) >> 2);
- out[1] = (byte) ((in[1] + in[4] + in[nextrow+1] + in[nextrow+4]) >> 2);
- out[2] = (byte) ((in[2] + in[5] + in[nextrow+2] + in[nextrow+5]) >> 2);
- out += 3;
- in += 6;
- }
- in += nextrow; // skip a line
- }
- }
- else
- Sys_Error("R_MipReduce: unsupported bytesperpixel %i\n", bytesperpixel);
- }
- else
- {
- // reduce width
- if (bytesperpixel == 4)
- {
- for (y = 0;y < *height;y++)
- {
- for (x = 0;x < *width;x++)
- {
- out[0] = (byte) ((in[0] + in[4]) >> 1);
- out[1] = (byte) ((in[1] + in[5]) >> 1);
- out[2] = (byte) ((in[2] + in[6]) >> 1);
- out[3] = (byte) ((in[3] + in[7]) >> 1);
- out += 4;
- in += 8;
- }
- }
- }
- else if (bytesperpixel == 3)
- {
- for (y = 0;y < *height;y++)
- {
- for (x = 0;x < *width;x++)
- {
- out[0] = (byte) ((in[0] + in[3]) >> 1);
- out[1] = (byte) ((in[1] + in[4]) >> 1);
- out[2] = (byte) ((in[2] + in[5]) >> 1);
- out += 3;
- in += 6;
- }
- }
- }
- else
- Sys_Error("R_MipReduce: unsupported bytesperpixel %i\n", bytesperpixel);
- }
- }
- else
- {
- if (*height > destheight)
- {
- // reduce height
- *height >>= 1;
- if (bytesperpixel == 4)
- {
- for (y = 0;y < *height;y++)
- {
- for (x = 0;x < *width;x++)
- {
- out[0] = (byte) ((in[0] + in[nextrow ]) >> 1);
- out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
- out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
- out[3] = (byte) ((in[3] + in[nextrow+3]) >> 1);
- out += 4;
- in += 4;
- }
- in += nextrow; // skip a line
- }
- }
- else if (bytesperpixel == 3)
- {
- for (y = 0;y < *height;y++)
- {
- for (x = 0;x < *width;x++)
- {
- out[0] = (byte) ((in[0] + in[nextrow ]) >> 1);
- out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
- out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
- out += 3;
- in += 3;
- }
- in += nextrow; // skip a line
- }
- }
- else
- Sys_Error("R_MipReduce: unsupported bytesperpixel %i\n", bytesperpixel);
- }
- else
- Sys_Error("R_MipReduce: desired size already achieved\n");
- }
-}
-
-static void R_Upload(gltexture_t *glt, byte *data)
-{
- int mip, width, height, internalformat;
- byte *prevbuffer;
- prevbuffer = data;
-
- glBindTexture(GL_TEXTURE_2D, glt->image->texnum);
- CHECKGLERROR
-
- glt->flags &= ~GLTEXF_UPLOAD;
-
- if (glt->flags & TEXF_FRAGMENT)
- {
- if (resizebuffersize < glt->image->width * glt->image->height * glt->image->bytesperpixel)
- {
- resizebuffersize = glt->image->width * glt->image->height * glt->image->bytesperpixel;
- if (resizebuffer)
- Mem_Free(resizebuffer);
- if (colorconvertbuffer)
- Mem_Free(colorconvertbuffer);
- resizebuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
- colorconvertbuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
- if (!resizebuffer || !colorconvertbuffer)
- Host_Error("R_Upload: out of memory\n");
- }
-
- if (glt->image->flags & GLTEXF_UPLOAD)
- {
- Con_DPrintf("uploaded new fragments image\n");
- glt->image->flags &= ~GLTEXF_UPLOAD;
- memset(resizebuffer, 255, glt->image->width * glt->image->height * glt->image->bytesperpixel);
- glTexImage2D (GL_TEXTURE_2D, 0, glt->image->glinternalformat, glt->image->width, glt->image->height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
- CHECKGLERROR
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
-
- if (prevbuffer == NULL)
- {
- memset(resizebuffer, 255, glt->width * glt->height * glt->image->bytesperpixel);
- prevbuffer = resizebuffer;
- }
- else if (glt->textype->textype == TEXTYPE_QPALETTE)
- {
- // promote paletted to RGBA, so we only have to worry about RGB and
- // RGBA in the rest of this code
- Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height, d_8to24table);
- prevbuffer = colorconvertbuffer;
- }
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, glt->x, glt->y, glt->width, glt->height, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
- CHECKGLERROR
- return;
- }
-
- glt->image->flags &= ~GLTEXF_UPLOAD;
-
- // these are rounded up versions of the size to do better resampling
- for (width = 1;width < glt->width;width <<= 1);
- for (height = 1;height < glt->height;height <<= 1);
-
- if (resizebuffersize < width * height * glt->image->bytesperpixel)
- {
- resizebuffersize = width * height * glt->image->bytesperpixel;
- if (resizebuffer)
- Mem_Free(resizebuffer);
- if (colorconvertbuffer)
- Mem_Free(colorconvertbuffer);
- resizebuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
- colorconvertbuffer = Mem_Alloc(textureprocessingmempool, resizebuffersize);
- if (!resizebuffer || !colorconvertbuffer)
- Host_Error("R_Upload: out of memory\n");
- }
-
- if (prevbuffer == NULL)
- {
- width = glt->image->width;
- height = glt->image->height;
- memset(resizebuffer, 255, width * height * glt->image->bytesperpixel);
- prevbuffer = resizebuffer;
- }
- else
- {
- if (glt->textype->textype == TEXTYPE_QPALETTE)
- {
- // promote paletted to RGBA, so we only have to worry about RGB and
- // RGBA in the rest of this code
- Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height, d_8to24table);
- prevbuffer = colorconvertbuffer;
- }
-
- if (glt->width != width || glt->height != height)
- {
- R_ResampleTexture(prevbuffer, glt->width, glt->height, resizebuffer, width, height, glt->image->bytesperpixel);
- prevbuffer = resizebuffer;
- }
-
- // apply picmip/max_size limitations
- while (width > glt->image->width || height > glt->image->height)
- {
- R_MipReduce(prevbuffer, resizebuffer, &width, &height, glt->image->width, glt->image->height, glt->image->bytesperpixel);
- prevbuffer = resizebuffer;
- }
- }
-
- // 3 and 4 are converted by the driver to it's preferred format for the current display mode
- internalformat = 3;
- if (glt->flags & TEXF_ALPHA)
- internalformat = 4;
-
- mip = 0;
- glTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
- CHECKGLERROR
- if (glt->flags & TEXF_MIPMAP)
- {
- while (width > 1 || height > 1)
- {
- R_MipReduce(prevbuffer, resizebuffer, &width, &height, 1, 1, glt->image->bytesperpixel);
- prevbuffer = resizebuffer;
-
- glTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
- CHECKGLERROR
- }
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- CHECKGLERROR
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
- else
- {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
-}
-
-static void R_FindImageForTexture(gltexture_t *glt)
-{
- int i, j, best, best2, x, y, w, h;
- textypeinfo_t *texinfo;
- gltexturepool_t *pool;
- gltextureimage_t *image, **imagechainpointer;
- texinfo = glt->textype;
- pool = glt->pool;
-
- x = 0;
- y = 0;
- w = glt->width;
- h = glt->height;
- if (glt->flags & TEXF_FRAGMENT)
- {
- for (imagechainpointer = &pool->imagechain;*imagechainpointer;imagechainpointer = &(*imagechainpointer)->imagechain)
- {
- image = *imagechainpointer;
- if (image->type != GLIMAGETYPE_FRAGMENTS)
- continue;
- if (image->glformat != texinfo->glformat || image->glinternalformat != texinfo->glinternalformat)
- continue;
-
- // got a fragments texture, find a place in it if we can
- best = block_size;
- for (best = block_size, i = 0;i < block_size - w;i += texinfo->align)
- {
- for (best2 = 0, j = 0;j < w;j++)
- {
- if (image->blockallocation[i+j] >= best)
- break;
- if (best2 < image->blockallocation[i+j])
- best2 = image->blockallocation[i+j];
- }
- if (j == w)
- {
- // this is a valid spot
- x = i;
- y = best = best2;