https://git.reactos.org/?p=reactos.git;a=commitdiff;h=882cc57c66ff472fb5a6e…
commit 882cc57c66ff472fb5a6ec6b202d86692a9bedcd
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Mon Sep 21 22:57:00 2020 +0200
Commit: Jérôme Gardou <jerome.gardou(a)reactos.org>
CommitDate: Thu Feb 4 16:37:04 2021 +0100
[WINESYNC] d3dx9: Handle compressed surfaces in D3DXLoadSurfaceFromMemory.
Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=24983
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
wine commit id 376182062ff1ab8e7835fd67bc650da83c2cc75d by Matteo Bruni
<mbruni(a)codeweavers.com>
---
dll/directx/wine/d3dx9_36/d3dx9.cmake | 2 +
dll/directx/wine/d3dx9_36/d3dx9_private.h | 4 +-
dll/directx/wine/d3dx9_36/precomp.h | 1 +
dll/directx/wine/d3dx9_36/surface.c | 112 +++-
dll/directx/wine/d3dx9_36/texture.c | 41 +-
dll/directx/wine/d3dx9_36/txc_compress_dxtn.c | 845 ++++++++++++++++++++++++++
dll/directx/wine/d3dx9_36/txc_dxtn.h | 54 ++
dll/directx/wine/d3dx9_36/txc_fetch_dxtn.c | 247 ++++++++
dll/directx/wine/d3dx9_36/volume.c | 1 -
modules/rostests/winetests/d3dx9_36/surface.c | 63 +-
modules/rostests/winetests/d3dx9_36/texture.c | 158 ++---
sdk/tools/winesync/d3dx9.cfg | 2 +-
12 files changed, 1397 insertions(+), 133 deletions(-)
diff --git a/dll/directx/wine/d3dx9_36/d3dx9.cmake
b/dll/directx/wine/d3dx9_36/d3dx9.cmake
index 4140f00eca1..cb8d937a561 100644
--- a/dll/directx/wine/d3dx9_36/d3dx9.cmake
+++ b/dll/directx/wine/d3dx9_36/d3dx9.cmake
@@ -20,6 +20,8 @@ function(add_d3dx9_target __version)
../d3dx9_36/sprite.c
../d3dx9_36/surface.c
../d3dx9_36/texture.c
+ ../d3dx9_36/txc_compress_dxtn.c
+ ../d3dx9_36/txc_fetch_dxtn.c
../d3dx9_36/util.c
../d3dx9_36/volume.c
../d3dx9_36/xfile.c)
diff --git a/dll/directx/wine/d3dx9_36/d3dx9_private.h
b/dll/directx/wine/d3dx9_36/d3dx9_private.h
index 66bbe21b4ae..69dcb033fdb 100644
--- a/dll/directx/wine/d3dx9_36/d3dx9_private.h
+++ b/dll/directx/wine/d3dx9_36/d3dx9_private.h
@@ -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)
{
if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16
- || format->type == FORMAT_ARGBF)
+ || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT)
return TRUE;
return !!format->to_rgba;
}
@@ -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)
{
if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16
- || format->type == FORMAT_ARGBF)
+ || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT)
return TRUE;
return !!format->from_rgba;
}
diff --git a/dll/directx/wine/d3dx9_36/precomp.h b/dll/directx/wine/d3dx9_36/precomp.h
index d0673e03b2b..b6a35522a31 100644
--- a/dll/directx/wine/d3dx9_36/precomp.h
+++ b/dll/directx/wine/d3dx9_36/precomp.h
@@ -27,6 +27,7 @@
#include <wine/unicode.h>
#include "d3dx9_private.h"
+#include "txc_dxtn.h"
#include <dxfile.h>
#include <rmxfguid.h>
diff --git a/dll/directx/wine/d3dx9_36/surface.c b/dll/directx/wine/d3dx9_36/surface.c
index b1caec724e1..c60364a12d2 100644
--- a/dll/directx/wine/d3dx9_36/surface.c
+++ b/dll/directx/wine/d3dx9_36/surface.c
@@ -27,6 +27,8 @@
#include "initguid.h"
#include "ole2.h"
#include "wincodec.h"
+
+#include "txc_dxtn.h"
#endif /* __REACTOS__ */
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
@@ -1931,6 +1933,11 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9
*dst_surface,
}
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)
|| !is_conversion_to_supported(destformatdesc))
{
@@ -1939,10 +1946,76 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9
*dst_surface,
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)
{
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) */
{
@@ -1952,7 +2025,42 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9
*dst_surface,
/* Always apply a point filter until D3DX_FILTER_LINEAR,
* D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
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);
}
}
diff --git a/dll/directx/wine/d3dx9_36/texture.c b/dll/directx/wine/d3dx9_36/texture.c
index 85515c73bbd..7773d2ad33b 100644
--- a/dll/directx/wine/d3dx9_36/texture.c
+++ b/dll/directx/wine/d3dx9_36/texture.c
@@ -187,24 +187,30 @@ HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture,
}
}
-static D3DFORMAT get_luminance_replacement_format(D3DFORMAT format)
+static D3DFORMAT get_replacement_format(D3DFORMAT format)
{
static const struct
{
- D3DFORMAT luminance_format;
+ D3DFORMAT format;
D3DFORMAT replacement_format;
- } luminance_replacements[] =
+ }
+ replacements[] =
{
{D3DFMT_L8, D3DFMT_X8R8G8B8},
{D3DFMT_A8L8, D3DFMT_A8R8G8B8},
{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;
- for (i = 0; i < ARRAY_SIZE(luminance_replacements); ++i)
- if (format == luminance_replacements[i].luminance_format)
- return luminance_replacements[i].replacement_format;
+ for (i = 0; i < ARRAY_SIZE(replacements); ++i)
+ if (format == replacements[i].format)
+ return replacements[i].replacement_format;
return format;
}
@@ -279,7 +285,7 @@ HRESULT WINAPI D3DXCheckTextureRequirements(struct IDirect3DDevice9
*device, UIN
FIXME("Pixel format %x not handled\n", usedformat);
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;
channels = !!fmt->bits[0] + !!fmt->bits[1] + !!fmt->bits[2] +
!!fmt->bits[3];
@@ -568,12 +574,12 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct
IDirect3DDevice9 *devi
D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO
*srcinfo,
PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
{
+ BOOL dynamic_texture, format_specified = FALSE;
+ unsigned int loaded_miplevels, skip_levels;
+ IDirect3DSurface9 *surface;
IDirect3DTexture9 **texptr;
IDirect3DTexture9 *buftex;
- IDirect3DSurface9 *surface;
- BOOL dynamic_texture, format_specified = FALSE;
D3DXIMAGE_INFO imginfo;
- UINT loaded_miplevels, skip_levels;
D3DCAPS9 caps;
HRESULT hr;
@@ -660,15 +666,10 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct
IDirect3DDevice9 *devi
if (colorkey && !format_specified)
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
&& 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;
}
@@ -1479,12 +1480,6 @@ HRESULT WINAPI
D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
if (FAILED(hr))
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);
if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
{
diff --git a/dll/directx/wine/d3dx9_36/txc_compress_dxtn.c
b/dll/directx/wine/d3dx9_36/txc_compress_dxtn.c
new file mode 100644
index 00000000000..62b3ae125d9
--- /dev/null
+++ b/dll/directx/wine/d3dx9_36/txc_compress_dxtn.c
@@ -0,0 +1,845 @@
+#ifdef __REACTOS__
+#include "precomp.h"
+#else
+/*
+ * 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 <stdlib.h>
+#include "txc_dxtn.h"
+#endif /* __REACTOS__ */
+
+/* weights used for error function, basically weights (unsquared 2/4/1) according to
rgb->luminance conversion
+ not sure if this really reflects visual perception */
+#define REDWEIGHT 4
+#define GREENWEIGHT 16
+#define BLUEWEIGHT 1
+
+#define ALPHACUT 127
+
+static void fancybasecolorsearch( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte
*bestcolor[2],
+ GLint numxpixels, GLint numypixels, GLint type, GLboolean
haveAlpha)
+{
+ /* use same luminance-weighted distance metric to determine encoding as for finding
the base colors */
+
+ /* TODO could also try to find a better encoding for the 3-color-encoding type, this
really should be done
+ if it's rgba_dxt1 and we have alpha in the block, currently even values which
will be mapped to black
+ due to their alpha value will influence the result */
+ GLint i, j, colors, z;
+ GLuint pixerror, pixerrorred, pixerrorgreen, pixerrorblue, pixerrorbest;
+ GLint colordist, blockerrlin[2][3];
+ GLubyte nrcolor[2];
+ GLint pixerrorcolorbest[3];
+ GLubyte enc = 0;
+ GLubyte cv[4][4];
+ GLubyte testcolor[2][3];
+
+/* fprintf(stderr, "color begin 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n",
+ bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0],
bestcolor[1][1], bestcolor[1][2]);*/
+ if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3
| bestcolor[0][2] >> 3) <
+ ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3
| bestcolor[1][2] >> 3)) {
+ testcolor[0][0] = bestcolor[0][0];
+ testcolor[0][1] = bestcolor[0][1];
+ testcolor[0][2] = bestcolor[0][2];
+ testcolor[1][0] = bestcolor[1][0];
+ testcolor[1][1] = bestcolor[1][1];
+ testcolor[1][2] = bestcolor[1][2];
+ }
+ else {
+ testcolor[1][0] = bestcolor[0][0];
+ testcolor[1][1] = bestcolor[0][1];
+ testcolor[1][2] = bestcolor[0][2];
+ testcolor[0][0] = bestcolor[1][0];
+ testcolor[0][1] = bestcolor[1][1];
+ testcolor[0][2] = bestcolor[1][2];
+ }
+
+ for (i = 0; i < 3; i ++) {
+ cv[0][i] = testcolor[0][i];
+ cv[1][i] = testcolor[1][i];
+ cv[2][i] = (testcolor[0][i] * 2 + testcolor[1][i]) / 3;
+ cv[3][i] = (testcolor[0][i] + testcolor[1][i] * 2) / 3;
+ }
+
+ blockerrlin[0][0] = 0;
+ blockerrlin[0][1] = 0;
+ blockerrlin[0][2] = 0;
+ blockerrlin[1][0] = 0;
+ blockerrlin[1][1] = 0;
+ blockerrlin[1][2] = 0;
+
+ nrcolor[0] = 0;
+ nrcolor[1] = 0;
+
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ pixerrorbest = 0xffffffff;
+ for (colors = 0; colors < 4; colors++) {
+ colordist = srccolors[j][i][0] - (cv[colors][0]);
+ pixerror = colordist * colordist * REDWEIGHT;
+ pixerrorred = colordist;
+ colordist = srccolors[j][i][1] - (cv[colors][1]);
+ pixerror += colordist * colordist * GREENWEIGHT;
+ pixerrorgreen = colordist;
+ colordist = srccolors[j][i][2] - (cv[colors][2]);
+ pixerror += colordist * colordist * BLUEWEIGHT;
+ pixerrorblue = colordist;
+ if (pixerror < pixerrorbest) {
+ enc = colors;
+ pixerrorbest = pixerror;
+ pixerrorcolorbest[0] = pixerrorred;
+ pixerrorcolorbest[1] = pixerrorgreen;
+ pixerrorcolorbest[2] = pixerrorblue;
+ }
+ }
+ if (enc == 0) {
+ for (z = 0; z < 3; z++) {
+ blockerrlin[0][z] += 3 * pixerrorcolorbest[z];
+ }
+ nrcolor[0] += 3;
+ }
+ else if (enc == 2) {
+ for (z = 0; z < 3; z++) {
+ blockerrlin[0][z] += 2 * pixerrorcolorbest[z];
+ }
+ nrcolor[0] += 2;
+ for (z = 0; z < 3; z++) {
+ blockerrlin[1][z] += 1 * pixerrorcolorbest[z];
+ }
+ nrcolor[1] += 1;
+ }
+ else if (enc == 3) {
+ for (z = 0; z < 3; z++) {
+ blockerrlin[0][z] += 1 * pixerrorcolorbest[z];
+ }
+ nrcolor[0] += 1;
+ for (z = 0; z < 3; z++) {
+ blockerrlin[1][z] += 2 * pixerrorcolorbest[z];
+ }
+ nrcolor[1] += 2;
+ }
+ else if (enc == 1) {
+ for (z = 0; z < 3; z++) {
+ blockerrlin[1][z] += 3 * pixerrorcolorbest[z];
+ }
+ nrcolor[1] += 3;
+ }
+ }
+ }
+ if (nrcolor[0] == 0) nrcolor[0] = 1;
+ if (nrcolor[1] == 0) nrcolor[1] = 1;
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 3; i++) {
+ GLint newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j];
+ if (newvalue <= 0)
+ testcolor[j][i] = 0;
+ else if (newvalue >= 255)
+ testcolor[j][i] = 255;
+ else testcolor[j][i] = newvalue;
+ }
+ }
+
+ if ((abs(testcolor[0][0] - testcolor[1][0]) < 8) &&
+ (abs(testcolor[0][1] - testcolor[1][1]) < 4) &&
+ (abs(testcolor[0][2] - testcolor[1][2]) < 8)) {
+ /* both colors are so close they might get encoded as the same 16bit values */
+ GLubyte coldiffred, coldiffgreen, coldiffblue, coldiffmax, factor, ind0, ind1;
+
+ coldiffred = abs(testcolor[0][0] - testcolor[1][0]);
+ coldiffgreen = 2 * abs(testcolor[0][1] - testcolor[1][1]);
+ coldiffblue = abs(testcolor[0][2] - testcolor[1][2]);
+ coldiffmax = coldiffred;
+ if (coldiffmax < coldiffgreen) coldiffmax = coldiffgreen;
+ if (coldiffmax < coldiffblue) coldiffmax = coldiffblue;
+ if (coldiffmax > 0) {
+ if (coldiffmax > 4) factor = 2;
+ else if (coldiffmax > 2) factor = 3;
+ else factor = 4;
+ /* Won't do much if the color value is near 255... */
+ /* argh so many ifs */
+ if (testcolor[1][1] >= testcolor[0][1]) {
+ ind1 = 1; ind0 = 0;
+ }
+ else {
+ ind1 = 0; ind0 = 1;
+ }
+ if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255)
+ testcolor[ind1][1] += factor * coldiffgreen;
+ else testcolor[ind1][1] = 255;
+ if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0) {
+ if ((testcolor[ind1][0] + factor * coldiffred) <= 255)
+ testcolor[ind1][0] += factor * coldiffred;
+ else testcolor[ind1][0] = 255;
+ }
+ else {
+ if ((testcolor[ind0][0] + factor * coldiffred) <= 255)
+ testcolor[ind0][0] += factor * coldiffred;
+ else testcolor[ind0][0] = 255;
+ }
+ if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0) {
+ if ((testcolor[ind1][2] + factor * coldiffblue) <= 255)
+ testcolor[ind1][2] += factor * coldiffblue;
+ else testcolor[ind1][2] = 255;
+ }
+ else {
+ if ((testcolor[ind0][2] + factor * coldiffblue) <= 255)
+ testcolor[ind0][2] += factor * coldiffblue;
+ else testcolor[ind0][2] = 255;
+ }
+ }
+ }
+
+ if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3
| testcolor[0][2] >> 3) <
+ ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3
| testcolor[1][2]) >> 3) {
+ for (i = 0; i < 3; i++) {
+ bestcolor[0][i] = testcolor[0][i];
+ bestcolor[1][i] = testcolor[1][i];
+ }
+ }
+ else {
+ for (i = 0; i < 3; i++) {
+ bestcolor[0][i] = testcolor[1][i];
+ bestcolor[1][i] = testcolor[0][i];
+ }
+ }
+
+/* fprintf(stderr, "color end 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n",
+ bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1],
bestcolor[1][2]);*/
+}
+
+
+
+static void storedxtencodedblock( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte
*bestcolor[2],
+ GLint numxpixels, GLint numypixels, GLuint type, GLboolean
haveAlpha)
+{
+ /* use same luminance-weighted distance metric to determine encoding as for finding
the base colors */
+
+ GLint i, j, colors;
+ GLuint testerror, testerror2, pixerror, pixerrorbest;
+ GLint colordist;
+ GLushort color0, color1, tempcolor;
+ GLuint bits = 0, bits2 = 0;
+ GLubyte *colorptr;
+ GLubyte enc = 0;
+ GLubyte cv[4][4];
+
+ bestcolor[0][0] = bestcolor[0][0] & 0xf8;
+ bestcolor[0][1] = bestcolor[0][1] & 0xfc;
+ bestcolor[0][2] = bestcolor[0][2] & 0xf8;
+ bestcolor[1][0] = bestcolor[1][0] & 0xf8;
+ bestcolor[1][1] = bestcolor[1][1] & 0xfc;
+ bestcolor[1][2] = bestcolor[1][2] & 0xf8;
+
+ color0 = bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2]
>> 3;
+ color1 = bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2]
>> 3;
+ if (color0 < color1) {
+ tempcolor = color0; color0 = color1; color1 = tempcolor;
+ colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr;
+ }
+
+
+ for (i = 0; i < 3; i++) {
+ cv[0][i] = bestcolor[0][i];
+ cv[1][i] = bestcolor[1][i];
+ cv[2][i] = (bestcolor[0][i] * 2 + bestcolor[1][i]) / 3;
+ cv[3][i] = (bestcolor[0][i] + bestcolor[1][i] * 2) / 3;
+ }
+
+ testerror = 0;
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ pixerrorbest = 0xffffffff;
+ for (colors = 0; colors < 4; colors++) {
+ colordist = srccolors[j][i][0] - cv[colors][0];
+ pixerror = colordist * colordist * REDWEIGHT;
+ colordist = srccolors[j][i][1] - cv[colors][1];
+ pixerror += colordist * colordist * GREENWEIGHT;
+ colordist = srccolors[j][i][2] - cv[colors][2];
+ pixerror += colordist * colordist * BLUEWEIGHT;
+ if (pixerror < pixerrorbest) {
+ pixerrorbest = pixerror;
+ enc = colors;
+ }
+ }
+ testerror += pixerrorbest;
+ bits |= enc << (2 * (j * 4 + i));
+ }
+ }
+ /* some hw might disagree but actually decoding should always use 4-color encoding
+ for non-dxt1 formats */
+ if (type == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || type ==
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
+ for (i = 0; i < 3; i++) {
+ cv[2][i] = (bestcolor[0][i] + bestcolor[1][i]) / 2;
+ /* this isn't used. Looks like the black color constant can only be used
+ with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu
disagrees,
+ it will decode 3 to black even with DXT3/5), and due to how the color
searching works
+ it won't get used even then */
+ cv[3][i] = 0;
+ }
+ testerror2 = 0;
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ pixerrorbest = 0xffffffff;
+ if ((type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) && (srccolors[j][i][3]
<= ALPHACUT)) {
+ enc = 3;
+ pixerrorbest = 0; /* don't calculate error */
+ }
+ else {
+ /* we're calculating the same what we have done already for colors 0-1
above... */
+ for (colors = 0; colors < 3; colors++) {
+ colordist = srccolors[j][i][0] - cv[colors][0];
+ pixerror = colordist * colordist * REDWEIGHT;
+ colordist = srccolors[j][i][1] - cv[colors][1];
+ pixerror += colordist * colordist * GREENWEIGHT;
+ colordist = srccolors[j][i][2] - cv[colors][2];
+ pixerror += colordist * colordist * BLUEWEIGHT;
+ if (pixerror < pixerrorbest) {
+ pixerrorbest = pixerror;
+ /* need to exchange colors later */
+ if (colors > 1) enc = colors;
+ else enc = colors ^ 1;
+ }
+ }
+ }
+ testerror2 += pixerrorbest;
+ bits2 |= enc << (2 * (j * 4 + i));
+ }
+ }
+ } else {
+ testerror2 = 0xffffffff;
+ }
+
+ /* finally we're finished, write back colors and bits */
+ if ((testerror > testerror2) || (haveAlpha)) {
+ *blkaddr++ = color1 & 0xff;
+ *blkaddr++ = color1 >> 8;
+ *blkaddr++ = color0 & 0xff;
+ *blkaddr++ = color0 >> 8;
+ *blkaddr++ = bits2 & 0xff;
+ *blkaddr++ = ( bits2 >> 8) & 0xff;
+ *blkaddr++ = ( bits2 >> 16) & 0xff;
+ *blkaddr = bits2 >> 24;
+ }
+ else {
+ *blkaddr++ = color0 & 0xff;
+ *blkaddr++ = color0 >> 8;
+ *blkaddr++ = color1 & 0xff;
+ *blkaddr++ = color1 >> 8;
+ *blkaddr++ = bits & 0xff;
+ *blkaddr++ = ( bits >> 8) & 0xff;
+ *blkaddr++ = ( bits >> 16) & 0xff;
+ *blkaddr = bits >> 24;
+ }
+}
+
+static void encodedxtcolorblockfaster( GLubyte *blkaddr, GLubyte srccolors[4][4][4],
+ GLint numxpixels, GLint numypixels, GLuint type )
+{
+/* simplistic approach. We need two base colors, simply use the "highest" and
the "lowest" color
+ present in the picture as base colors */
+
+ /* define lowest and highest color as shortest and longest vector to 0/0/0, though
the
+ vectors are weighted similar to their importance in rgb-luminance conversion
+ doesn't work too well though...
+ This seems to be a rather difficult problem */
+
+ GLubyte *bestcolor[2];
+ GLubyte basecolors[2][3];
+ GLubyte i, j;
+ GLuint lowcv, highcv, testcv;
+ GLboolean haveAlpha = GL_FALSE;
+
+ lowcv = highcv = srccolors[0][0][0] * srccolors[0][0][0] * REDWEIGHT +
+ srccolors[0][0][1] * srccolors[0][0][1] * GREENWEIGHT +
+ srccolors[0][0][2] * srccolors[0][0][2] * BLUEWEIGHT;
+ bestcolor[0] = bestcolor[1] = srccolors[0][0];
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* don't use this as a base color if the pixel will get black/transparent
anyway */
+ if ((type != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (srccolors[j][i][3] >
ALPHACUT)) {
+ testcv = srccolors[j][i][0] * srccolors[j][i][0] * REDWEIGHT +
+ srccolors[j][i][1] * srccolors[j][i][1] * GREENWEIGHT +
+ srccolors[j][i][2] * srccolors[j][i][2] * BLUEWEIGHT;
+ if (testcv > highcv) {
+ highcv = testcv;
+ bestcolor[1] = srccolors[j][i];
+ }
+ else if (testcv < lowcv) {
+ lowcv = testcv;
+ bestcolor[0] = srccolors[j][i];
+ }
+ }
+ else haveAlpha = GL_TRUE;
+ }
+ }
+ /* make sure the original color values won't get touched... */
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 3; i++) {
+ basecolors[j][i] = bestcolor[j][i];
+ }
+ }
+ bestcolor[0] = basecolors[0];
+ bestcolor[1] = basecolors[1];
+
+ /* try to find better base colors */
+ fancybasecolorsearch(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type,
haveAlpha);
+ /* find the best encoding for these colors, and store the result */
+ storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type,
haveAlpha);
+}
+
+static void writedxt5encodedalphablock( GLubyte *blkaddr, GLubyte alphabase1, GLubyte
alphabase2,
+ GLubyte alphaenc[16])
+{
+ *blkaddr++ = alphabase1;
+ *blkaddr++ = alphabase2;
+ *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) <<
6);
+ *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4]
<< 4) | ((alphaenc[5] & 1) << 7);
+ *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7]
<< 5);
+ *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) <<
6);
+ *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12]
<< 4) | ((alphaenc[13] & 1) << 7);
+ *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15]
<< 5);
+}
+
+static void encodedxt5alpha(GLubyte *blkaddr, GLubyte srccolors[4][4][4],
+ GLint numxpixels, GLint numypixels)
+{
+ GLubyte alphabase[2], alphause[2];
+ GLshort alphatest[2];
+ GLuint alphablockerror1, alphablockerror2, alphablockerror3;
+ GLubyte i, j, aindex, acutValues[7];
+ GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16];
+ GLboolean alphaabsmin = GL_FALSE;
+ GLboolean alphaabsmax = GL_FALSE;
+ GLshort alphadist;
+
+ /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1]
highest */
+ alphabase[0] = 0xff; alphabase[1] = 0x0;
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ if (srccolors[j][i][3] == 0)
+ alphaabsmin = GL_TRUE;
+ else if (srccolors[j][i][3] == 255)
+ alphaabsmax = GL_TRUE;
+ else {
+ if (srccolors[j][i][3] > alphabase[1])
+ alphabase[1] = srccolors[j][i][3];
+ if (srccolors[j][i][3] < alphabase[0])
+ alphabase[0] = srccolors[j][i][3];
+ }
+ }
+ }
+
+
+ if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax))
{ /* one color, either max or min */
+ /* shortcut here since it is a very common case (and also avoids later problems)
*/
+ /* || (alphabase[0] == alphabase[1] && !alphaabsmin &&
!alphaabsmax) */
+ /* could also thest for alpha0 == alpha1 (and not min/max), but probably not
common, so don't bother */
+
+ *blkaddr++ = srccolors[0][0][3];
+ blkaddr++;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+ *blkaddr++ = 0;
+/* fprintf(stderr, "enc0 used\n");*/
+ return;
+ }
+
+ /* find best encoding for alpha0 > alpha1 */
+ /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax
are true */
+ alphablockerror1 = 0x0;
+ alphablockerror2 = 0xffffffff;
+ alphablockerror3 = 0xffffffff;
+ if (alphaabsmin) alphause[0] = 0;
+ else alphause[0] = alphabase[0];
+ if (alphaabsmax) alphause[1] = 255;
+ else alphause[1] = alphabase[1];
+ /* calculate the 7 cut values, just the middle between 2 of the computed alpha values
*/
+ for (aindex = 0; aindex < 7; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex
+ 1))) / 14;
+ }
+
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* maybe it's overkill to have the most complicated calculation just for the
error
+ calculation which we only need to figure out if encoding1 or encoding2 is
better... */
+ if (srccolors[j][i][3] > acutValues[0]) {
+ alphaenc1[4*j + i] = 0;
+ alphadist = srccolors[j][i][3] - alphause[1];
+ }
+ else if (srccolors[j][i][3] > acutValues[1]) {
+ alphaenc1[4*j + i] = 2;
+ alphadist = srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7;
+ }
+ else if (srccolors[j][i][3] > acutValues[2]) {
+ alphaenc1[4*j + i] = 3;
+ alphadist = srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7;
+ }
+ else if (srccolors[j][i][3] > acutValues[3]) {
+ alphaenc1[4*j + i] = 4;
+ alphadist = srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7;
+ }
+ else if (srccolors[j][i][3] > acutValues[4]) {
+ alphaenc1[4*j + i] = 5;
+ alphadist = srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7;
+ }
+ else if (srccolors[j][i][3] > acutValues[5]) {
+ alphaenc1[4*j + i] = 6;
+ alphadist = srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7;
+ }
+ else if (srccolors[j][i][3] > acutValues[6]) {
+ alphaenc1[4*j + i] = 7;
+ alphadist = srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7;
+ }
+ else {
+ alphaenc1[4*j + i] = 1;
+ alphadist = srccolors[j][i][3] - alphause[0];
+ }
+ alphablockerror1 += alphadist * alphadist;
+ }
+ }
+/* for (i = 0; i < 16; i++) {
+ fprintf(stderr, "%d ", alphaenc1[i]);
+ }
+ fprintf(stderr, "cutVals ");
+ for (i = 0; i < 8; i++) {
+ fprintf(stderr, "%d ", acutValues[i]);
+ }
+ fprintf(stderr, "srcVals ");
+ for (j = 0; j < numypixels; j++)
+ for (i = 0; i < numxpixels; i++) {
+ fprintf(stderr, "%d ", srccolors[j][i][3]);
+ }
+
+ fprintf(stderr, "\n");
+ }*/
+ /* it's not very likely this encoding is better if both alphaabsmin and
alphaabsmax
+ are false but try it anyway */
+ if (alphablockerror1 >= 32) {
+
+ /* don't bother if encoding is already very good, this condition should also
imply
+ we have valid alphabase colors which we absolutely need (alphabase[0] <=
alphabase[1]) */
+ alphablockerror2 = 0;
+ for (aindex = 0; aindex < 5; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] *
(2*aindex + 1)) / 10;
+ }
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* maybe it's overkill to have the most complicated calculation just for
the error
+ calculation which we only need to figure out if encoding1 or encoding2 is
better... */
+ if (srccolors[j][i][3] == 0) {
+ alphaenc2[4*j + i] = 6;
+ alphadist = 0;
+ }
+ else if (srccolors[j][i][3] == 255) {
+ alphaenc2[4*j + i] = 7;
+ alphadist = 0;
+ }
+ else if (srccolors[j][i][3] <= acutValues[0]) {
+ alphaenc2[4*j + i] = 0;
+ alphadist = srccolors[j][i][3] - alphabase[0];
+ }
+ else if (srccolors[j][i][3] <= acutValues[1]) {
+ alphaenc2[4*j + i] = 2;
+ alphadist = srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) /
5;
+ }
+ else if (srccolors[j][i][3] <= acutValues[2]) {
+ alphaenc2[4*j + i] = 3;
+ alphadist = srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) /
5;
+ }
+ else if (srccolors[j][i][3] <= acutValues[3]) {
+ alphaenc2[4*j + i] = 4;
+ alphadist = srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) /
5;
+ }
+ else if (srccolors[j][i][3] <= acutValues[4]) {
+ alphaenc2[4*j + i] = 5;
+ alphadist = srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) /
5;
+ }
+ else {
+ alphaenc2[4*j + i] = 1;
+ alphadist = srccolors[j][i][3] - alphabase[1];
+ }
+ alphablockerror2 += alphadist * alphadist;
+ }
+ }
+
+
+ /* skip this if the error is already very small
+ this encoding is MUCH better on average than #2 though, but expensive! */
+ if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
+ GLshort blockerrlin1 = 0;
+ GLshort blockerrlin2 = 0;
+ GLubyte nralphainrangelow = 0;
+ GLubyte nralphainrangehigh = 0;
+ alphatest[0] = 0xff;
+ alphatest[1] = 0x0;
+ /* if we have large range it's likely there are values close to 0/255, try
to map them to 0/255 */
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ if ((srccolors[j][i][3] > alphatest[1]) && (srccolors[j][i][3]
< (255 -(alphabase[1] - alphabase[0]) / 28)))
+ alphatest[1] = srccolors[j][i][3];
+ if ((srccolors[j][i][3] < alphatest[0]) && (srccolors[j][i][3]
> (alphabase[1] - alphabase[0]) / 28))
+ alphatest[0] = srccolors[j][i][3];
+ }
+ }
+ /* shouldn't happen too often, don't really care about those
degenerated cases */
+ if (alphatest[1] <= alphatest[0]) {
+ alphatest[0] = 1;
+ alphatest[1] = 254;
+/* fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/
+ }
+ for (aindex = 0; aindex < 5; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] *
(2*aindex + 1)) / 10;
+ }
+
+ /* find the "average" difference between the alpha values and the next
encoded value.
+ This is then used to calculate new base values.
+ Should there be some weighting, i.e. those values closer to alphatest[x] have
more weight,
+ since they will see more improvement, and also because the values in the
middle are somewhat
+ likely to get no improvement at all (because the base values might move in
different directions)?
+ OTOH it would mean the values in the middle are even less likely to get an
improvement
+ */
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ if (srccolors[j][i][3] <= alphatest[0] / 2) {
+ }
+ else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) {
+ }
+ else if (srccolors[j][i][3] <= acutValues[0]) {
+ blockerrlin1 += (srccolors[j][i][3] - alphatest[0]);
+ nralphainrangelow += 1;
+ }
+ else if (srccolors[j][i][3] <= acutValues[1]) {
+ blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1]
* 1) / 5);
+ blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1]
* 1) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else if (srccolors[j][i][3] <= acutValues[2]) {
+ blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1]
* 2) / 5);
+ blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1]
* 2) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else if (srccolors[j][i][3] <= acutValues[3]) {
+ blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1]
* 3) / 5);
+ blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1]
* 3) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else if (srccolors[j][i][3] <= acutValues[4]) {
+ blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1]
* 4) / 5);
+ blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1]
* 4) / 5);
+ nralphainrangelow += 1;
+ nralphainrangehigh += 1;
+ }
+ else {
+ blockerrlin2 += (srccolors[j][i][3] - alphatest[1]);
+ nralphainrangehigh += 1;
+ }
+ }
+ }
+ /* shouldn't happen often, needed to avoid div by zero */
+ if (nralphainrangelow == 0) nralphainrangelow = 1;
+ if (nralphainrangehigh == 0) nralphainrangehigh = 1;
+ alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
+/* fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1,
nralphainrangelow);
+ fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2,
nralphainrangehigh);*/
+ /* again shouldn't really happen often... */
+ if (alphatest[0] < 0) {
+ alphatest[0] = 0;
+/* fprintf(stderr, "adj alpha base val to 0\n");*/
+ }
+ alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
+ if (alphatest[1] > 255) {
+ alphatest[1] = 255;
+/* fprintf(stderr, "adj alpha base val to 255\n");*/
+ }
+
+ alphablockerror3 = 0;
+ for (aindex = 0; aindex < 5; aindex++) {
+ /* don't forget here is always rounded down */
+ acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] *
(2*aindex + 1)) / 10;
+ }
+ for (j = 0; j < numypixels; j++) {
+ for (i = 0; i < numxpixels; i++) {
+ /* maybe it's overkill to have the most complicated calculation just
for the error
+ calculation which we only need to figure out if encoding1 or encoding2
is better... */
+ if (srccolors[j][i][3] <= alphatest[0] / 2) {
+ alphaenc3[4*j + i] = 6;
+ alphadist = srccolors[j][i][3];
+ }
+ else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) {
+ alphaenc3[4*j + i] = 7;
+ alphadist = 255 - srccolors[j][i][3];
+ }
+ else if (srccolors[j][i][3] <= acutValues[0]) {
+ alphaenc3[4*j + i] = 0;
+ alphadist = srccolors[j][i][3] - alphatest[0];
+ }
+ else if (srccolors[j][i][3] <= acutValues[1]) {
+ alphaenc3[4*j + i] = 2;
+ alphadist = srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) /
5;
+ }
+ else if (srccolors[j][i][3] <= acutValues[2]) {
+ alphaenc3[4*j + i] = 3;
+ alphadist = srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2)
/ 5;
+ }
+ else if (srccolors[j][i][3] <= acutValues[3]) {
+ alphaenc3[4*j + i] = 4;
+ alphadist = srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3)
/ 5;
+ }
+ else if (srccolors[j][i][3] <= acutValues[4]) {
+ alphaenc3[4*j + i] = 5;
+ alphadist = srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4)
/ 5;
+ }
+ else {
+ alphaenc3[4*j + i] = 1;
+ alphadist = srccolors[j][i][3] - alphatest[1];
+ }
+ alphablockerror3 += alphadist * alphadist;
+ }
+ }
+ }
+ }
+ /* write the alpha values and encoding back. */
+ if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <=
alphablockerror3)) {
+/* if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n",
alphablockerror1);*/
+ writedxt5encodedalphablock( blkaddr, alphause[1], alphause[0], alphaenc1 );
+ }
+ else if (alphablockerror2 <= alphablockerror3) {
+/* if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n",
alphablockerror2);*/
+ writedxt5encodedalphablock( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
+ }
+ else {
+/* fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/
+ writedxt5encodedalphablock( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1],
alphaenc3 );
+ }
+}
+
+static void extractsrccolors( GLubyte srcpixels[4][4][4], const GLchan *srcaddr,
+ GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint
comps)
+{
+ GLubyte i, j, c;
+ const GLchan *curaddr;
+ for (j = 0; j < numypixels; j++) {
+ curaddr = srcaddr + j * srcRowStride * comps;
+ for (i = 0; i < numxpixels; i++) {
+ for (c = 0; c < comps; c++) {
+ srcpixels[j][i][c] = *curaddr++ / (CHAN_MAX / 255);
+ }
+ }
+ }
+}
+
+
+void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, const GLubyte
*srcPixData,
+ GLenum destFormat, GLubyte *dest, GLint dstRowStride)
+{
+ GLubyte *blkaddr = dest;
+ GLubyte srcpixels[4][4][4];
+ const GLchan *srcaddr = srcPixData;
+ GLint numxpixels, numypixels;
+ GLint i, j;
+ GLint dstRowDiff;
+
+ switch (destFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ /* hmm we used to get called without dstRowStride... */
+ dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) &
~3) * 2) : 0;
+/* fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
+ width, height, dstRowStride); */
+ for (j = 0; j < height; j += 4) {
+ if (height > j + 3) numypixels = 4;
+ else numypixels = height - j;
+ srcaddr = srcPixData + j * width * srccomps;
+ for (i = 0; i < width; i += 4) {
+ if (width > i + 3) numxpixels = 4;
+ else numxpixels = width - i;
+ extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels,
srccomps);
+ encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels,
destFormat);
+ srcaddr += srccomps * numxpixels;
+ blkaddr += 8;
+ }
+ blkaddr += dstRowDiff;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) &
~3) * 4) : 0;
+/* fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
+ width, height, dstRowStride); */
+ for (j = 0; j < height; j += 4) {
+ if (height > j + 3) numypixels = 4;
+ else numypixels = height - j;
+ srcaddr = srcPixData + j * width * srccomps;
+ for (i = 0; i < width; i += 4) {
+ if (width > i + 3) numxpixels = 4;
+ else numxpixels = width - i;
+ extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels,
srccomps);
+ *blkaddr++ = (srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] &
0xf0);
+ *blkaddr++ = (srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] &
0xf0);
+ *blkaddr++ = (srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] &
0xf0);
+ *blkaddr++ = (srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] &
0xf0);
+ *blkaddr++ = (srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] &
0xf0);
+ *blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] &
0xf0);
+ *blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] &
0xf0);
+ *blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] &
0xf0);
+ encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels,
destFormat);
+ srcaddr += srccomps * numxpixels;
+ blkaddr += 8;
+ }
+ blkaddr += dstRowDiff;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) &
~3) * 4) : 0;
+/* fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
+ width, height, dstRowStride); */
+ for (j = 0; j < height; j += 4) {
+ if (height > j + 3) numypixels = 4;
+ else numypixels = height - j;
+ srcaddr = srcPixData + j * width * srccomps;
+ for (i = 0; i < width; i += 4) {
+ if (width > i + 3) numxpixels = 4;
+ else numxpixels = width - i;
+ extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels,
srccomps);
+ encodedxt5alpha(blkaddr, srcpixels, numxpixels, numypixels);
+ encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels,
destFormat);
+ srcaddr += srccomps * numxpixels;
+ blkaddr += 16;
+ }
+ blkaddr += dstRowDiff;
+ }
+ break;
+ default:
+ /* fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n",
destFormat); */
+ return;
+ }
+}
diff --git a/dll/directx/wine/d3dx9_36/txc_dxtn.h b/dll/directx/wine/d3dx9_36/txc_dxtn.h
new file mode 100644
index 00000000000..79b0ecbbad4
--- /dev/null
+++ b/dll/directx/wine/d3dx9_36/txc_dxtn.h
@@ -0,0 +1,54 @@
+/*
+ * 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
+
+#ifndef __REACTOS__
+#include "winternl.h"
+#endif
+#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 */
diff --git a/dll/directx/wine/d3dx9_36/txc_fetch_dxtn.c
b/dll/directx/wine/d3dx9_36/txc_fetch_dxtn.c
new file mode 100644
index 00000000000..9c7518a9d8b
--- /dev/null
+++ b/dll/directx/wine/d3dx9_36/txc_fetch_dxtn.c
@@ -0,0 +1,247 @@
+#ifdef __REACTOS__
+#include "precomp.h"
+#else
+/*
+ * 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"
+#endif /* __REACTOS__ */
+
+#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
+}
diff --git a/dll/directx/wine/d3dx9_36/volume.c b/dll/directx/wine/d3dx9_36/volume.c
index e1a6a3bc3cd..35bd869a273 100644
--- a/dll/directx/wine/d3dx9_36/volume.c
+++ b/dll/directx/wine/d3dx9_36/volume.c
@@ -189,7 +189,6 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume,
{
const BYTE *src_addr;
-
if (!is_conversion_from_supported(src_format_desc)
|| !is_conversion_to_supported(dst_format_desc))
{
diff --git a/modules/rostests/winetests/d3dx9_36/surface.c
b/modules/rostests/winetests/d3dx9_36/surface.c
index 11bc3159bb9..04ce57fa4f5 100644
--- a/modules/rostests/winetests/d3dx9_36/surface.c
+++ b/modules/rostests/winetests/d3dx9_36/surface.c
@@ -950,7 +950,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
else {
PALETTEENTRY palette;
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2,
D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2,
+ D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_4bpp(&lockrect, 0, 0, 0x57dbffff);
@@ -959,7 +960,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_4bpp(&lockrect, 1, 1, 0xc8929255);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5,
D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5,
+ D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_4bpp(&lockrect, 0, 0, 0x008cadad);
@@ -968,7 +970,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_4bpp(&lockrect, 1, 1, 0xff29088c);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, D3DFMT_R5G6B5,
4, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5,
+ D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_4bpp(&lockrect, 0, 0, 0xff9cdfb5);
@@ -977,7 +980,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_4bpp(&lockrect, 1, 1, 0xff425d73);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, D3DFMT_G16R16,
8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16,
+ D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
todo_wine {
@@ -988,8 +992,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_4bpp(&lockrect, 1, 1, 0xfffe9aff);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8,
D3DFMT_A8B8G8R8,
- 8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8,
+ D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
@@ -1001,8 +1005,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
SetRect(&rect, 0, 0, 1, 1);
SetRect(&destrect, 1, 1, 2, 2);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata_a8b8g8r8,
D3DFMT_A8B8G8R8,
- 8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata_a8b8g8r8,
+ D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_4bpp(&lockrect, 0, 0, 0xc3f04c39);
@@ -1013,8 +1017,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
SetRect(&rect, 0, 0, 2, 2);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10,
D3DFMT_A2R10G10B10,
- 8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10,
+ D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_4bpp(&lockrect, 0, 0, 0x555c95bf);
@@ -1050,7 +1054,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected
%#x\n", hr, D3D_OK);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr);
- ok(*(DWORD*)lockrect.pBits == 0x80f3f2f1, "Pixel color mismatch: got %#x,
expected 0x80f3f2f1\n", *(DWORD*)lockrect.pBits);
+ ok(*(DWORD*)lockrect.pBits == 0x80f3f2f1,
+ "Pixel color mismatch: got %#x, expected 0x80f3f2f1\n",
*(DWORD*)lockrect.pBits);
hr = IDirect3DSurface9_UnlockRect(surf);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr);
}
@@ -1071,7 +1076,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A1R5G5B5,
D3DPOOL_DEFAULT, &surf, NULL);
if(FAILED(hr)) skip("Failed to create a surface (%#x)\n", hr);
else {
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2,
D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2,
+ D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_2bpp(&lockrect, 0, 0, 0x6fff);
@@ -1080,7 +1086,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_2bpp(&lockrect, 1, 1, 0xca4a);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5,
D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5,
+ D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_2bpp(&lockrect, 0, 0, 0x46b5);
@@ -1089,7 +1096,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_2bpp(&lockrect, 1, 1, 0x9431);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, D3DFMT_R5G6B5,
4, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5,
+ D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_2bpp(&lockrect, 0, 0, 0xcf76);
@@ -1098,7 +1106,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_2bpp(&lockrect, 1, 1, 0xa16e);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, D3DFMT_G16R16,
8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16,
+ D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
todo_wine {
@@ -1109,7 +1118,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_2bpp(&lockrect, 1, 1, 0xfe7f);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8,
D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8,
+ D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
todo_wine {
@@ -1120,7 +1130,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
check_pixel_2bpp(&lockrect, 1, 1, 0xf8b8);
IDirect3DSurface9_UnlockRect(surf);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10,
D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10,
+ D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected
%#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
check_pixel_2bpp(&lockrect, 0, 0, 0x2e57);
@@ -1246,7 +1257,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
/* DXT1, DXT2, DXT3, DXT4, DXT5 */
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM, &surf, NULL);
if (FAILED(hr))
- skip("Failed to create R8G8B8 surface, hr %#x.\n", hr);
+ skip("Failed to create A8R8G8B8 surface, hr %#x.\n", hr);
else
{
hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, dds_24bit,
sizeof(dds_24bit), NULL, D3DX_FILTER_NONE, 0, NULL);
@@ -1260,7 +1271,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL,
D3DX_FILTER_NONE, 0);
- todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT2
format.\n");
+ ok(SUCCEEDED(hr), "Failed to convert pixels to DXT2 format.\n");
check_release((IUnknown*)newsurf, 1);
check_release((IUnknown*)tex, 0);
}
@@ -1273,7 +1284,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL,
D3DX_FILTER_NONE, 0);
- todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3
format.\n");
+ ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n");
check_release((IUnknown*)newsurf, 1);
check_release((IUnknown*)tex, 0);
}
@@ -1286,7 +1297,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL,
D3DX_FILTER_NONE, 0);
- todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT4
format.\n");
+ ok(SUCCEEDED(hr), "Failed to convert pixels to DXT4 format.\n");
check_release((IUnknown*)newsurf, 1);
check_release((IUnknown*)tex, 0);
}
@@ -1299,11 +1310,11 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL,
D3DX_FILTER_NONE, 0);
- todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5
format.\n");
+ ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n");
SetRect(&rect, 0, 0, 4, 2);
hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, &rect, surf, NULL,
&rect, D3DX_FILTER_NONE, 0);
- todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, &rect, &dds_dxt5[128],
D3DFMT_DXT5, 16, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
@@ -1332,7 +1343,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
SetRect(&rect, 2, 2, 6, 6);
hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, NULL, &dds_dxt5_8_8[128],
D3DFMT_DXT5, 16 * 2, NULL, &rect, D3DX_FILTER_POINT, 0);
- todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, &rect,
&dds_dxt5_8_8[128],
D3DFMT_DXT5, 16 * 2, NULL, NULL, D3DX_FILTER_POINT, 0);
@@ -1354,10 +1365,10 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL,
D3DX_FILTER_NONE, 0);
- todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1
format.\n");
+ ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n");
hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL,
D3DX_FILTER_NONE, 0);
- todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1
format.\n");
+ ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n");
check_release((IUnknown*)newsurf, 1);
check_release((IUnknown*)tex, 0);
diff --git a/modules/rostests/winetests/d3dx9_36/texture.c
b/modules/rostests/winetests/d3dx9_36/texture.c
index ced362ff9f1..04513fa4b07 100644
--- a/modules/rostests/winetests/d3dx9_36/texture.c
+++ b/modules/rostests/winetests/d3dx9_36/texture.c
@@ -636,7 +636,7 @@ static void test_D3DXCheckVolumeTextureRequirements(IDirect3DDevice9
*device)
if (has_3d_dxt3)
ok(format == D3DFMT_DXT3, "Returned format %u, expected %u\n", format,
D3DFMT_DXT3);
else
- todo_wine ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected
%u\n", format, D3DFMT_A8R8G8B8);
+ ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n",
format, D3DFMT_A8R8G8B8);
/* mipmaps */
if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
@@ -1628,16 +1628,16 @@ static void
test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
/* Check that D3DXCreateTextureFromFileInMemory accepts cube texture dds file (only
first face texture is loaded) */
hr = D3DXCreateTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map),
&texture);
- todo_wine_if (!has_2d_dxt5)
- ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected
%#x.\n", hr, D3D_OK);
- if (SUCCEEDED(hr))
+ ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected
%#x.\n", hr, D3D_OK);
+ type = IDirect3DTexture9_GetType(texture);
+ ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected
%u.\n", type, D3DRTYPE_TEXTURE);
+ hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
+ ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected
%#x.\n", hr, D3D_OK);
+ ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width);
+ ok(desc.Height == 4, "Height is %u, expected 4.\n", desc.Height);
+ if (has_cube_dxt5)
{
- type = IDirect3DTexture9_GetType(texture);
- ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u,
expected %u\n", type, D3DRTYPE_TEXTURE);
- hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
- ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected
%#x\n", hr, D3D_OK);
- ok(desc.Width == 4, "Width is %u, expected 4\n", desc.Width);
- ok(desc.Height == 4, "Height is %u, expected 4\n", desc.Height);
+ ok(desc.Format == D3DFMT_DXT5, "Unexpected texture format %#x.\n",
desc.Format);
hr = IDirect3DTexture9_LockRect(texture, 0, &lock_rect, NULL,
D3DLOCK_READONLY);
ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %#x, expected
%#x\n", hr, D3D_OK);
if (SUCCEEDED(hr))
@@ -1648,12 +1648,17 @@ static void
test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
i, ((BYTE *)lock_rect.pBits)[i], dds_cube_map[128 + i]);
IDirect3DTexture9_UnlockRect(texture, 0);
}
- IDirect3DTexture9_Release(texture);
}
+ else
+ {
+ ok(desc.Format == D3DFMT_A8R8G8B8, "Unexpected texture format %#x.\n",
desc.Format);
+ skip("D3DFMT_DXT5 textures are not supported, skipping a test.\n");
+ }
+ IDirect3DTexture9_Release(texture);
/* Test with a DXT5 texture smaller than the block size. */
hr = D3DXCreateTextureFromFileInMemory(device, dds_dxt5, sizeof(dds_dxt5),
&texture);
- todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr) && has_2d_dxt5)
{
type = IDirect3DTexture9_GetType(texture);
@@ -1709,7 +1714,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9
*device)
D3DPOOL_DEFAULT, &uncompressed_surface, NULL);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = D3DXLoadSurfaceFromSurface(uncompressed_surface, NULL, NULL, surface, NULL,
NULL, D3DX_FILTER_NONE, 0);
- todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
{
hr = IDirect3DSurface9_LockRect(uncompressed_surface, &lock_rect, NULL,
D3DLOCK_READONLY);
@@ -1739,28 +1744,25 @@ static void
test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
SetRect(&rect, 2, 2, 6, 6);
hr = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, &dds_dxt5_8_8[128],
D3DFMT_DXT5, 16 * 2, NULL, &rect, D3DX_FILTER_POINT, 0);
- todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
- if (SUCCEEDED(hr))
- {
- hr = D3DXLoadSurfaceFromSurface(uncompressed_surface, NULL, NULL, surface, NULL,
NULL, D3DX_FILTER_NONE, 0);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = D3DXLoadSurfaceFromSurface(uncompressed_surface, NULL, NULL, surface, NULL,
NULL, D3DX_FILTER_NONE, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
- hr = IDirect3DSurface9_LockRect(uncompressed_surface, &lock_rect, NULL,
D3DLOCK_READONLY);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
- for (y = 0; y < 8; ++y)
+ hr = IDirect3DSurface9_LockRect(uncompressed_surface, &lock_rect, NULL,
D3DLOCK_READONLY);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ for (y = 0; y < 8; ++y)
+ {
+ for (x = 0; x < 8; ++x)
{
- for (x = 0; x < 8; ++x)
- {
- ok(compare_color(((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y +
x],
- dds_dxt5_8_8_expected_misaligned_1[y * 8 + x], 0),
- "Color at position %u, %u is 0x%08x, expected
0x%08x.\n",
- x, y, ((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x],
- dds_dxt5_8_8_expected_misaligned_1[y * 8 + x]);
- }
+ ok(compare_color(((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x],
+ dds_dxt5_8_8_expected_misaligned_1[y * 8 + x], 0),
+ "Color at position %u, %u is 0x%08x, expected 0x%08x.\n",
+ x, y, ((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x],
+ dds_dxt5_8_8_expected_misaligned_1[y * 8 + x]);
}
- hr = IDirect3DSurface9_UnlockRect(uncompressed_surface);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
}
+ hr = IDirect3DSurface9_UnlockRect(uncompressed_surface);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DSurface9_LockRect(surface, &lock_rect, NULL, D3DLOCK_READONLY);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
@@ -1804,19 +1806,19 @@ static void
test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
/* Volume textures work too. */
hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_map,
sizeof(dds_volume_map), &texture);
- todo_wine_if (!has_2d_dxt3)
- ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected
%#x.\n", hr, D3D_OK);
- if (SUCCEEDED(hr))
- {
- type = IDirect3DTexture9_GetType(texture);
- ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u,
expected %u.\n", type, D3DRTYPE_TEXTURE);
- level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9
*)texture);
- todo_wine ok(level_count == 3, "Texture has %u mip levels, 3
expected.\n", level_count);
- hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
- ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected
%#x.\n", hr, D3D_OK);
- ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width);
- ok(desc.Height == 4, "Height is %u, expected 4.\n", desc.Height);
+ ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected
%#x.\n", hr, D3D_OK);
+ type = IDirect3DTexture9_GetType(texture);
+ ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected
%u.\n", type, D3DRTYPE_TEXTURE);
+ level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9 *)texture);
+ todo_wine ok(level_count == 3, "Texture has %u mip levels, 3 expected.\n",
level_count);
+ hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
+ ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected
%#x.\n", hr, D3D_OK);
+ ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width);
+ ok(desc.Height == 4, "Height is %u, expected 4.\n", desc.Height);
+ if (has_2d_dxt3)
+ {
+ ok(desc.Format == D3DFMT_DXT3, "Unexpected texture format %#x.\n",
desc.Format);
hr = IDirect3DTexture9_LockRect(texture, 0, &lock_rect, NULL,
D3DLOCK_READONLY);
ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %#x, expected
%#x.\n", hr, D3D_OK);
if (SUCCEEDED(hr))
@@ -1827,10 +1829,15 @@ static void
test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device)
i, ((BYTE *)lock_rect.pBits)[i], dds_volume_map[128 + i]);
IDirect3DTexture9_UnlockRect(texture, 0);
}
- /* The lower texture levels are apparently generated by filtering the level 0
surface
- * I.e. following levels from the file are ignored. */
- IDirect3DTexture9_Release(texture);
}
+ else
+ {
+ ok(desc.Format == D3DFMT_A8R8G8B8, "Unexpected texture format %#x.\n",
desc.Format);
+ skip("D3DFMT_DXT3 volume textures are not supported, skipping a
test.\n");
+ }
+ /* The lower texture levels are apparently generated by filtering the level 0
surface
+ * I.e. following levels from the file are ignored. */
+ IDirect3DTexture9_Release(texture);
}
static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device)
@@ -1985,7 +1992,7 @@ static void
test_D3DXCreateCubeTextureFromFileInMemory(IDirect3DDevice9 *device)
if (SUCCEEDED(hr))
{
levelcount = IDirect3DCubeTexture9_GetLevelCount(cube_texture);
- todo_wine ok(levelcount == 3, "GetLevelCount returned %u, expected
3\n", levelcount);
+ ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n",
levelcount);
hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr,
D3D_OK);
@@ -2010,8 +2017,7 @@ static void
test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic
hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map,
sizeof(dds_cube_map), D3DX_DEFAULT, D3DX_DEFAULT,
D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &cube_texture);
- todo_wine_if (!has_cube_dxt5)
- ok(hr == D3D_OK, "D3DXCreateCubeTextureFromFileInMemoryEx returned %#x,
expected %#x.\n", hr, D3D_OK);
+ ok(hr == D3D_OK, "D3DXCreateCubeTextureFromFileInMemoryEx returned %#x, expected
%#x.\n", hr, D3D_OK);
if (SUCCEEDED(hr)) IDirect3DCubeTexture9_Release(cube_texture);
}
@@ -2036,29 +2042,25 @@ static void
test_D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *devic
ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned
%#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map,
sizeof(dds_volume_map), &volume_texture);
- todo_wine_if (!has_3d_dxt3)
- ok(hr == D3D_OK, "D3DXCreateVolumeTextureFromFileInMemory returned %#x,
expected %#x\n", hr, D3D_OK);
- if (SUCCEEDED(hr))
- {
- levelcount = IDirect3DVolumeTexture9_GetLevelCount(volume_texture);
- ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n",
levelcount);
-
- hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
- ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr,
D3D_OK);
- ok(volume_desc.Width == 4, "Got width %u, expected 4\n",
volume_desc.Width);
- ok(volume_desc.Height == 4, "Got height %u, expected 4\n",
volume_desc.Height);
- ok(volume_desc.Depth == 2, "Got depth %u, expected 2\n",
volume_desc.Depth);
- ok(volume_desc.Pool == D3DPOOL_MANAGED, "Got pool %u, expected
D3DPOOL_MANAGED\n", volume_desc.Pool);
-
- hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 1, &volume_desc);
- ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr,
D3D_OK);
- ok(volume_desc.Width == 2, "Got width %u, expected 2\n",
volume_desc.Width);
- ok(volume_desc.Height == 2, "Got height %u, expected 2\n",
volume_desc.Height);
- ok(volume_desc.Depth == 1, "Got depth %u, expected 1\n",
volume_desc.Depth);
-
- ref = IDirect3DVolumeTexture9_Release(volume_texture);
- ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref);
- }
+ ok(hr == D3D_OK, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected
%#x.\n", hr, D3D_OK);
+ levelcount = IDirect3DVolumeTexture9_GetLevelCount(volume_texture);
+ ok(levelcount == 3, "GetLevelCount returned %u, expected 3.\n",
levelcount);
+
+ hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
+ ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x.\n", hr,
D3D_OK);
+ ok(volume_desc.Width == 4, "Got width %u, expected 4.\n",
volume_desc.Width);
+ ok(volume_desc.Height == 4, "Got height %u, expected 4.\n",
volume_desc.Height);
+ ok(volume_desc.Depth == 2, "Got depth %u, expected 2.\n",
volume_desc.Depth);
+ ok(volume_desc.Pool == D3DPOOL_MANAGED, "Got pool %u, expected
D3DPOOL_MANAGED.\n", volume_desc.Pool);
+
+ hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 1, &volume_desc);
+ ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x.\n", hr,
D3D_OK);
+ ok(volume_desc.Width == 2, "Got width %u, expected 2.\n",
volume_desc.Width);
+ ok(volume_desc.Height == 2, "Got height %u, expected 2.\n",
volume_desc.Height);
+ ok(volume_desc.Depth == 1, "Got depth %u, expected 1.\n",
volume_desc.Depth);
+
+ ref = IDirect3DVolumeTexture9_Release(volume_texture);
+ ok(ref == 0, "Invalid reference count. Got %u, expected 0.\n", ref);
}
/* fills positive x face with red color */
@@ -2511,14 +2513,14 @@ START_TEST(texture)
/* Check whether DXTn textures are supported. */
has_2d_dxt3 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
- hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5);
- has_2d_dxt5 = SUCCEEDED(hr);
- hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, D3DFMT_DXT5);
- has_cube_dxt5 = SUCCEEDED(hr);
+ has_2d_dxt5 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
+ D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
+ has_cube_dxt5 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
+ D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, D3DFMT_DXT5));
has_3d_dxt3 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, D3DFMT_DXT3));
+ trace("DXTn texture support: 2D DXT3 %#x, 2D DXT5 %#x, cube DXT5 %#x, 3D dxt3
%#x.\n",
+ has_2d_dxt3, has_2d_dxt5, has_cube_dxt5, has_3d_dxt3);
test_D3DXCheckTextureRequirements(device);
test_D3DXCheckCubeTextureRequirements(device);
diff --git a/sdk/tools/winesync/d3dx9.cfg b/sdk/tools/winesync/d3dx9.cfg
index cc418c43615..cad5dac2594 100644
--- a/sdk/tools/winesync/d3dx9.cfg
+++ b/sdk/tools/winesync/d3dx9.cfg
@@ -15,4 +15,4 @@ files: {include/d3dx9.h: sdk/include/dxsdk/d3dx9.h, include/d3dx9anim.h:
sdk/inc
include/d3dx9mesh.h: sdk/include/dxsdk/d3dx9mesh.h, include/d3dx9of.h:
sdk/include/dxsdk/d3dx9of.h,
include/d3dx9shader.h: sdk/include/dxsdk/d3dx9shader.h, include/d3dx9shape.h:
sdk/include/dxsdk/d3dx9shape.h,
include/d3dx9tex.h: sdk/include/dxsdk/d3dx9tex.h, include/d3dx9xof.h:
sdk/include/dxsdk/d3dx9xof.h}
-tags: {wine: 1f9243c757589c6ff2333794c3a44327d64855ae}
+tags: {wine: 376182062ff1ab8e7835fd67bc650da83c2cc75d}