+ qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ if (!(glt->flags & TEXF_RENDERTARGET))
+ {
+ D3DLOCKED_RECT d3dlockedrect;
+ D3DLOCKED_BOX d3dlockedbox;
+ switch(glt->texturetype)
+ {
+ case GLTEXTURETYPE_2D:
+ if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
+ {
+ if (prevbuffer)
+ memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
+ else
+ memset(d3dlockedrect.pBits, 255, width*height*glt->bytesperpixel);
+ IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
+ }
+ mip++;
+ if ((glt->flags & TEXF_MIPMAP) && prevbuffer)
+ {
+ while (width > 1 || height > 1 || depth > 1)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
+ prevbuffer = resizebuffer;
+ if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
+ {
+ memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
+ IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
+ }
+ mip++;
+ }
+ }
+ break;
+ case GLTEXTURETYPE_3D:
+ if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
+ {
+ // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
+ memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
+ IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
+ }
+ mip++;
+ if (glt->flags & TEXF_MIPMAP)
+ {
+ while (width > 1 || height > 1 || depth > 1)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
+ prevbuffer = resizebuffer;
+ if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
+ {
+ // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
+ memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
+ IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
+ }
+ mip++;
+ }
+ }
+ break;
+ case GLTEXTURETYPE_CUBEMAP:
+ // convert and upload each side in turn,
+ // from a continuous block of input texels
+ texturebuffer = (unsigned char *)prevbuffer;
+ for (i = 0;i < 6;i++)
+ {
+ prevbuffer = texturebuffer;
+ texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
+ if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
+ {
+ Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
+ prevbuffer = resizebuffer;
+ }
+ // picmip/max_size
+ while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
+ prevbuffer = resizebuffer;
+ }
+ mip = 0;
+ if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
+ {
+ memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
+ IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
+ }
+ mip++;
+ if (glt->flags & TEXF_MIPMAP)
+ {
+ while (width > 1 || height > 1 || depth > 1)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
+ prevbuffer = resizebuffer;
+ if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
+ {
+ memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
+ IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
+ }
+ mip++;
+ }
+ }
+ }
+ break;
+ }
+ }
+ glt->d3daddressw = 0;
+ if (glt->flags & TEXF_CLAMP)
+ {
+ glt->d3daddressu = D3DTADDRESS_CLAMP;
+ glt->d3daddressv = D3DTADDRESS_CLAMP;
+ if (glt->tiledepth > 1)
+ glt->d3daddressw = D3DTADDRESS_CLAMP;
+ }
+ else
+ {
+ glt->d3daddressu = D3DTADDRESS_WRAP;
+ glt->d3daddressv = D3DTADDRESS_WRAP;
+ if (glt->tiledepth > 1)
+ glt->d3daddressw = D3DTADDRESS_WRAP;
+ }
+ glt->d3dmipmaplodbias = 0;
+ glt->d3dmaxmiplevel = 0;
+ glt->d3dmaxmiplevelfilter = d3d_filter_nomip ? 0 : glt->d3dmaxmiplevel;
+ if (glt->flags & TEXF_FORCELINEAR)
+ {
+ glt->d3dminfilter = D3DTEXF_LINEAR;
+ glt->d3dmagfilter = D3DTEXF_LINEAR;
+ glt->d3dmipfilter = D3DTEXF_POINT;
+ }
+ else if (glt->flags & TEXF_FORCENEAREST)
+ {
+ glt->d3dminfilter = D3DTEXF_POINT;
+ glt->d3dmagfilter = D3DTEXF_POINT;
+ glt->d3dmipfilter = D3DTEXF_POINT;
+ }
+ else if (glt->flags & TEXF_MIPMAP)
+ {
+ glt->d3dminfilter = d3d_filter_mipmin;
+ glt->d3dmagfilter = d3d_filter_mipmag;
+ glt->d3dmipfilter = d3d_filter_mipmix;
+ }
+ else
+ {
+ glt->d3dminfilter = d3d_filter_flatmin;
+ glt->d3dmagfilter = d3d_filter_flatmag;
+ glt->d3dmipfilter = d3d_filter_flatmix;
+ }
+#endif
+ break;
+ case RENDERPATH_D3D10:
+ Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ case RENDERPATH_D3D11:
+ Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ case RENDERPATH_SOFT:
+ switch(glt->texturetype)
+ {
+ case GLTEXTURETYPE_2D:
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
+ break;
+ case GLTEXTURETYPE_3D:
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
+ break;
+ case GLTEXTURETYPE_CUBEMAP:
+ if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
+ {
+ unsigned char *combinedbuffer = (unsigned char *)Mem_Alloc(tempmempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
+ // convert and upload each side in turn,
+ // from a continuous block of input texels
+ // copy the results into combinedbuffer
+ texturebuffer = (unsigned char *)prevbuffer;
+ for (i = 0;i < 6;i++)
+ {
+ prevbuffer = texturebuffer;
+ texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
+ if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
+ {
+ Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
+ prevbuffer = resizebuffer;
+ }
+ // picmip/max_size
+ while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
+ prevbuffer = resizebuffer;
+ }
+ memcpy(combinedbuffer + i*glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel, prevbuffer, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel);
+ }
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, combinedbuffer);
+ Mem_Free(combinedbuffer);
+ }
+ else
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
+ break;
+ }
+ if (glt->flags & TEXF_FORCELINEAR)
+ DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
+ else if (glt->flags & TEXF_FORCENEAREST)
+ DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
+ else if (glt->flags & TEXF_MIPMAP)
+ DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
+ else
+ DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
+ break;
+ }
+}
+
+static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, int sides, int flags, int miplevel, textype_t textype, int texturetype, const unsigned char *data, const unsigned int *palette)
+{
+ int i, size;
+ gltexture_t *glt;
+ gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
+ textypeinfo_t *texinfo, *texinfo2;
+ unsigned char *temppixels = NULL;
+ qboolean swaprb;
+
+ if (cls.state == ca_dedicated)
+ return NULL;
+
+ // see if we need to swap red and blue (BGRA <-> RGBA conversion)
+ swaprb = false;
+ switch(textype)
+ {
+ case TEXTYPE_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_BGRA;} break;
+ case TEXTYPE_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_RGBA;} break;
+ case TEXTYPE_SRGB_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_SRGB_BGRA;} break;
+ case TEXTYPE_SRGB_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_SRGB_RGBA;} break;
+ default: break;
+ }
+ if (swaprb)
+ {
+ // swap bytes
+ static int rgbaswapindices[4] = {2, 1, 0, 3};
+ size = width * height * depth * sides * 4;
+ temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
+ Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
+ data = temppixels;
+ }
+
+ // if sRGB texture formats are not supported, convert input to linear and upload as normal types
+ if (!vid.support.ext_texture_srgb)
+ {
+ qboolean convertsRGB = false;
+ switch(textype)
+ {
+ case TEXTYPE_SRGB_DXT1: textype = TEXTYPE_DXT1 ;convertsRGB = true;break;
+ case TEXTYPE_SRGB_DXT1A: textype = TEXTYPE_DXT1A ;convertsRGB = true;break;
+ case TEXTYPE_SRGB_DXT3: textype = TEXTYPE_DXT3 ;convertsRGB = true;break;
+ case TEXTYPE_SRGB_DXT5: textype = TEXTYPE_DXT5 ;convertsRGB = true;break;
+ case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;convertsRGB = true;break;
+ case TEXTYPE_SRGB_RGBA: textype = TEXTYPE_RGBA ;convertsRGB = true;break;
+ case TEXTYPE_SRGB_BGRA: textype = TEXTYPE_BGRA ;convertsRGB = true;break;
+ default:
+ break;
+ }
+ if (convertsRGB && data)
+ {
+ size = width * height * depth * sides * 4;
+ if (!temppixels)
+ {
+ temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
+ memcpy(temppixels, data, size);
+ }
+ Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides);
+ }
+ }
+
+ if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
+ {
+ Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
+ return NULL;
+ }
+ if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d)
+ {
+ Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n");
+ return NULL;
+ }
+
+ texinfo = R_GetTexTypeInfo(textype, flags);
+ size = width * height * depth * sides * texinfo->inputbytesperpixel;
+ if (size < 1)
+ {
+ Con_Printf ("R_LoadTexture: bogus texture size (%dx%dx%dx%dbppx%dsides = %d bytes)\n", width, height, depth, texinfo->inputbytesperpixel * 8, sides, size);
+ return NULL;
+ }
+
+ // clear the alpha flag if the texture has no transparent pixels
+ switch(textype)