Commit 37618206 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

d3dx9: Handle compressed surfaces in D3DXLoadSurfaceFromMemory.

parent 1f9243c7
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -78,7 +78,7 @@ extern const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl DECLSPEC_HIDDEN ...@@ -78,7 +78,7 @@ extern const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl DECLSPEC_HIDDEN
static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *format) static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *format)
{ {
if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16 if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16
|| format->type == FORMAT_ARGBF) || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT)
return TRUE; return TRUE;
return !!format->to_rgba; return !!format->to_rgba;
} }
...@@ -86,7 +86,7 @@ static inline BOOL is_conversion_from_supported(const struct pixel_format_desc * ...@@ -86,7 +86,7 @@ static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *
static inline BOOL is_conversion_to_supported(const struct pixel_format_desc *format) static inline BOOL is_conversion_to_supported(const struct pixel_format_desc *format)
{ {
if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16 if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16
|| format->type == FORMAT_ARGBF) || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT)
return TRUE; return TRUE;
return !!format->from_rgba; return !!format->from_rgba;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "ole2.h" #include "ole2.h"
#include "wincodec.h" #include "wincodec.h"
#include "txc_dxtn.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3dx); WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**); HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
...@@ -1927,6 +1929,11 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, ...@@ -1927,6 +1929,11 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
} }
else /* Stretching or format conversion. */ else /* Stretching or format conversion. */
{ {
const struct pixel_format_desc *dst_format;
DWORD *src_uncompressed = NULL;
unsigned int dst_pitch;
BYTE *dst_mem;
if (!is_conversion_from_supported(srcformatdesc) if (!is_conversion_from_supported(srcformatdesc)
|| !is_conversion_to_supported(destformatdesc)) || !is_conversion_to_supported(destformatdesc))
{ {
...@@ -1935,10 +1942,76 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, ...@@ -1935,10 +1942,76 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
return E_NOTIMPL; return E_NOTIMPL;
} }
if (srcformatdesc->type == FORMAT_DXT)
{
void (*fetch_dxt_texel)(int srcRowStride, const BYTE *pixdata,
int i, int j, void *texel);
unsigned int x, y;
src_uncompressed = heap_alloc(src_size.width * src_size.height * sizeof(DWORD));
if (!src_uncompressed)
{
unlock_surface(dst_surface, dst_rect, surface, FALSE);
return E_OUTOFMEMORY;
}
switch(src_format)
{
case D3DFMT_DXT1:
fetch_dxt_texel = fetch_2d_texel_rgba_dxt1;
break;
case D3DFMT_DXT2:
case D3DFMT_DXT3:
fetch_dxt_texel = fetch_2d_texel_rgba_dxt3;
break;
case D3DFMT_DXT4:
case D3DFMT_DXT5:
fetch_dxt_texel = fetch_2d_texel_rgba_dxt5;
break;
default:
FIXME("Unexpected compressed texture format %u.\n", src_format);
fetch_dxt_texel = NULL;
}
TRACE("Uncompressing DXTn surface.\n");
for (y = 0; y < src_size.height; ++y)
{
DWORD *ptr = &src_uncompressed[y * src_size.width];
for (x = 0; x < src_size.width; ++x)
{
fetch_dxt_texel(src_pitch / sizeof(DWORD), src_memory,
x + src_rect->left, y + src_rect->top, ptr);
++ptr;
}
}
src_memory = src_uncompressed;
src_pitch = src_size.width * sizeof(DWORD);
srcformatdesc = get_format_info(D3DFMT_A8B8G8R8);
}
if (destformatdesc->type == FORMAT_DXT)
{
dst_mem = heap_alloc(dst_size.width * dst_size.height * sizeof(DWORD));
if (!dst_mem)
{
heap_free(src_uncompressed);
unlock_surface(dst_surface, dst_rect, surface, FALSE);
return E_OUTOFMEMORY;
}
dst_pitch = dst_size.width * sizeof(DWORD);
dst_format = get_format_info(D3DFMT_A8B8G8R8);
}
else
{
dst_mem = lockrect.pBits;
dst_pitch = lockrect.Pitch;
dst_format = destformatdesc;
}
if ((filter & 0xf) == D3DX_FILTER_NONE) if ((filter & 0xf) == D3DX_FILTER_NONE)
{ {
convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc, convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette); dst_mem, dst_pitch, 0, &dst_size, dst_format, color_key, src_palette);
} }
else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
{ {
...@@ -1948,7 +2021,42 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, ...@@ -1948,7 +2021,42 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
/* Always apply a point filter until D3DX_FILTER_LINEAR, /* Always apply a point filter until D3DX_FILTER_LINEAR,
* D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */ * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc, point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette); dst_mem, dst_pitch, 0, &dst_size, dst_format, color_key, src_palette);
}
heap_free(src_uncompressed);
if (destformatdesc->type == FORMAT_DXT)
{
if (dst_rect && (dst_rect->left || dst_rect->top))
{
FIXME("Not implemented for destination rect left / top != 0.\n");
}
else
{
GLenum gl_format = 0;
TRACE("Compressing DXTn surface.\n");
switch(surfdesc.Format)
{
case D3DFMT_DXT1:
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case D3DFMT_DXT2:
case D3DFMT_DXT3:
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case D3DFMT_DXT4:
case D3DFMT_DXT5:
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
default:
ERR("Unexpected destination compressed format %u.\n", surfdesc.Format);
}
tx_compress_dxtn(4, dst_size.width, dst_size.height,
dst_mem, gl_format, lockrect.pBits, lockrect.Pitch);
}
heap_free(dst_mem);
} }
} }
......
...@@ -183,24 +183,30 @@ HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture, ...@@ -183,24 +183,30 @@ HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture,
} }
} }
static D3DFORMAT get_luminance_replacement_format(D3DFORMAT format) static D3DFORMAT get_replacement_format(D3DFORMAT format)
{ {
static const struct static const struct
{ {
D3DFORMAT luminance_format; D3DFORMAT format;
D3DFORMAT replacement_format; D3DFORMAT replacement_format;
} luminance_replacements[] = }
replacements[] =
{ {
{D3DFMT_L8, D3DFMT_X8R8G8B8}, {D3DFMT_L8, D3DFMT_X8R8G8B8},
{D3DFMT_A8L8, D3DFMT_A8R8G8B8}, {D3DFMT_A8L8, D3DFMT_A8R8G8B8},
{D3DFMT_A4L4, D3DFMT_A4R4G4B4}, {D3DFMT_A4L4, D3DFMT_A4R4G4B4},
{D3DFMT_L16, D3DFMT_A16B16G16R16} {D3DFMT_L16, D3DFMT_A16B16G16R16},
{D3DFMT_DXT1, D3DFMT_A8R8G8B8},
{D3DFMT_DXT2, D3DFMT_A8R8G8B8},
{D3DFMT_DXT3, D3DFMT_A8R8G8B8},
{D3DFMT_DXT4, D3DFMT_A8R8G8B8},
{D3DFMT_DXT5, D3DFMT_A8R8G8B8},
}; };
unsigned int i; unsigned int i;
for (i = 0; i < ARRAY_SIZE(luminance_replacements); ++i) for (i = 0; i < ARRAY_SIZE(replacements); ++i)
if (format == luminance_replacements[i].luminance_format) if (format == replacements[i].format)
return luminance_replacements[i].replacement_format; return replacements[i].replacement_format;
return format; return format;
} }
...@@ -275,7 +281,7 @@ HRESULT WINAPI D3DXCheckTextureRequirements(struct IDirect3DDevice9 *device, UIN ...@@ -275,7 +281,7 @@ HRESULT WINAPI D3DXCheckTextureRequirements(struct IDirect3DDevice9 *device, UIN
FIXME("Pixel format %x not handled\n", usedformat); FIXME("Pixel format %x not handled\n", usedformat);
goto cleanup; goto cleanup;
} }
fmt = get_format_info(get_luminance_replacement_format(usedformat)); fmt = get_format_info(get_replacement_format(usedformat));
allow_24bits = fmt->bytes_per_pixel == 3; allow_24bits = fmt->bytes_per_pixel == 3;
channels = !!fmt->bits[0] + !!fmt->bits[1] + !!fmt->bits[2] + !!fmt->bits[3]; channels = !!fmt->bits[0] + !!fmt->bits[1] + !!fmt->bits[2] + !!fmt->bits[3];
...@@ -564,12 +570,12 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi ...@@ -564,12 +570,12 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo, D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
PALETTEENTRY *palette, struct IDirect3DTexture9 **texture) PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
{ {
BOOL dynamic_texture, format_specified = FALSE;
unsigned int loaded_miplevels, skip_levels;
IDirect3DSurface9 *surface;
IDirect3DTexture9 **texptr; IDirect3DTexture9 **texptr;
IDirect3DTexture9 *buftex; IDirect3DTexture9 *buftex;
IDirect3DSurface9 *surface;
BOOL dynamic_texture, format_specified = FALSE;
D3DXIMAGE_INFO imginfo; D3DXIMAGE_INFO imginfo;
UINT loaded_miplevels, skip_levels;
D3DCAPS9 caps; D3DCAPS9 caps;
HRESULT hr; HRESULT hr;
...@@ -656,15 +662,10 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi ...@@ -656,15 +662,10 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
if (colorkey && !format_specified) if (colorkey && !format_specified)
format = get_alpha_replacement_format(format); format = get_alpha_replacement_format(format);
if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
{
FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet.\n");
miplevels = imginfo.MipLevels;
}
if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE
&& D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1) && D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1)
{ {
FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet.\n"); FIXME("Generation of mipmaps for compressed volume textures is not implemented yet.\n");
miplevels = 1; miplevels = 1;
} }
...@@ -1475,12 +1476,6 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, ...@@ -1475,12 +1476,6 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
if (FAILED(hr)) if (FAILED(hr))
return D3DERR_INVALIDCALL; return D3DERR_INVALIDCALL;
if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
{
FIXME("Generation of mipmaps for compressed pixel formats is not supported yet.\n");
mip_levels = img_info.MipLevels;
}
dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC); dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
if (pool == D3DPOOL_DEFAULT && !dynamic_texture) if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
{ {
......
/*
* libtxc_dxtn
* Version: 1.0
*
* Copyright (C) 2004 Roland Scheidegger All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _TXC_DXTN_H
#define _TXC_DXTN_H
#include "winternl.h"
#include "wine/wgl.h"
typedef GLubyte GLchan;
#define UBYTE_TO_CHAN(b) (b)
#define CHAN_MAX 255
#define RCOMP 0
#define GCOMP 1
#define BCOMP 2
#define ACOMP 3
void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel);
void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel);
void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel);
void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel);
void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
const GLubyte *srcPixData, GLenum destformat,
GLubyte *dest, GLint dstRowStride);
#endif /* _TXC_DXTN_H */
/*
* libtxc_dxtn
* Version: 1.0
*
* Copyright (C) 2004 Roland Scheidegger All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include "txc_dxtn.h"
#define EXP5TO8R(packedcol) \
((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7))
#define EXP6TO8G(packedcol) \
((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3))
#define EXP5TO8B(packedcol) \
((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7))
#define EXP4TO8(col) \
((col) | ((col) << 4))
/* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */
static void dxt135_decode_imageblock ( const GLubyte *img_block_src,
GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) {
GLchan *rgba = (GLchan *) texel;
const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8);
const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8);
const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) |
(img_block_src[6] << 16) | (img_block_src[7] << 24);
/* What about big/little endian? */
GLubyte bit_pos = 2 * (j * 4 + i) ;
GLubyte code = (GLubyte) ((bits >> bit_pos) & 3);
rgba[ACOMP] = CHAN_MAX;
switch (code) {
case 0:
rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) );
rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) );
rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) );
break;
case 1:
rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) );
rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) );
rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) );
break;
case 2:
if ((dxt_type > 1) || (color0 > color1)) {
rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) );
rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) );
rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) );
}
else {
rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) );
rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) );
rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) );
}
break;
case 3:
if ((dxt_type > 1) || (color0 > color1)) {
rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) );
rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) );
rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) );
}
else {
rgba[RCOMP] = 0;
rgba[GCOMP] = 0;
rgba[BCOMP] = 0;
if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0);
}
break;
default:
/* CANNOT happen (I hope) */
break;
}
}
void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel)
{
/* Extract the (i,j) pixel from pixdata and return it
* in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
*/
const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel);
}
void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel)
{
/* Extract the (i,j) pixel from pixdata and return it
* in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
*/
const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel);
}
void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel) {
/* Extract the (i,j) pixel from pixdata and return it
* in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
*/
GLchan *rgba = (GLchan *) texel;
const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
#if 0
/* Simple 32bit version. */
/* that's pretty brain-dead for a single pixel, isn't it? */
const GLubyte bit_pos = 4 * ((j&3) * 4 + (i&3));
const GLuint alpha_low = blksrc[0] | (blksrc[1] << 8) | (blksrc[2] << 16) | (blksrc[3] << 24);
const GLuint alpha_high = blksrc[4] | (blksrc[5] << 8) | (blksrc[6] << 16) | (blksrc[7] << 24);
dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
if (bit_pos < 32)
rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8((alpha_low >> bit_pos) & 15)) );
else
rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8((alpha_high >> (bit_pos - 32)) & 15)) );
#endif
#if 1
/* TODO test this! */
const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf;
dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) );
#endif
}
void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
GLint i, GLint j, GLvoid *texel) {
/* Extract the (i,j) pixel from pixdata and return it
* in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
*/
GLchan *rgba = (GLchan *) texel;
const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
const GLubyte alpha0 = blksrc[0];
const GLubyte alpha1 = blksrc[1];
#if 0
const GLubyte bit_pos = 3 * ((j&3) * 4 + (i&3));
/* simple 32bit version */
const GLuint bits_low = blksrc[2] | (blksrc[3] << 8) | (blksrc[4] << 16) | (blksrc[5] << 24);
const GLuint bits_high = blksrc[6] | (blksrc[7] << 8);
GLubyte code;
if (bit_pos < 30)
code = (GLubyte) ((bits_low >> bit_pos) & 7);
else if (bit_pos == 30)
code = (GLubyte) ((bits_low >> 30) & 3) | ((bits_high << 2) & 4);
else
code = (GLubyte) ((bits_high >> (bit_pos - 32)) & 7);
#endif
#if 1
/* TODO test this! */
const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3;
const GLubyte acodelow = blksrc[2 + bit_pos / 8];
const GLubyte acodehigh = blksrc[3 + bit_pos / 8];
const GLubyte code = (acodelow >> (bit_pos & 0x7) |
(acodehigh << (8 - (bit_pos & 0x7)))) & 0x7;
#endif
dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
#if 0
if (alpha0 > alpha1) {
switch (code) {
case 0:
rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 );
break;
case 1:
rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 );
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) );
break;
}
}
else {
switch (code) {
case 0:
rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 );
break;
case 1:
rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 );
break;
case 2:
case 3:
case 4:
case 5:
rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) );
break;
case 6:
rgba[ACOMP] = 0;
break;
case 7:
rgba[ACOMP] = CHAN_MAX;
break;
}
}
#endif
/* not sure. Which version is faster? */
#if 1
/* TODO test this */
if (code == 0)
rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 );
else if (code == 1)
rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 );
else if (alpha0 > alpha1)
rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) );
else if (code < 6)
rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) );
else if (code == 6)
rgba[ACOMP] = 0;
else
rgba[ACOMP] = CHAN_MAX;
#endif
}
...@@ -185,7 +185,6 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, ...@@ -185,7 +185,6 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume,
{ {
const BYTE *src_addr; const BYTE *src_addr;
if (!is_conversion_from_supported(src_format_desc) if (!is_conversion_from_supported(src_format_desc)
|| !is_conversion_to_supported(dst_format_desc)) || !is_conversion_to_supported(dst_format_desc))
{ {
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
...@@ -22,6 +22,8 @@ C_SRCS = \ ...@@ -22,6 +22,8 @@ C_SRCS = \
sprite.c \ sprite.c \
surface.c \ surface.c \
texture.c \ texture.c \
txc_compress_dxtn.c \
txc_fetch_dxtn.c \
util.c \ util.c \
volume.c \ volume.c \
xfile.c xfile.c
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment