utils.c 150 KB
Newer Older
1 2 3 4 5 6
/*
 * Utility functions for the WineD3D Library
 *
 * Copyright 2002-2004 Jason Edmeades
 * Copyright 2003-2004 Raphael Junqueira
 * Copyright 2004 Christian Costa
7
 * Copyright 2005 Oliver Stieber
8
 * Copyright 2006-2008 Henri Verbeet
9
 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10
 * Copyright 2009-2010 Henri Verbeet for CodeWeavers
11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
24
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 26 27
 */

#include "config.h"
Henri Verbeet's avatar
Henri Verbeet committed
28 29
#include "wine/port.h"

30 31 32 33
#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

34
struct wined3d_format_channels
35
{
36
    enum wined3d_format_id id;
37 38
    DWORD red_size, green_size, blue_size, alpha_size;
    DWORD red_offset, green_offset, blue_offset, alpha_offset;
39
    UINT bpp;
40
    BYTE depth_size, stencil_size;
41 42
};

43
static const struct wined3d_format_channels formats[] =
44
{
45 46 47
    /*                                          size            offset
     *  format id                           r   g   b   a    r   g   b   a    bpp depth stencil */
    {WINED3DFMT_UNKNOWN,                    0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
48
    /* FourCC formats */
49 50 51 52 53 54 55 56 57 58 59
    {WINED3DFMT_UYVY,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_YUY2,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_YV12,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_DXT1,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_DXT2,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_DXT3,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_DXT4,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_DXT5,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_MULTI2_ARGB8,               0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_G8R8_G8B8,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_R8G8_B8G8,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
60
    /* IEEE formats */
61 62 63 64
    {WINED3DFMT_R32_FLOAT,                 32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
    {WINED3DFMT_R32G32_FLOAT,              32, 32,  0,  0,   0, 32,  0,  0,    8,   0,     0},
    {WINED3DFMT_R32G32B32_FLOAT,           32, 32, 32,  0,   0, 32, 64,  0,   12,   0,     0},
    {WINED3DFMT_R32G32B32A32_FLOAT,        32, 32, 32, 32,   0, 32, 64, 96,   16,   0,     0},
65
    /* Hmm? */
66
    {WINED3DFMT_R8G8_SNORM_Cx,              0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
67
    /* Float */
68 69 70 71 72
    {WINED3DFMT_R16_FLOAT,                 16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_R16G16_FLOAT,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
    {WINED3DFMT_R16G16_SINT,               16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
    {WINED3DFMT_R16G16B16A16_FLOAT,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
    {WINED3DFMT_R16G16B16A16_SINT,         16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
73
    /* Palettized formats */
74 75
    {WINED3DFMT_P8_UINT_A8_UNORM,           0,  0,  0,  8,   0,  0,  0,  8,    2,   0,     0},
    {WINED3DFMT_P8_UINT,                    0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
76
    /* Standard ARGB formats. */
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    {WINED3DFMT_B8G8R8_UNORM,               8,  8,  8,  0,  16,  8,  0,  0,    3,   0,     0},
    {WINED3DFMT_B8G8R8A8_UNORM,             8,  8,  8,  8,  16,  8,  0, 24,    4,   0,     0},
    {WINED3DFMT_B8G8R8X8_UNORM,             8,  8,  8,  0,  16,  8,  0,  0,    4,   0,     0},
    {WINED3DFMT_B5G6R5_UNORM,               5,  6,  5,  0,  11,  5,  0,  0,    2,   0,     0},
    {WINED3DFMT_B5G5R5X1_UNORM,             5,  5,  5,  0,  10,  5,  0,  0,    2,   0,     0},
    {WINED3DFMT_B5G5R5A1_UNORM,             5,  5,  5,  1,  10,  5,  0, 15,    2,   0,     0},
    {WINED3DFMT_B4G4R4A4_UNORM,             4,  4,  4,  4,   8,  4,  0, 12,    2,   0,     0},
    {WINED3DFMT_B2G3R3_UNORM,               3,  3,  2,  0,   5,  2,  0,  0,    1,   0,     0},
    {WINED3DFMT_A8_UNORM,                   0,  0,  0,  8,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_B2G3R3A8_UNORM,             3,  3,  2,  8,   5,  2,  0,  8,    2,   0,     0},
    {WINED3DFMT_B4G4R4X4_UNORM,             4,  4,  4,  0,   8,  4,  0,  0,    2,   0,     0},
    {WINED3DFMT_R10G10B10A2_UNORM,         10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
    {WINED3DFMT_R10G10B10A2_UINT,          10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
    {WINED3DFMT_R10G10B10A2_SNORM,         10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
    {WINED3DFMT_R8G8B8A8_UNORM,             8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
    {WINED3DFMT_R8G8B8A8_UINT,              8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
    {WINED3DFMT_R8G8B8X8_UNORM,             8,  8,  8,  0,   0,  8, 16,  0,    4,   0,     0},
    {WINED3DFMT_R16G16_UNORM,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
    {WINED3DFMT_B10G10R10A2_UNORM,         10, 10, 10,  2,  20, 10,  0, 30,    4,   0,     0},
    {WINED3DFMT_R16G16B16A16_UNORM,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
97
    /* Luminance */
98 99 100 101
    {WINED3DFMT_L8_UNORM,                   0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_L8A8_UNORM,                 0,  0,  0,  8,   0,  0,  0,  8,    2,   0,     0},
    {WINED3DFMT_L4A4_UNORM,                 0,  0,  0,  4,   0,  0,  0,  4,    1,   0,     0},
    {WINED3DFMT_L16_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
102
    /* Bump mapping stuff */
103 104 105 106 107 108 109
    {WINED3DFMT_R8G8_SNORM,                 8,  8,  0,  0,   0,  8,  0,  0,    2,   0,     0},
    {WINED3DFMT_R5G5_SNORM_L6_UNORM,        5,  5,  0,  0,   0,  5,  0,  0,    2,   0,     0},
    {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,      8,  8,  0,  0,   0,  8,  0,  0,    4,   0,     0},
    {WINED3DFMT_R8G8B8A8_SNORM,             8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
    {WINED3DFMT_R16G16_SNORM,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
    {WINED3DFMT_R10G11B11_SNORM,           10, 11, 11,  0,   0, 10, 21,  0,    4,   0,     0},
    {WINED3DFMT_R10G10B10_SNORM_A2_UNORM,  10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
110
    /* Depth stencil formats */
111 112 113 114 115 116 117 118 119 120 121 122 123
    {WINED3DFMT_D16_LOCKABLE,               0,  0,  0,  0,   0,  0,  0,  0,    2,  16,     0},
    {WINED3DFMT_D32_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    4,  32,     0},
    {WINED3DFMT_S1_UINT_D15_UNORM,          0,  0,  0,  0,   0,  0,  0,  0,    2,  15,     1},
    {WINED3DFMT_D24_UNORM_S8_UINT,          0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
    {WINED3DFMT_X8D24_UNORM,                0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     0},
    {WINED3DFMT_S4X4_UINT_D24_UNORM,        0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     4},
    {WINED3DFMT_D16_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    2,  16,     0},
    {WINED3DFMT_D32_FLOAT,                  0,  0,  0,  0,   0,  0,  0,  0,    4,  32,     0},
    {WINED3DFMT_S8_UINT_D24_FLOAT,          0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
    {WINED3DFMT_VERTEXDATA,                 0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
    {WINED3DFMT_R16_UINT,                  16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_R32_UINT,                  32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
    {WINED3DFMT_R16G16B16A16_SNORM,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
124
    /* Vendor-specific formats */
125 126 127 128 129 130
    {WINED3DFMT_ATI2N,                      0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
    {WINED3DFMT_NVDB,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
    {WINED3DFMT_INTZ,                       0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
    {WINED3DFMT_NVHU,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_NVHS,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_NULL,                       8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
131
    /* Unsure about them, could not find a Windows driver that supports them */
132 133
    {WINED3DFMT_R16,                       16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
    {WINED3DFMT_AL16,                       0,  0,  0, 16,   0,  0,  0, 16,    4,   0,     0},
134 135 136 137
};

struct wined3d_format_base_flags
{
138
    enum wined3d_format_id id;
139 140 141
    DWORD flags;
};

142 143 144
/* The ATI2N format behaves like an uncompressed format in LockRect(), but
 * still needs to use the correct block based calculation for e.g. the
 * resource size. */
145 146
static const struct wined3d_format_base_flags format_base_flags[] =
{
147 148 149 150 151 152 153 154 155 156 157
    {WINED3DFMT_UYVY,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_YUY2,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_YV12,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_DXT1,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_DXT2,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_DXT3,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_DXT4,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_DXT5,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_MULTI2_ARGB8,       WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_G8R8_G8B8,          WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_R8G8_B8G8,          WINED3DFMT_FLAG_FOURCC},
158
    {WINED3DFMT_INTZ,               WINED3DFMT_FLAG_FOURCC},
159
    {WINED3DFMT_NULL,               WINED3DFMT_FLAG_FOURCC},
160 161 162 163 164 165 166 167 168 169 170
    {WINED3DFMT_P8_UINT,            WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B8G8R8_UNORM,       WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B8G8R8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B8G8R8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B5G6R5_UNORM,       WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B5G5R5X1_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B5G5R5A1_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B4G4R4A4_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_B4G4R4X4_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_R8G8B8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
    {WINED3DFMT_R8G8B8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
171
    {WINED3DFMT_ATI2N,              WINED3DFMT_FLAG_FOURCC | WINED3DFMT_FLAG_BROKEN_PITCH},
172
    {WINED3DFMT_NVDB,               WINED3DFMT_FLAG_FOURCC},
173 174 175 176 177 178 179 180 181 182 183
    {WINED3DFMT_NVHU,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_NVHS,               WINED3DFMT_FLAG_FOURCC},
    {WINED3DFMT_R32_FLOAT,          WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_R32G32_FLOAT,       WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_R32G32B32_FLOAT,    WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_R32G32B32A32_FLOAT, WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_R16_FLOAT,          WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_R16G16_FLOAT,       WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_R16G16B16A16_FLOAT, WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_D32_FLOAT,          WINED3DFMT_FLAG_FLOAT},
    {WINED3DFMT_S8_UINT_D24_FLOAT,  WINED3DFMT_FLAG_FLOAT},
184 185
};

186
struct wined3d_format_block_info
187
{
188
    enum wined3d_format_id id;
189 190 191 192 193
    UINT block_width;
    UINT block_height;
    UINT block_byte_count;
};

194
static const struct wined3d_format_block_info format_block_info[] =
195 196 197 198 199 200
{
    {WINED3DFMT_DXT1,   4,  4,  8},
    {WINED3DFMT_DXT2,   4,  4,  16},
    {WINED3DFMT_DXT3,   4,  4,  16},
    {WINED3DFMT_DXT4,   4,  4,  16},
    {WINED3DFMT_DXT5,   4,  4,  16},
201
    {WINED3DFMT_ATI2N,  4,  4,  16},
202 203
    {WINED3DFMT_YUY2,   2,  1,  4},
    {WINED3DFMT_UYVY,   2,  1,  4},
204 205
};

206 207
struct wined3d_format_vertex_info
{
208
    enum wined3d_format_id id;
209 210 211 212 213 214 215 216 217 218 219 220 221 222
    enum wined3d_ffp_emit_idx emit_idx;
    GLint component_count;
    GLenum gl_vtx_type;
    GLint gl_vtx_format;
    GLboolean gl_normalized;
    unsigned int component_size;
};

static const struct wined3d_format_vertex_info format_vertex_info[] =
{
    {WINED3DFMT_R32_FLOAT,          WINED3D_FFP_EMIT_FLOAT1,    1, GL_FLOAT,          1, GL_FALSE, sizeof(float)},
    {WINED3DFMT_R32G32_FLOAT,       WINED3D_FFP_EMIT_FLOAT2,    2, GL_FLOAT,          2, GL_FALSE, sizeof(float)},
    {WINED3DFMT_R32G32B32_FLOAT,    WINED3D_FFP_EMIT_FLOAT3,    3, GL_FLOAT,          3, GL_FALSE, sizeof(float)},
    {WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_FFP_EMIT_FLOAT4,    4, GL_FLOAT,          4, GL_FALSE, sizeof(float)},
223
    {WINED3DFMT_B8G8R8A8_UNORM,     WINED3D_FFP_EMIT_D3DCOLOR,  4, GL_UNSIGNED_BYTE,  4, GL_TRUE,  sizeof(BYTE)},
224 225 226 227 228 229 230 231 232 233 234 235 236 237
    {WINED3DFMT_R8G8B8A8_UINT,      WINED3D_FFP_EMIT_UBYTE4,    4, GL_UNSIGNED_BYTE,  4, GL_FALSE, sizeof(BYTE)},
    {WINED3DFMT_R16G16_SINT,        WINED3D_FFP_EMIT_SHORT2,    2, GL_SHORT,          2, GL_FALSE, sizeof(short int)},
    {WINED3DFMT_R16G16B16A16_SINT,  WINED3D_FFP_EMIT_SHORT4,    4, GL_SHORT,          4, GL_FALSE, sizeof(short int)},
    {WINED3DFMT_R8G8B8A8_UNORM,     WINED3D_FFP_EMIT_UBYTE4N,   4, GL_UNSIGNED_BYTE,  4, GL_TRUE,  sizeof(BYTE)},
    {WINED3DFMT_R16G16_SNORM,       WINED3D_FFP_EMIT_SHORT2N,   2, GL_SHORT,          2, GL_TRUE,  sizeof(short int)},
    {WINED3DFMT_R16G16B16A16_SNORM, WINED3D_FFP_EMIT_SHORT4N,   4, GL_SHORT,          4, GL_TRUE,  sizeof(short int)},
    {WINED3DFMT_R16G16_UNORM,       WINED3D_FFP_EMIT_USHORT2N,  2, GL_UNSIGNED_SHORT, 2, GL_TRUE,  sizeof(short int)},
    {WINED3DFMT_R16G16B16A16_UNORM, WINED3D_FFP_EMIT_USHORT4N,  4, GL_UNSIGNED_SHORT, 4, GL_TRUE,  sizeof(short int)},
    {WINED3DFMT_R10G10B10A2_UINT,   WINED3D_FFP_EMIT_UDEC3,     3, GL_UNSIGNED_SHORT, 3, GL_FALSE, sizeof(short int)},
    {WINED3DFMT_R10G10B10A2_SNORM,  WINED3D_FFP_EMIT_DEC3N,     3, GL_SHORT,          3, GL_TRUE,  sizeof(short int)},
    {WINED3DFMT_R16G16_FLOAT,       WINED3D_FFP_EMIT_FLOAT16_2, 2, GL_FLOAT,          2, GL_FALSE, sizeof(GLhalfNV)},
    {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_FLOAT,          4, GL_FALSE, sizeof(GLhalfNV)}
};

238 239
struct wined3d_format_texture_info
{
240
    enum wined3d_format_id id;
241 242 243 244 245
    GLint gl_internal;
    GLint gl_srgb_internal;
    GLint gl_rt_internal;
    GLint gl_format;
    GLint gl_type;
246
    unsigned int conv_byte_count;
247
    unsigned int flags;
248
    enum wined3d_gl_extension extension;
249
    void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height);
250
};
251

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not
     * format+type combination to load it. Thus convert it to A8L8, then load it
     * with A4L4 internal, but A8L8 format+type
     */
    unsigned int x, y;
    const unsigned char *Source;
    unsigned char *Dest;
    UINT outpitch = pitch * 2;

    for(y = 0; y < height; y++) {
        Source = src + y * pitch;
        Dest = dst + y * outpitch;
        for (x = 0; x < width; x++ ) {
            unsigned char color = (*Source++);
            /* A */ Dest[1] = (color & 0xf0) << 0;
            /* L */ Dest[0] = (color & 0x0f) << 4;
            Dest += 2;
        }
    }
}

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const WORD *Source;

    for(y = 0; y < height; y++)
    {
        unsigned short *Dest_s = (unsigned short *) (dst + y * pitch);
        Source = (const WORD *)(src + y * pitch);
        for (x = 0; x < width; x++ )
        {
            short color = (*Source++);
            unsigned char l = ((color >> 10) & 0xfc);
                    short v = ((color >>  5) & 0x3e);
                    short u = ((color      ) & 0x1f);
            short v_conv = v + 16;
            short u_conv = u + 16;

            *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
            Dest_s += 1;
        }
    }
}

static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const WORD *Source;
    unsigned char *Dest;
    UINT outpitch = (pitch * 3)/2;

    /* This makes the gl surface bigger(24 bit instead of 16), but it works with
     * fixed function and shaders without further conversion once the surface is
     * loaded
     */
    for(y = 0; y < height; y++) {
        Source = (const WORD *)(src + y * pitch);
        Dest = dst + y * outpitch;
        for (x = 0; x < width; x++ ) {
            short color = (*Source++);
            unsigned char l = ((color >> 10) & 0xfc);
                     char v = ((color >>  5) & 0x3e);
                     char u = ((color      ) & 0x1f);

            /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign
             * and doubles the positive range. Thus shift left only once, gl does the 2nd
             * shift. GL reads a signed value and converts it into an unsigned value.
             */
            /* M */ Dest[2] = l << 1;

            /* Those are read as signed, but kept signed. Just left-shift 3 times to scale
             * from 5 bit values to 8 bit values.
             */
            /* V */ Dest[1] = v << 3;
            /* U */ Dest[0] = u << 3;
            Dest += 3;
        }
    }
}

335 336 337 338 339 340 341 342 343 344 345 346 347
static void convert_r8g8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const short *Source;
    unsigned char *Dest;
    UINT outpitch = (pitch * 3)/2;

    for(y = 0; y < height; y++)
    {
        Source = (const short *)(src + y * pitch);
        Dest = dst + y * outpitch;
        for (x = 0; x < width; x++ )
        {
348
            const short color = (*Source++);
349 350
            /* B */ Dest[0] = 0xff;
            /* G */ Dest[1] = (color >> 8) + 128; /* V */
351
            /* R */ Dest[2] = (color & 0xff) + 128;      /* U */
352 353 354 355 356
            Dest += 3;
        }
    }
}

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
static void convert_r8g8_snorm_l8x8_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const DWORD *Source;
    unsigned char *Dest;

    /* Doesn't work correctly with the fixed function pipeline, but can work in
     * shaders if the shader is adjusted. (There's no use for this format in gl's
     * standard fixed function pipeline anyway).
     */
    for(y = 0; y < height; y++)
    {
        Source = (const DWORD *)(src + y * pitch);
        Dest = dst + y * pitch;
        for (x = 0; x < width; x++ )
        {
373
            LONG color = (*Source++);
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
            /* B */ Dest[0] = ((color >> 16) & 0xff);       /* L */
            /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
            /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
            Dest += 4;
        }
    }
}

static void convert_r8g8_snorm_l8x8_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const DWORD *Source;
    unsigned char *Dest;

    /* This implementation works with the fixed function pipeline and shaders
     * without further modification after converting the surface.
     */
    for(y = 0; y < height; y++)
    {
        Source = (const DWORD *)(src + y * pitch);
        Dest = dst + y * pitch;
        for (x = 0; x < width; x++ )
        {
397
            LONG color = (*Source++);
398 399 400 401 402 403 404 405 406
            /* L */ Dest[2] = ((color >> 16) & 0xff);   /* L */
            /* V */ Dest[1] = ((color >> 8 ) & 0xff);   /* V */
            /* U */ Dest[0] = (color         & 0xff);   /* U */
            /* I */ Dest[3] = 255;                      /* X */
            Dest += 4;
        }
    }
}

407 408 409 410 411 412 413 414 415 416 417 418
static void convert_r8g8b8a8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const DWORD *Source;
    unsigned char *Dest;

    for(y = 0; y < height; y++)
    {
        Source = (const DWORD *)(src + y * pitch);
        Dest = dst + y * pitch;
        for (x = 0; x < width; x++ )
        {
419
            LONG color = (*Source++);
420 421 422 423 424 425 426 427 428
            /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
            /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
            /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
            /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
            Dest += 4;
        }
    }
}

429 430 431 432 433 434 435 436 437 438 439 440 441
static void convert_r16g16_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const DWORD *Source;
    unsigned short *Dest;
    UINT outpitch = (pitch * 3)/2;

    for(y = 0; y < height; y++)
    {
        Source = (const DWORD *)(src + y * pitch);
        Dest = (unsigned short *) (dst + y * outpitch);
        for (x = 0; x < width; x++ )
        {
442
            const DWORD color = (*Source++);
443 444
            /* B */ Dest[0] = 0xffff;
            /* G */ Dest[1] = (color >> 16) + 32768; /* V */
445
            /* R */ Dest[2] = (color & 0xffff) + 32768; /* U */
446 447 448 449 450
            Dest += 3;
        }
    }
}

451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
static void convert_r16g16(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const WORD *Source;
    WORD *Dest;
    UINT outpitch = (pitch * 3)/2;

    for(y = 0; y < height; y++)
    {
        Source = (const WORD *)(src + y * pitch);
        Dest = (WORD *) (dst + y * outpitch);
        for (x = 0; x < width; x++ )
        {
            WORD green = (*Source++);
            WORD red = (*Source++);
            Dest[0] = green;
            Dest[1] = red;
            /* Strictly speaking not correct for R16G16F, but it doesn't matter because the
             * shader overwrites it anyway
             */
            Dest[2] = 0xffff;
            Dest += 3;
        }
    }
}

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
static void convert_r32g32_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    const float *Source;
    float *Dest;
    UINT outpitch = (pitch * 3)/2;

    for(y = 0; y < height; y++)
    {
        Source = (const float *)(src + y * pitch);
        Dest = (float *) (dst + y * outpitch);
        for (x = 0; x < width; x++ )
        {
            float green = (*Source++);
            float red = (*Source++);
            Dest[0] = green;
            Dest[1] = red;
            Dest[2] = 1.0f;
            Dest += 3;
        }
    }
}

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
static void convert_s1_uint_d15_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    UINT outpitch = pitch * 2;

    for (y = 0; y < height; ++y)
    {
        const WORD *source = (const WORD *)(src + y * pitch);
        DWORD *dest = (DWORD *)(dst + y * outpitch);

        for (x = 0; x < width; ++x)
        {
            /* The depth data is normalized, so needs to be scaled,
             * the stencil data isn't.  Scale depth data by
             *      (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */
            WORD d15 = source[x] >> 1;
            DWORD d24 = (d15 << 9) + (d15 >> 6);
            dest[x] = (d24 << 8) | (source[x] & 0x1);
        }
    }
}

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
static void convert_s4x4_uint_d24_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;

    for (y = 0; y < height; ++y)
    {
        const DWORD *source = (const DWORD *)(src + y * pitch);
        DWORD *dest = (DWORD *)(dst + y * pitch);

        for (x = 0; x < width; ++x)
        {
            /* Just need to clear out the X4 part. */
            dest[x] = source[x] & ~0xf0;
        }
    }
}

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
{
    unsigned int x, y;
    UINT outpitch = pitch * 2;

    for (y = 0; y < height; ++y)
    {
        const DWORD *source = (const DWORD *)(src + y * pitch);
        float *dest_f = (float *)(dst + y * outpitch);
        DWORD *dest_s = (DWORD *)(dst + y * outpitch);

        for (x = 0; x < width; ++x)
        {
            dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8);
            dest_s[x * 2 + 1] = source[x] & 0xff;
        }
    }
}

558 559
static const struct wined3d_format_texture_info format_texture_info[] =
{
560
    /* format id                        internal                          srgbInternal                       rtInternal
561
            format                      type
562 563
            flags
            extension */
564
    /* FourCC formats */
565 566 567
    /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type
     * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The
     * d3d9 test however shows that the opposite is true. Since the extension is from 2002, it predates the x86 based
568
     * Macs, so probably the endianness differs. This could be tested as soon as we have a Windows and MacOS on a big
569 570
     * endian machine
     */
571
    {WINED3DFMT_UYVY,                   GL_LUMINANCE_ALPHA,               GL_LUMINANCE_ALPHA,                     0,
572
            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
573
            WINED3DFMT_FLAG_FILTERING,
574
            WINED3D_GL_EXT_NONE,        NULL},
575
    {WINED3DFMT_UYVY,                   GL_RGB,                           GL_RGB,                                 0,
576
            GL_YCBCR_422_APPLE,         GL_UNSIGNED_SHORT_8_8_APPLE,      0,
577
            WINED3DFMT_FLAG_FILTERING,
578
            APPLE_YCBCR_422,            NULL},
579
    {WINED3DFMT_YUY2,                   GL_LUMINANCE_ALPHA,               GL_LUMINANCE_ALPHA,                     0,
580
            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
581
            WINED3DFMT_FLAG_FILTERING,
582
            WINED3D_GL_EXT_NONE,        NULL},
583
    {WINED3DFMT_YUY2,                   GL_RGB,                           GL_RGB,                                 0,
584
            GL_YCBCR_422_APPLE,         GL_UNSIGNED_SHORT_8_8_REV_APPLE,  0,
585
            WINED3DFMT_FLAG_FILTERING,
586
            APPLE_YCBCR_422,            NULL},
587
    {WINED3DFMT_YV12,                   GL_ALPHA,                         GL_ALPHA,                               0,
588
            GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
589
            WINED3DFMT_FLAG_FILTERING,
590
            WINED3D_GL_EXT_NONE,        NULL},
591
    {WINED3DFMT_DXT1,                   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
592
            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
593 594
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
            | WINED3DFMT_FLAG_COMPRESSED,
595
            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
596
    {WINED3DFMT_DXT2,                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
597
            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
598 599
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
            | WINED3DFMT_FLAG_COMPRESSED,
600
            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
601
    {WINED3DFMT_DXT3,                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
602
            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
603 604
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
            | WINED3DFMT_FLAG_COMPRESSED,
605
            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
606
    {WINED3DFMT_DXT4,                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
607
            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
608 609
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
            | WINED3DFMT_FLAG_COMPRESSED,
610
            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
611
    {WINED3DFMT_DXT5,                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
612
            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
613 614
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
            | WINED3DFMT_FLAG_COMPRESSED,
615
            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
616
    /* IEEE formats */
617
    {WINED3DFMT_R32_FLOAT,              GL_RGB32F_ARB,                    GL_RGB32F_ARB,                          0,
618
            GL_RED,                     GL_FLOAT,                         0,
619
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
620
            ARB_TEXTURE_FLOAT,          NULL},
621
    {WINED3DFMT_R32_FLOAT,              GL_R32F,                          GL_R32F,                                0,
622
            GL_RED,                     GL_FLOAT,                         0,
623
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
624
            ARB_TEXTURE_RG,             NULL},
625
    {WINED3DFMT_R32G32_FLOAT,           GL_RGB32F_ARB,                    GL_RGB32F_ARB,                          0,
626
            GL_RGB,                     GL_FLOAT,                         12,
627
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
628
            ARB_TEXTURE_FLOAT,          convert_r32g32_float},
629
    {WINED3DFMT_R32G32_FLOAT,           GL_RG32F,                         GL_RG32F,                               0,
630
            GL_RG,                      GL_FLOAT,                         0,
631
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
632
            ARB_TEXTURE_RG,             NULL},
633
    {WINED3DFMT_R32G32B32A32_FLOAT,     GL_RGBA32F_ARB,                   GL_RGBA32F_ARB,                         0,
634
            GL_RGBA,                    GL_FLOAT,                         0,
635
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
636
            ARB_TEXTURE_FLOAT,          NULL},
637
    /* Float */
638
    {WINED3DFMT_R16_FLOAT,              GL_RGB16F_ARB,                    GL_RGB16F_ARB,                          0,
639
            GL_RED,                     GL_HALF_FLOAT_ARB,                0,
640
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
641
            ARB_TEXTURE_FLOAT,          NULL},
642
    {WINED3DFMT_R16_FLOAT,              GL_R16F,                          GL_R16F,                                0,
643
            GL_RED,                     GL_HALF_FLOAT_ARB,                0,
644
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
645
            ARB_TEXTURE_RG,             NULL},
646
    {WINED3DFMT_R16G16_FLOAT,           GL_RGB16F_ARB,                    GL_RGB16F_ARB,                          0,
647
            GL_RGB,                     GL_HALF_FLOAT_ARB,                6,
648
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
649
            ARB_TEXTURE_FLOAT,          convert_r16g16},
650
    {WINED3DFMT_R16G16_FLOAT,           GL_RG16F,                         GL_RG16F,                               0,
651
            GL_RG,                      GL_HALF_FLOAT_ARB,                0,
652
            WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
653
            ARB_TEXTURE_RG,             NULL},
654
    {WINED3DFMT_R16G16B16A16_FLOAT,     GL_RGBA16F_ARB,                   GL_RGBA16F_ARB,                         0,
655
            GL_RGBA,                    GL_HALF_FLOAT_ARB,                0,
656
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
657
            ARB_TEXTURE_FLOAT,          NULL},
658
    /* Palettized formats */
659
    {WINED3DFMT_P8_UINT,                GL_RGBA,                          GL_RGBA,                                0,
660
            GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
661
            0,
662
            ARB_FRAGMENT_PROGRAM,       NULL},
663
    {WINED3DFMT_P8_UINT,                GL_COLOR_INDEX8_EXT,              GL_COLOR_INDEX8_EXT,                    0,
664
            GL_COLOR_INDEX,             GL_UNSIGNED_BYTE,                 0,
665
            0,
666
            EXT_PALETTED_TEXTURE,       NULL},
667
    /* Standard ARGB formats */
668
    {WINED3DFMT_B8G8R8_UNORM,           GL_RGB8,                          GL_RGB8,                                0,
669
            GL_BGR,                     GL_UNSIGNED_BYTE,                 0,
670
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
671
            WINED3D_GL_EXT_NONE,        NULL},
672
    {WINED3DFMT_B8G8R8A8_UNORM,         GL_RGBA8,                         GL_SRGB8_ALPHA8_EXT,                    0,
673
            GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
674
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET
675
            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE | WINED3DFMT_FLAG_VTF,
676
            WINED3D_GL_EXT_NONE,        NULL},
677
    {WINED3DFMT_B8G8R8X8_UNORM,         GL_RGB8,                          GL_SRGB8_EXT,                           0,
678
            GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
679
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET
680
            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE,
681
            WINED3D_GL_EXT_NONE,        NULL},
682
    {WINED3DFMT_B5G6R5_UNORM,           GL_RGB5,                          GL_RGB5,                          GL_RGB8,
683
            GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          0,
684
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
685
            WINED3D_GL_EXT_NONE,        NULL},
686
    {WINED3DFMT_B5G5R5X1_UNORM,         GL_RGB5,                          GL_RGB5_A1,                             0,
687
            GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
688
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
689
            WINED3D_GL_EXT_NONE,        NULL},
690
    {WINED3DFMT_B5G5R5A1_UNORM,         GL_RGB5_A1,                       GL_RGB5_A1,                             0,
691
            GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
692
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
693
            WINED3D_GL_EXT_NONE,        NULL},
694
    {WINED3DFMT_B4G4R4A4_UNORM,         GL_RGBA4,                         GL_SRGB8_ALPHA8_EXT,                    0,
695
            GL_BGRA,                    GL_UNSIGNED_SHORT_4_4_4_4_REV,    0,
696
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ,
697
            WINED3D_GL_EXT_NONE,        NULL},
698
    {WINED3DFMT_B2G3R3_UNORM,           GL_R3_G3_B2,                      GL_R3_G3_B2,                            0,
699
            GL_RGB,                     GL_UNSIGNED_BYTE_3_3_2,           0,
700
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
701
            WINED3D_GL_EXT_NONE,        NULL},
702
    {WINED3DFMT_A8_UNORM,               GL_ALPHA8,                        GL_ALPHA8,                              0,
703
            GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
704
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
705
            WINED3D_GL_EXT_NONE,        NULL},
706
    {WINED3DFMT_B4G4R4X4_UNORM,         GL_RGB4,                          GL_RGB4,                                0,
707
            GL_BGRA,                    GL_UNSIGNED_SHORT_4_4_4_4_REV,    0,
708
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
709
            WINED3D_GL_EXT_NONE,        NULL},
710
    {WINED3DFMT_R10G10B10A2_UNORM,      GL_RGB10_A2,                      GL_RGB10_A2,                            0,
711
            GL_RGBA,                    GL_UNSIGNED_INT_2_10_10_10_REV,   0,
712
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
713
            WINED3D_GL_EXT_NONE,        NULL},
714
    {WINED3DFMT_R8G8B8A8_UNORM,         GL_RGBA8,                         GL_RGBA8,                               0,
715
            GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
716
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
717
            WINED3D_GL_EXT_NONE,        NULL},
718
    {WINED3DFMT_R8G8B8X8_UNORM,         GL_RGB8,                          GL_RGB8,                                0,
719
            GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
720
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
721
            WINED3D_GL_EXT_NONE,        NULL},
722
    {WINED3DFMT_R16G16_UNORM,           GL_RGB16,                         GL_RGB16,                       GL_RGBA16,
723
            GL_RGB,                     GL_UNSIGNED_SHORT,                6,
724
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
725
            WINED3D_GL_EXT_NONE,        convert_r16g16},
726 727 728 729
    {WINED3DFMT_R16G16_UNORM,           GL_RG16,                          GL_RG16,                                0,
            GL_RG,                      GL_UNSIGNED_SHORT,                0,
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
            ARB_TEXTURE_RG,             NULL},
730
    {WINED3DFMT_B10G10R10A2_UNORM,      GL_RGB10_A2,                      GL_RGB10_A2,                            0,
731
            GL_BGRA,                    GL_UNSIGNED_INT_2_10_10_10_REV,   0,
732
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
733
            WINED3D_GL_EXT_NONE,        NULL},
734
    {WINED3DFMT_R16G16B16A16_UNORM,     GL_RGBA16,                        GL_RGBA16,                              0,
735
            GL_RGBA,                    GL_UNSIGNED_SHORT,                0,
736
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
737
            WINED3D_GL_EXT_NONE,        NULL},
738
    /* Luminance */
739
    {WINED3DFMT_L8_UNORM,               GL_LUMINANCE8,                    GL_SLUMINANCE8_EXT,                     0,
740
            GL_LUMINANCE,               GL_UNSIGNED_BYTE,                 0,
741
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ,
742
            WINED3D_GL_EXT_NONE,        NULL},
743
    {WINED3DFMT_L8A8_UNORM,             GL_LUMINANCE8_ALPHA8,             GL_SLUMINANCE8_ALPHA8_EXT,              0,
744
            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
745
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ,
746
            WINED3D_GL_EXT_NONE,        NULL},
747
    {WINED3DFMT_L4A4_UNORM,             GL_LUMINANCE4_ALPHA4,             GL_LUMINANCE4_ALPHA4,                   0,
748
            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 2,
749
            WINED3DFMT_FLAG_FILTERING,
750
            WINED3D_GL_EXT_NONE,        convert_l4a4_unorm},
751
    /* Bump mapping stuff */
752
    {WINED3DFMT_R8G8_SNORM,             GL_RGB8,                          GL_RGB8,                                0,
753
            GL_BGR,                     GL_UNSIGNED_BYTE,                 3,
754
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
755
            WINED3D_GL_EXT_NONE,        convert_r8g8_snorm},
756
    {WINED3DFMT_R8G8_SNORM,             GL_DSDT8_NV,                      GL_DSDT8_NV,                            0,
757
            GL_DSDT_NV,                 GL_BYTE,                          0,
758
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
759
            NV_TEXTURE_SHADER,          NULL},
760
    {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_RGB5,                          GL_RGB5,                                0,
761
            GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          2,
762
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
763
            WINED3D_GL_EXT_NONE,        convert_r5g5_snorm_l6_unorm},
764
    {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_DSDT8_MAG8_NV,                 GL_DSDT8_MAG8_NV,                       0,
765
            GL_DSDT_MAG_NV,             GL_BYTE,                          3,
766
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
767
            NV_TEXTURE_SHADER,          convert_r5g5_snorm_l6_unorm_nv},
768
    {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,  GL_RGB8,                          GL_RGB8,                                0,
769
            GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      4,
770
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
771
            WINED3D_GL_EXT_NONE,        convert_r8g8_snorm_l8x8_unorm},
772
    {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,  GL_DSDT8_MAG8_INTENSITY8_NV,      GL_DSDT8_MAG8_INTENSITY8_NV,            0,
773
            GL_DSDT_MAG_VIB_NV,         GL_UNSIGNED_INT_8_8_S8_S8_REV_NV, 4,
774
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
775
            NV_TEXTURE_SHADER,          convert_r8g8_snorm_l8x8_unorm_nv},
776
    {WINED3DFMT_R8G8B8A8_SNORM,         GL_RGBA8,                         GL_RGBA8,                               0,
777
            GL_BGRA,                    GL_UNSIGNED_BYTE,                 4,
778
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
779
            WINED3D_GL_EXT_NONE,        convert_r8g8b8a8_snorm},
780
    {WINED3DFMT_R8G8B8A8_SNORM,         GL_SIGNED_RGBA8_NV,               GL_SIGNED_RGBA8_NV,                     0,
781
            GL_RGBA,                    GL_BYTE,                          0,
782
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
783
            NV_TEXTURE_SHADER,          NULL},
784
    {WINED3DFMT_R16G16_SNORM,           GL_RGB16,                         GL_RGB16,                               0,
785
            GL_BGR,                     GL_UNSIGNED_SHORT,                6,
786
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
787
            WINED3D_GL_EXT_NONE,        convert_r16g16_snorm},
788
    {WINED3DFMT_R16G16_SNORM,           GL_SIGNED_HILO16_NV,              GL_SIGNED_HILO16_NV,                    0,
789
            GL_HILO_NV,                 GL_SHORT,                         0,
790
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
791
            NV_TEXTURE_SHADER,          NULL},
792
    /* Depth stencil formats */
793
    {WINED3DFMT_D16_LOCKABLE,           GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
794
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
795
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
796
            ARB_DEPTH_TEXTURE,          NULL},
797
    {WINED3DFMT_D32_UNORM,              GL_DEPTH_COMPONENT32_ARB,         GL_DEPTH_COMPONENT32_ARB,               0,
798
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
799
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
800
            ARB_DEPTH_TEXTURE,          NULL},
801
    {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
802
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
803
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
804
            ARB_DEPTH_TEXTURE,          NULL},
805
    {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
806
            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         4,
807
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
808
            EXT_PACKED_DEPTH_STENCIL,   convert_s1_uint_d15_unorm},
809
    {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
810
            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             4,
811
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
812
            ARB_FRAMEBUFFER_OBJECT,     convert_s1_uint_d15_unorm},
813
    {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
814
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
815 816
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_SHADOW,
817
            ARB_DEPTH_TEXTURE,          NULL},
818
    {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
819
            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         0,
820 821
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
822
            EXT_PACKED_DEPTH_STENCIL,   NULL},
823
    {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
824
            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             0,
825 826
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
827
            ARB_FRAMEBUFFER_OBJECT,     NULL},
828
    {WINED3DFMT_X8D24_UNORM,            GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
829
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
830 831
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_SHADOW,
832
            ARB_DEPTH_TEXTURE,          NULL},
833
    {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
834
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
835
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
836
            ARB_DEPTH_TEXTURE,          NULL},
837
    {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
838
            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         4,
839
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
840
            EXT_PACKED_DEPTH_STENCIL,   convert_s4x4_uint_d24_unorm},
841
    {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
842
            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             4,
843
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
844
            ARB_FRAMEBUFFER_OBJECT,     convert_s4x4_uint_d24_unorm},
845
    {WINED3DFMT_D16_UNORM,              GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
846
            GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
847 848
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_SHADOW,
849
            ARB_DEPTH_TEXTURE,          NULL},
850
    {WINED3DFMT_L16_UNORM,              GL_LUMINANCE16,                   GL_LUMINANCE16,                         0,
851
            GL_LUMINANCE,               GL_UNSIGNED_SHORT,                0,
852
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
853
            WINED3D_GL_EXT_NONE,        NULL},
854
    {WINED3DFMT_D32_FLOAT,              GL_DEPTH_COMPONENT32F,            GL_DEPTH_COMPONENT32F,                  0,
855
            GL_DEPTH_COMPONENT,         GL_FLOAT,                         0,
856
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
857
            ARB_DEPTH_BUFFER_FLOAT,     NULL},
858
    {WINED3DFMT_S8_UINT_D24_FLOAT,      GL_DEPTH32F_STENCIL8,             GL_DEPTH32F_STENCIL8,                   0,
859
            GL_DEPTH_STENCIL,           GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8,
860
            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
861
            ARB_DEPTH_BUFFER_FLOAT,     convert_s8_uint_d24_float},
862
    /* Vendor-specific formats */
863
    {WINED3DFMT_ATI2N,                  GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0,
864
            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
865
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED,
866
            ATI_TEXTURE_COMPRESSION_3DC, NULL},
867
    {WINED3DFMT_ATI2N,                  GL_COMPRESSED_RG_RGTC2,           GL_COMPRESSED_RG_RGTC2,                 0,
868
            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
869
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED,
870
            ARB_TEXTURE_COMPRESSION_RGTC, NULL},
871 872 873 874 875 876 877 878 879 880
    {WINED3DFMT_INTZ,                   GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         0,
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_STENCIL,
            EXT_PACKED_DEPTH_STENCIL,   NULL},
    {WINED3DFMT_INTZ,                   GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             0,
            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
            | WINED3DFMT_FLAG_STENCIL,
            ARB_FRAMEBUFFER_OBJECT,     NULL},
881 882 883 884
    {WINED3DFMT_NULL,                   GL_RGBA8,                         GL_RGBA8,                               0,
            GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
            WINED3DFMT_FLAG_RENDERTARGET,
            ARB_FRAMEBUFFER_OBJECT,     NULL},
885 886
};

887 888
static inline int getFmtIdx(enum wined3d_format_id format_id)
{
889
    /* First check if the format is at the position of its value.
890 891 892 893 894 895 896 897
     * This will catch the argb formats before the loop is entered. */
    if (format_id < (sizeof(formats) / sizeof(*formats))
            && formats[format_id].id == format_id)
    {
        return format_id;
    }
    else
    {
898
        unsigned int i;
899 900 901 902

        for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
        {
            if (formats[i].id == format_id) return i;
903 904
        }
    }
905 906 907
    return -1;
}

908
static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
909 910 911 912
{
    UINT format_count = sizeof(formats) / sizeof(*formats);
    UINT i;

913 914
    gl_info->formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, format_count * sizeof(*gl_info->formats));
    if (!gl_info->formats)
915 916 917 918 919 920 921
    {
        ERR("Failed to allocate memory.\n");
        return FALSE;
    }

    for (i = 0; i < format_count; ++i)
    {
922 923
        struct wined3d_format *format = &gl_info->formats[i];
        format->id = formats[i].id;
924 925 926 927 928 929 930 931
        format->red_size = formats[i].red_size;
        format->green_size = formats[i].green_size;
        format->blue_size = formats[i].blue_size;
        format->alpha_size = formats[i].alpha_size;
        format->red_offset = formats[i].red_offset;
        format->green_offset = formats[i].green_offset;
        format->blue_offset = formats[i].blue_offset;
        format->alpha_offset = formats[i].alpha_offset;
932
        format->byte_count = formats[i].bpp;
933 934
        format->depth_size = formats[i].depth_size;
        format->stencil_size = formats[i].stencil_size;
935 936 937
        format->block_width = 1;
        format->block_height = 1;
        format->block_byte_count = formats[i].bpp;
938 939 940 941
    }

    for (i = 0; i < (sizeof(format_base_flags) / sizeof(*format_base_flags)); ++i)
    {
942
        int fmt_idx = getFmtIdx(format_base_flags[i].id);
943 944 945 946

        if (fmt_idx == -1)
        {
            ERR("Format %s (%#x) not found.\n",
947
                    debug_d3dformat(format_base_flags[i].id), format_base_flags[i].id);
948
            HeapFree(GetProcessHeap(), 0, gl_info->formats);
949 950 951
            return FALSE;
        }

952
        gl_info->formats[fmt_idx].flags |= format_base_flags[i].flags;
953 954 955 956 957
    }

    return TRUE;
}

958
static BOOL init_format_block_info(struct wined3d_gl_info *gl_info)
959 960 961
{
    unsigned int i;

962
    for (i = 0; i < (sizeof(format_block_info) / sizeof(*format_block_info)); ++i)
963
    {
964
        struct wined3d_format *format;
965
        int fmt_idx = getFmtIdx(format_block_info[i].id);
966 967 968 969

        if (fmt_idx == -1)
        {
            ERR("Format %s (%#x) not found.\n",
970
                    debug_d3dformat(format_block_info[i].id), format_block_info[i].id);
971 972 973
            return FALSE;
        }

974
        format = &gl_info->formats[fmt_idx];
975 976 977 978
        format->block_width = format_block_info[i].block_width;
        format->block_height = format_block_info[i].block_height;
        format->block_byte_count = format_block_info[i].block_byte_count;
        format->flags |= WINED3DFMT_FLAG_BLOCKS;
979 980 981 982 983
    }

    return TRUE;
}

984
/* Context activation is done by the caller. */
985
static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format *format)
986
{
987 988 989 990
    /* Check if the default internal format is supported as a frame buffer
     * target, otherwise fall back to the render target internal.
     *
     * Try to stick to the standard format if possible, this limits precision differences. */
991
    GLenum status;
992
    GLuint tex;
993

994 995
    while (gl_info->gl_ops.gl.p_glGetError());
    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
996

997 998
    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
999

1000 1001 1002 1003
    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glInternal, 16, 16, 0,
            format->glFormat, format->glType, NULL);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1004

1005
    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1006

1007
    status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
1008 1009
    checkGLcall("Framebuffer format check");

1010
    if (status == GL_FRAMEBUFFER_COMPLETE)
1011
    {
1012
        TRACE("Format %s is supported as FBO color attachment.\n", debug_d3dformat(format->id));
1013
        format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
1014
        format->rtInternal = format->glInternal;
1015 1016 1017
    }
    else
    {
1018
        if (!format->rtInternal)
1019
        {
1020
            if (format->flags & WINED3DFMT_FLAG_RENDERTARGET)
1021 1022
            {
                FIXME("Format %s with rendertarget flag is not supported as FBO color attachment,"
1023
                        " and no fallback specified.\n", debug_d3dformat(format->id));
1024
                format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
1025 1026 1027
            }
            else
            {
1028
                TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format->id));
1029
            }
1030
            format->rtInternal = format->glInternal;
1031 1032 1033 1034
        }
        else
        {
            TRACE("Format %s is not supported as FBO color attachment, trying rtInternal format as fallback.\n",
1035
                    debug_d3dformat(format->id));
1036

1037
            while (gl_info->gl_ops.gl.p_glGetError());
1038

1039
            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1040

1041 1042 1043 1044
            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->rtInternal, 16, 16, 0,
                    format->glFormat, format->glType, NULL);
            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1045

1046
            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1047

1048
            status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
1049 1050
            checkGLcall("Framebuffer format check");

1051
            if (status == GL_FRAMEBUFFER_COMPLETE)
1052
            {
1053
                TRACE("Format %s rtInternal format is supported as FBO color attachment.\n",
1054
                        debug_d3dformat(format->id));
1055 1056 1057 1058
            }
            else
            {
                FIXME("Format %s rtInternal format is not supported as FBO color attachment.\n",
1059
                        debug_d3dformat(format->id));
1060
                format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
1061 1062 1063 1064
            }
        }
    }

1065
    if (status == GL_FRAMEBUFFER_COMPLETE && ((format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
1066 1067
            || !(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
            && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
1068 1069
            && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
            && (format->red_size || format->alpha_size))
1070
    {
1071
        GLuint rb, tex2;
1072
        DWORD readback[16 * 16], color, r_range, a_range;
1073 1074
        BYTE r, a;
        BOOL match = TRUE;
1075

1076 1077
        if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
                || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
1078
        {
1079 1080 1081 1082 1083
            gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
            gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
            gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
1084 1085 1086
            checkGLcall("RB attachment");
        }

1087 1088 1089 1090
        gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
        gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
        if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
1091
        {
1092
            while (gl_info->gl_ops.gl.p_glGetError());
1093
            TRACE("Format doesn't support post-pixelshader blending.\n");
1094
            format->flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
1095
        }
1096
        else
1097
        {
1098
            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
1099 1100 1101 1102 1103 1104
            gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
            gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
            gl_info->gl_ops.gl.p_glLoadIdentity();
            gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
            gl_info->gl_ops.gl.p_glLoadIdentity();
1105

1106
            gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1107 1108

            /* Draw a full-black quad */
1109
            gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
1110
            gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1111 1112 1113 1114 1115
            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glEnd();
1116

1117
            gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
1118
            /* Draw a half-transparent red quad */
1119
            gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
1120
            gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
1121 1122 1123 1124 1125 1126
            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
            gl_info->gl_ops.gl.p_glEnd();

1127
            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
1128 1129 1130 1131 1132
            gl_info->gl_ops.gl.p_glGenTextures(1, &tex2);
            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex2);

            gl_info->gl_ops.gl.p_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 16, 16, 0);
            gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
1133 1134 1135 1136 1137 1138
            checkGLcall("Post-pixelshader blending check");

            color = readback[7 * 16 + 7];
            a = color >> 24;
            r = (color & 0x00ff0000) >> 16;

1139 1140 1141
            r_range = format->red_size < 8 ? 1 << (8 - format->red_size) : 1;
            a_range = format->alpha_size < 8 ? 1 << (8 - format->alpha_size) : 1;
            if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
1142
                match = FALSE;
1143
            else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
                match = FALSE;
            if (!match)
            {
                TRACE("Format doesn't support post-pixelshader blending.\n");
                TRACE("Color output: %#x\n", color);
                format->flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
            }
            else
            {
                TRACE("Format supports post-pixelshader blending.\n");
1154
                TRACE("Color output: %#x\n", color);
1155 1156
                format->flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
            }
1157

1158 1159
            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
            gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex2);
1160
        }
1161

1162 1163
        if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
                || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
1164
        {
1165 1166 1167
            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
            gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
1168 1169 1170 1171
            checkGLcall("RB cleanup");
        }
    }

1172
    if (format->glInternal != format->glGammaInternal)
1173
    {
1174 1175
        gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glGammaInternal, 16, 16, 0,
                format->glFormat, format->glType, NULL);
1176 1177 1178 1179 1180 1181 1182
        gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);

        status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
        checkGLcall("Framebuffer format check");

        if (status == GL_FRAMEBUFFER_COMPLETE)
        {
1183
            TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format->id));
1184
            format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
1185 1186 1187
        }
        else
        {
1188
            WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format->id));
1189 1190
        }
    }
1191 1192
    else if (status == GL_FRAMEBUFFER_COMPLETE)
        format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
1193

1194
    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
1195 1196
}

1197
/* Context activation is done by the caller. */
1198
static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
1199 1200
{
    unsigned int i;
1201 1202 1203 1204
    GLuint fbo;

    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
    {
1205 1206
        gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
        gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1207 1208
        gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
        gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
1209
    }
1210 1211 1212

    for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
    {
1213
        struct wined3d_format *format = &gl_info->formats[i];
1214

1215
        if (!format->glInternal) continue;
1216

1217
        if (format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
1218 1219
        {
            TRACE("Skipping format %s because it's a depth/stencil format.\n",
1220
                    debug_d3dformat(format->id));
1221 1222 1223
            continue;
        }

1224
        if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
1225 1226
        {
            TRACE("Skipping format %s because it's a compressed format.\n",
1227
                    debug_d3dformat(format->id));
1228 1229 1230
            continue;
        }

1231
        if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1232
        {
1233 1234
            TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
            check_fbo_compat(gl_info, format);
1235 1236 1237
        }
        else
        {
1238
            format->rtInternal = format->glInternal;
1239 1240
        }
    }
1241 1242

    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1243
        gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
1244 1245
}

1246
static BOOL init_format_texture_info(struct wined3d_gl_info *gl_info)
1247 1248 1249
{
    unsigned int i;

1250
    for (i = 0; i < sizeof(format_texture_info) / sizeof(*format_texture_info); ++i)
1251
    {
1252
        int fmt_idx = getFmtIdx(format_texture_info[i].id);
1253
        struct wined3d_format *format;
1254

1255 1256 1257
        if (fmt_idx == -1)
        {
            ERR("Format %s (%#x) not found.\n",
1258
                    debug_d3dformat(format_texture_info[i].id), format_texture_info[i].id);
1259 1260 1261
            return FALSE;
        }

1262
        if (!gl_info->supported[format_texture_info[i].extension]) continue;
1263

1264
        format = &gl_info->formats[fmt_idx];
1265 1266 1267 1268

        /* ARB_texture_rg defines floating point formats, but only if
         * ARB_texture_float is also supported. */
        if (!gl_info->supported[ARB_TEXTURE_FLOAT]
1269
                && (format->flags & WINED3DFMT_FLAG_FLOAT))
1270 1271
            continue;

1272 1273 1274 1275 1276 1277
        format->glInternal = format_texture_info[i].gl_internal;
        format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
        format->rtInternal = format_texture_info[i].gl_rt_internal;
        format->glFormat = format_texture_info[i].gl_format;
        format->glType = format_texture_info[i].gl_type;
        format->color_fixup = COLOR_FIXUP_IDENTITY;
1278
        format->flags |= format_texture_info[i].flags;
1279 1280
        format->height_scale.numerator = 1;
        format->height_scale.denominator = 1;
1281

1282
        if (format->glGammaInternal != format->glInternal)
1283
        {
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
            /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
            if (!gl_info->supported[EXT_TEXTURE_SRGB])
            {
                format->glGammaInternal = format->glInternal;
                format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
            }
            else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
            {
                format->glInternal = format->glGammaInternal;
            }
1294 1295
        }

1296
        /* Texture conversion stuff */
1297 1298
        format->convert = format_texture_info[i].convert;
        format->conv_byte_count = format_texture_info[i].conv_byte_count;
1299
    }
1300 1301

    return TRUE;
1302 1303
}

1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff)
{
    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
    c1 >>= 8; c2 >>= 8;
    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
    c1 >>= 8; c2 >>= 8;
    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
    c1 >>= 8; c2 >>= 8;
    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
    return TRUE;
}

/* A context is provided by the caller */
static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal)
{
1319
    static const DWORD data[] = {0x00000000, 0xffffffff};
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
    GLuint tex, fbo, buffer;
    DWORD readback[16 * 1];
    BOOL ret = FALSE;

    /* Render a filtered texture and see what happens. This is intended to detect the lack of
     * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of
     * falling back to software. If this changes in the future this code will get fooled and
     * apps might hit the software path due to incorrectly advertised caps.
     *
     * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter
     * disable fallback, if Apple or ATI ever change the driver behavior they will break more
     * than Wine. The Linux binary <= r500 driver is not maintained any more anyway
     */

1334
    while (gl_info->gl_ops.gl.p_glGetError());
1335

1336 1337
    gl_info->gl_ops.gl.p_glGenTextures(1, &buffer);
    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
1338
    memset(readback, 0x7e, sizeof(readback));
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0,
            GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0,
            GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
1357

1358 1359 1360
    gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer, 0);
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
    gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);

    gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
    gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
    gl_info->gl_ops.gl.p_glLoadIdentity();
    gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
    gl_info->gl_ops.gl.p_glLoadIdentity();

    gl_info->gl_ops.gl.p_glClearColor(0, 1, 0, 0);
    gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);

    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
    gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 0.0);
    gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
    gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 0.0);
    gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
    gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 1.0);
    gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
    gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 1.0);
    gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
    gl_info->gl_ops.gl.p_glEnd();

    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
1385
    memset(readback, 0x7f, sizeof(readback));
1386 1387 1388
    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
    if (color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5)
            || color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5))
1389
    {
1390
        TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, assuming no filtering\n",
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
              readback[6], readback[9]);
        ret = FALSE;
    }
    else
    {
        TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n",
              readback[6], readback[9]);
        ret = TRUE;
    }

1401 1402
    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
1403 1404
    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
    gl_info->gl_ops.gl.p_glDeleteTextures(1, &buffer);
1405

1406
    if (gl_info->gl_ops.gl.p_glGetError())
1407 1408 1409 1410
    {
        FIXME("Error during filtering test for format %x, returning no filtering\n", internal);
        ret = FALSE;
    }
1411

1412 1413 1414
    return ret;
}

1415
static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor)
1416
{
1417
    struct wined3d_format *format;
1418
    unsigned int fmt_idx, i;
1419
    static const enum wined3d_format_id fmts16[] =
1420
    {
1421 1422 1423 1424 1425 1426 1427 1428 1429
        WINED3DFMT_R16_FLOAT,
        WINED3DFMT_R16G16_FLOAT,
        WINED3DFMT_R16G16B16A16_FLOAT,
    };
    BOOL filtered;

    if(wined3d_settings.offscreen_rendering_mode != ORM_FBO)
    {
        WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
1430
        if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
1431 1432 1433 1434
        {
            TRACE("Nvidia card with texture_float support: Assuming float16 blending\n");
            filtered = TRUE;
        }
1435
        else if (gl_info->limits.glsl_varyings > 44)
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
        {
            TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n");
            filtered = TRUE;
        }
        else
        {
            TRACE("Assuming no float16 blending\n");
            filtered = FALSE;
        }

        if(filtered)
        {
            for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++)
            {
                fmt_idx = getFmtIdx(fmts16[i]);
1451
                gl_info->formats[fmt_idx].flags |= WINED3DFMT_FLAG_FILTERING;
1452 1453 1454 1455 1456 1457 1458 1459
            }
        }
        return;
    }

    for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++)
    {
        fmt_idx = getFmtIdx(fmts16[i]);
1460 1461
        format = &gl_info->formats[fmt_idx];
        if (!format->glInternal) continue; /* Not supported by GL */
1462

1463
        filtered = check_filter(gl_info, gl_info->formats[fmt_idx].glInternal);
1464 1465 1466
        if(filtered)
        {
            TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i]));
1467
            format->flags |= WINED3DFMT_FLAG_FILTERING;
1468 1469 1470 1471 1472 1473 1474 1475
        }
        else
        {
            TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i]));
        }
    }
}

1476
static void apply_format_fixups(struct wined3d_gl_info *gl_info)
1477
{
1478
    int idx;
1479

1480
    idx = getFmtIdx(WINED3DFMT_R16_FLOAT);
1481
    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1482 1483
            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);

1484
    idx = getFmtIdx(WINED3DFMT_R32_FLOAT);
1485
    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1486 1487
            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);

1488
    idx = getFmtIdx(WINED3DFMT_R16G16_UNORM);
1489
    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1490 1491
            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);

1492
    idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
1493
    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1494 1495
            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);

1496
    idx = getFmtIdx(WINED3DFMT_R32G32_FLOAT);
1497
    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1498 1499
            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);

1500 1501
    /* V8U8 is supported natively by GL_ATI_envmap_bumpmap and GL_NV_texture_shader.
     * V16U16 is only supported by GL_NV_texture_shader. The formats need fixup if
1502 1503
     * their extensions are not available. GL_ATI_envmap_bumpmap is not used because
     * the only driver that implements it(fglrx) has a buggy implementation.
1504
     *
1505 1506 1507
     * V8U8 and V16U16 need a fixup of the undefined blue channel. OpenGL
     * returns 0.0 when sampling from it, DirectX 1.0. So we always have in-shader
     * conversion for this format.
1508
     */
1509
    if (!gl_info->supported[NV_TEXTURE_SHADER])
1510
    {
1511
        idx = getFmtIdx(WINED3DFMT_R8G8_SNORM);
1512
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1513
                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1514
        idx = getFmtIdx(WINED3DFMT_R16G16_SNORM);
1515
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1516 1517 1518 1519
                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
    }
    else
    {
1520
        idx = getFmtIdx(WINED3DFMT_R8G8_SNORM);
1521
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1522
                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1523

1524
        idx = getFmtIdx(WINED3DFMT_R16G16_SNORM);
1525
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1526 1527
                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
    }
1528

1529
    if (!gl_info->supported[NV_TEXTURE_SHADER])
1530
    {
1531 1532 1533
        /* If GL_NV_texture_shader is not supported, those formats are converted, incompatibly
         * with each other
         */
1534
        idx = getFmtIdx(WINED3DFMT_R5G5_SNORM_L6_UNORM);
1535
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1536
                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE);
1537
        idx = getFmtIdx(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
1538
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1539
                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W);
1540
        idx = getFmtIdx(WINED3DFMT_R8G8B8A8_SNORM);
1541
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1542
                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 1, CHANNEL_SOURCE_Z, 1, CHANNEL_SOURCE_W);
1543 1544 1545
    }
    else
    {
1546 1547 1548 1549 1550
        /* If GL_NV_texture_shader is supported, WINED3DFMT_L6V5U5 and WINED3DFMT_X8L8V8U8
         * are converted at surface loading time, but they do not need any modification in
         * the shader, thus they are compatible with all WINED3DFMT_UNKNOWN group formats.
         * WINED3DFMT_Q8W8V8U8 doesn't even need load-time conversion
         */
1551 1552
    }

1553
    if (gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
1554 1555
    {
        idx = getFmtIdx(WINED3DFMT_ATI2N);
1556
        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1557
                0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1558
    }
1559
    else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
1560 1561
    {
        idx = getFmtIdx(WINED3DFMT_ATI2N);
1562
        gl_info->formats[idx].color_fixup= create_color_fixup_desc(
1563
                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1564 1565
    }

1566
    if (!gl_info->supported[APPLE_YCBCR_422])
1567 1568
    {
        idx = getFmtIdx(WINED3DFMT_YUY2);
1569
        gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
1570 1571

        idx = getFmtIdx(WINED3DFMT_UYVY);
1572
        gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
1573 1574 1575
    }

    idx = getFmtIdx(WINED3DFMT_YV12);
1576
    gl_info->formats[idx].flags |= WINED3DFMT_FLAG_HEIGHT_SCALE;
1577 1578
    gl_info->formats[idx].height_scale.numerator = 3;
    gl_info->formats[idx].height_scale.denominator = 2;
1579
    gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
1580

1581 1582 1583
    if (gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM])
    {
        idx = getFmtIdx(WINED3DFMT_P8_UINT);
1584
        gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
1585
    }
1586

1587
    if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
1588
    {
1589
        idx = getFmtIdx(WINED3DFMT_B8G8R8A8_UNORM);
1590
        gl_info->formats[idx].gl_vtx_format = GL_BGRA;
1591 1592
    }

1593
    if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
1594 1595 1596 1597
    {
        /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
         * It is the job of the vertex buffer code to make sure that the vbos have the right format */
        idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
1598
        gl_info->formats[idx].gl_vtx_type = GL_HALF_FLOAT; /* == GL_HALF_FLOAT_NV */
1599 1600

        idx = getFmtIdx(WINED3DFMT_R16G16B16A16_FLOAT);
1601
        gl_info->formats[idx].gl_vtx_type = GL_HALF_FLOAT;
1602 1603 1604
    }
}

1605
static BOOL init_format_vertex_info(struct wined3d_gl_info *gl_info)
1606 1607 1608 1609 1610
{
    unsigned int i;

    for (i = 0; i < (sizeof(format_vertex_info) / sizeof(*format_vertex_info)); ++i)
    {
1611
        struct wined3d_format *format;
1612
        int fmt_idx = getFmtIdx(format_vertex_info[i].id);
1613 1614 1615 1616

        if (fmt_idx == -1)
        {
            ERR("Format %s (%#x) not found.\n",
1617
                    debug_d3dformat(format_vertex_info[i].id), format_vertex_info[i].id);
1618 1619 1620
            return FALSE;
        }

1621 1622 1623 1624 1625 1626 1627
        format = &gl_info->formats[fmt_idx];
        format->emit_idx = format_vertex_info[i].emit_idx;
        format->component_count = format_vertex_info[i].component_count;
        format->gl_vtx_type = format_vertex_info[i].gl_vtx_type;
        format->gl_vtx_format = format_vertex_info[i].gl_vtx_format;
        format->gl_normalized = format_vertex_info[i].gl_normalized;
        format->component_size = format_vertex_info[i].component_size;
1628 1629 1630
    }

    return TRUE;
1631 1632
}

1633
BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info)
1634 1635 1636
{
    if (!init_format_base_info(gl_info)) return FALSE;

1637
    if (!init_format_block_info(gl_info))
1638
    {
1639 1640
        HeapFree(GetProcessHeap(), 0, gl_info->formats);
        gl_info->formats = NULL;
1641 1642
        return FALSE;
    }
1643

1644 1645 1646
    return TRUE;
}

1647
/* Context activation is done by the caller. */
1648
BOOL initPixelFormats(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor)
1649 1650 1651
{
    if (!init_format_base_info(gl_info)) return FALSE;

1652
    if (!init_format_block_info(gl_info)) goto fail;
1653 1654
    if (!init_format_texture_info(gl_info)) goto fail;
    if (!init_format_vertex_info(gl_info)) goto fail;
1655

1656
    apply_format_fixups(gl_info);
1657
    init_format_fbo_compat_info(gl_info);
1658
    init_format_filter_info(gl_info, vendor);
1659 1660

    return TRUE;
1661 1662

fail:
1663 1664
    HeapFree(GetProcessHeap(), 0, gl_info->formats);
    gl_info->formats = NULL;
1665
    return FALSE;
1666 1667
}

1668 1669
const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
        enum wined3d_format_id format_id)
1670
{
1671
    int idx = getFmtIdx(format_id);
1672

1673 1674 1675 1676
    if (idx == -1)
    {
        FIXME("Can't find format %s (%#x) in the format lookup table\n",
                debug_d3dformat(format_id), format_id);
1677 1678 1679
        /* Get the caller a valid pointer */
        idx = getFmtIdx(WINED3DFMT_UNKNOWN);
    }
1680

1681
    return &gl_info->formats[idx];
1682 1683
}

1684
UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment, UINT width, UINT height)
1685 1686 1687
{
    UINT size;

1688
    if (format->id == WINED3DFMT_UNKNOWN)
1689 1690 1691
    {
        size = 0;
    }
1692
    else if (format->flags & WINED3DFMT_FLAG_BLOCKS)
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
    {
        UINT row_block_count = (width + format->block_width - 1) / format->block_width;
        UINT row_count = (height + format->block_height - 1) / format->block_height;
        size = row_count * (((row_block_count * format->block_byte_count) + alignment - 1) & ~(alignment - 1));
    }
    else
    {
        size = height * (((width * format->byte_count) + alignment - 1) & ~(alignment - 1));
    }

1703
    if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
1704 1705
    {
        /* The D3D format requirements make sure that the resulting format is an integer again */
1706 1707
        size *= format->height_scale.numerator;
        size /= format->height_scale.denominator;
1708
    }
1709 1710 1711 1712

    return size;
}

1713 1714 1715
/*****************************************************************************
 * Trace formatting of useful values
 */
1716 1717
const char *debug_d3dformat(enum wined3d_format_id format_id)
{
1718 1719
    switch (format_id)
    {
1720
#define FMT_TO_STR(format_id) case format_id: return #format_id
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
        FMT_TO_STR(WINED3DFMT_UNKNOWN);
        FMT_TO_STR(WINED3DFMT_B8G8R8_UNORM);
        FMT_TO_STR(WINED3DFMT_B5G5R5X1_UNORM);
        FMT_TO_STR(WINED3DFMT_B4G4R4A4_UNORM);
        FMT_TO_STR(WINED3DFMT_B2G3R3_UNORM);
        FMT_TO_STR(WINED3DFMT_B2G3R3A8_UNORM);
        FMT_TO_STR(WINED3DFMT_B4G4R4X4_UNORM);
        FMT_TO_STR(WINED3DFMT_R8G8B8X8_UNORM);
        FMT_TO_STR(WINED3DFMT_B10G10R10A2_UNORM);
        FMT_TO_STR(WINED3DFMT_P8_UINT_A8_UNORM);
        FMT_TO_STR(WINED3DFMT_P8_UINT);
        FMT_TO_STR(WINED3DFMT_L8_UNORM);
        FMT_TO_STR(WINED3DFMT_L8A8_UNORM);
        FMT_TO_STR(WINED3DFMT_L4A4_UNORM);
        FMT_TO_STR(WINED3DFMT_R5G5_SNORM_L6_UNORM);
        FMT_TO_STR(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
        FMT_TO_STR(WINED3DFMT_R10G11B11_SNORM);
        FMT_TO_STR(WINED3DFMT_R10G10B10_SNORM_A2_UNORM);
        FMT_TO_STR(WINED3DFMT_UYVY);
        FMT_TO_STR(WINED3DFMT_YUY2);
        FMT_TO_STR(WINED3DFMT_YV12);
        FMT_TO_STR(WINED3DFMT_DXT1);
        FMT_TO_STR(WINED3DFMT_DXT2);
        FMT_TO_STR(WINED3DFMT_DXT3);
        FMT_TO_STR(WINED3DFMT_DXT4);
        FMT_TO_STR(WINED3DFMT_DXT5);
        FMT_TO_STR(WINED3DFMT_MULTI2_ARGB8);
        FMT_TO_STR(WINED3DFMT_G8R8_G8B8);
        FMT_TO_STR(WINED3DFMT_R8G8_B8G8);
        FMT_TO_STR(WINED3DFMT_D16_LOCKABLE);
        FMT_TO_STR(WINED3DFMT_D32_UNORM);
        FMT_TO_STR(WINED3DFMT_S1_UINT_D15_UNORM);
        FMT_TO_STR(WINED3DFMT_X8D24_UNORM);
        FMT_TO_STR(WINED3DFMT_S4X4_UINT_D24_UNORM);
        FMT_TO_STR(WINED3DFMT_L16_UNORM);
        FMT_TO_STR(WINED3DFMT_S8_UINT_D24_FLOAT);
        FMT_TO_STR(WINED3DFMT_VERTEXDATA);
        FMT_TO_STR(WINED3DFMT_R8G8_SNORM_Cx);
        FMT_TO_STR(WINED3DFMT_ATI2N);
1760
        FMT_TO_STR(WINED3DFMT_NVDB);
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
        FMT_TO_STR(WINED3DFMT_NVHU);
        FMT_TO_STR(WINED3DFMT_NVHS);
        FMT_TO_STR(WINED3DFMT_R32G32B32A32_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R32G32B32A32_FLOAT);
        FMT_TO_STR(WINED3DFMT_R32G32B32A32_UINT);
        FMT_TO_STR(WINED3DFMT_R32G32B32A32_SINT);
        FMT_TO_STR(WINED3DFMT_R32G32B32_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R32G32B32_FLOAT);
        FMT_TO_STR(WINED3DFMT_R32G32B32_UINT);
        FMT_TO_STR(WINED3DFMT_R32G32B32_SINT);
        FMT_TO_STR(WINED3DFMT_R16G16B16A16_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R16G16B16A16_FLOAT);
        FMT_TO_STR(WINED3DFMT_R16G16B16A16_UNORM);
        FMT_TO_STR(WINED3DFMT_R16G16B16A16_UINT);
        FMT_TO_STR(WINED3DFMT_R16G16B16A16_SNORM);
        FMT_TO_STR(WINED3DFMT_R16G16B16A16_SINT);
        FMT_TO_STR(WINED3DFMT_R32G32_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R32G32_FLOAT);
        FMT_TO_STR(WINED3DFMT_R32G32_UINT);
        FMT_TO_STR(WINED3DFMT_R32G32_SINT);
        FMT_TO_STR(WINED3DFMT_R32G8X24_TYPELESS);
        FMT_TO_STR(WINED3DFMT_D32_FLOAT_S8X24_UINT);
        FMT_TO_STR(WINED3DFMT_R32_FLOAT_X8X24_TYPELESS);
        FMT_TO_STR(WINED3DFMT_X32_TYPELESS_G8X24_UINT);
        FMT_TO_STR(WINED3DFMT_R10G10B10A2_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R10G10B10A2_UNORM);
        FMT_TO_STR(WINED3DFMT_R10G10B10A2_UINT);
        FMT_TO_STR(WINED3DFMT_R10G10B10A2_SNORM);
        FMT_TO_STR(WINED3DFMT_R11G11B10_FLOAT);
        FMT_TO_STR(WINED3DFMT_R8G8B8A8_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM);
        FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM_SRGB);
        FMT_TO_STR(WINED3DFMT_R8G8B8A8_UINT);
        FMT_TO_STR(WINED3DFMT_R8G8B8A8_SNORM);
        FMT_TO_STR(WINED3DFMT_R8G8B8A8_SINT);
        FMT_TO_STR(WINED3DFMT_R16G16_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R16G16_FLOAT);
        FMT_TO_STR(WINED3DFMT_R16G16_UNORM);
        FMT_TO_STR(WINED3DFMT_R16G16_UINT);
        FMT_TO_STR(WINED3DFMT_R16G16_SNORM);
        FMT_TO_STR(WINED3DFMT_R16G16_SINT);
        FMT_TO_STR(WINED3DFMT_R32_TYPELESS);
        FMT_TO_STR(WINED3DFMT_D32_FLOAT);
        FMT_TO_STR(WINED3DFMT_R32_FLOAT);
        FMT_TO_STR(WINED3DFMT_R32_UINT);
        FMT_TO_STR(WINED3DFMT_R32_SINT);
        FMT_TO_STR(WINED3DFMT_R24G8_TYPELESS);
        FMT_TO_STR(WINED3DFMT_D24_UNORM_S8_UINT);
        FMT_TO_STR(WINED3DFMT_R24_UNORM_X8_TYPELESS);
        FMT_TO_STR(WINED3DFMT_X24_TYPELESS_G8_UINT);
        FMT_TO_STR(WINED3DFMT_R8G8_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R8G8_UNORM);
        FMT_TO_STR(WINED3DFMT_R8G8_UINT);
        FMT_TO_STR(WINED3DFMT_R8G8_SNORM);
        FMT_TO_STR(WINED3DFMT_R8G8_SINT);
        FMT_TO_STR(WINED3DFMT_R16_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R16_FLOAT);
        FMT_TO_STR(WINED3DFMT_D16_UNORM);
        FMT_TO_STR(WINED3DFMT_R16_UNORM);
        FMT_TO_STR(WINED3DFMT_R16_UINT);
        FMT_TO_STR(WINED3DFMT_R16_SNORM);
        FMT_TO_STR(WINED3DFMT_R16_SINT);
        FMT_TO_STR(WINED3DFMT_R8_TYPELESS);
        FMT_TO_STR(WINED3DFMT_R8_UNORM);
        FMT_TO_STR(WINED3DFMT_R8_UINT);
        FMT_TO_STR(WINED3DFMT_R8_SNORM);
        FMT_TO_STR(WINED3DFMT_R8_SINT);
        FMT_TO_STR(WINED3DFMT_A8_UNORM);
        FMT_TO_STR(WINED3DFMT_R1_UNORM);
        FMT_TO_STR(WINED3DFMT_R9G9B9E5_SHAREDEXP);
        FMT_TO_STR(WINED3DFMT_R8G8_B8G8_UNORM);
        FMT_TO_STR(WINED3DFMT_G8R8_G8B8_UNORM);
        FMT_TO_STR(WINED3DFMT_BC1_TYPELESS);
        FMT_TO_STR(WINED3DFMT_BC1_UNORM);
        FMT_TO_STR(WINED3DFMT_BC1_UNORM_SRGB);
        FMT_TO_STR(WINED3DFMT_BC2_TYPELESS);
        FMT_TO_STR(WINED3DFMT_BC2_UNORM);
        FMT_TO_STR(WINED3DFMT_BC2_UNORM_SRGB);
        FMT_TO_STR(WINED3DFMT_BC3_TYPELESS);
        FMT_TO_STR(WINED3DFMT_BC3_UNORM);
        FMT_TO_STR(WINED3DFMT_BC3_UNORM_SRGB);
        FMT_TO_STR(WINED3DFMT_BC4_TYPELESS);
        FMT_TO_STR(WINED3DFMT_BC4_UNORM);
        FMT_TO_STR(WINED3DFMT_BC4_SNORM);
        FMT_TO_STR(WINED3DFMT_BC5_TYPELESS);
        FMT_TO_STR(WINED3DFMT_BC5_UNORM);
        FMT_TO_STR(WINED3DFMT_BC5_SNORM);
        FMT_TO_STR(WINED3DFMT_B5G6R5_UNORM);
        FMT_TO_STR(WINED3DFMT_B5G5R5A1_UNORM);
        FMT_TO_STR(WINED3DFMT_B8G8R8A8_UNORM);
        FMT_TO_STR(WINED3DFMT_B8G8R8X8_UNORM);
1852
        FMT_TO_STR(WINED3DFMT_INTZ);
1853
        FMT_TO_STR(WINED3DFMT_NULL);
1854 1855
        FMT_TO_STR(WINED3DFMT_R16);
        FMT_TO_STR(WINED3DFMT_AL16);
1856
#undef FMT_TO_STR
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
        default:
        {
            char fourcc[5];
            fourcc[0] = (char)(format_id);
            fourcc[1] = (char)(format_id >> 8);
            fourcc[2] = (char)(format_id >> 16);
            fourcc[3] = (char)(format_id >> 24);
            fourcc[4] = 0;
            if (isprint(fourcc[0]) && isprint(fourcc[1]) && isprint(fourcc[2]) && isprint(fourcc[3]))
                FIXME("Unrecognized %#x (as fourcc: %s) WINED3DFORMAT!\n", format_id, fourcc);
            else
                FIXME("Unrecognized %#x WINED3DFORMAT!\n", format_id);
        }
        return "unrecognized";
1871
    }
1872
}
1873

1874
const char *debug_d3ddevicetype(enum wined3d_device_type device_type)
1875
{
1876
    switch (device_type)
1877
    {
1878
#define DEVTYPE_TO_STR(dev) case dev: return #dev
1879 1880 1881
        DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_HAL);
        DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_REF);
        DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_SW);
1882
#undef DEVTYPE_TO_STR
1883
        default:
1884
            FIXME("Unrecognized device type %#x.\n", device_type);
1885 1886
            return "unrecognized";
    }
1887 1888
}

1889 1890
const char *debug_d3dusage(DWORD usage)
{
1891
    char buf[333];
1892 1893 1894

    buf[0] = '\0';
#define WINED3DUSAGE_TO_STR(u) if (usage & u) { strcat(buf, " | "#u); usage &= ~u; }
1895 1896 1897 1898 1899 1900 1901 1902 1903
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_SOFTWAREPROCESSING);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DONOTCLIP);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_POINTS);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_RTPATCHES);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_NPATCHES);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DYNAMIC);
1904 1905
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_AUTOGENMIPMAP);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DMAP);
1906 1907
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_STATICDECL);
    WINED3DUSAGE_TO_STR(WINED3DUSAGE_OVERLAY);
1908
#undef WINED3DUSAGE_TO_STR
1909 1910 1911
    if (usage) FIXME("Unrecognized usage flag(s) %#x\n", usage);

    return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
1912 1913
}

1914 1915 1916 1917 1918 1919
const char *debug_d3dusagequery(DWORD usagequery)
{
    char buf[238];

    buf[0] = '\0';
#define WINED3DUSAGEQUERY_TO_STR(u) if (usagequery & u) { strcat(buf, " | "#u); usagequery &= ~u; }
1920 1921 1922 1923 1924 1925 1926 1927
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER);
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP);
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING);
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBREAD);
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBWRITE);
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE);
    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP);
#undef WINED3DUSAGEQUERY_TO_STR
1928 1929 1930
    if (usagequery) FIXME("Unrecognized usage query flag(s) %#x\n", usagequery);

    return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
1931 1932
}

1933 1934 1935 1936
const char *debug_d3ddeclmethod(enum wined3d_decl_method method)
{
    switch (method)
    {
1937
#define WINED3DDECLMETHOD_TO_STR(u) case u: return #u
1938 1939 1940 1941 1942 1943 1944
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_DEFAULT);
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_U);
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_V);
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_CROSS_UV);
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_UV);
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP);
        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP_PRESAMPLED);
1945 1946
#undef WINED3DDECLMETHOD_TO_STR
        default:
1947
            FIXME("Unrecognized declaration method %#x.\n", method);
1948 1949 1950 1951
            return "unrecognized";
    }
}

1952 1953 1954 1955
const char *debug_d3ddeclusage(enum wined3d_decl_usage usage)
{
    switch (usage)
    {
1956
#define WINED3DDECLUSAGE_TO_STR(u) case u: return #u
1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITION);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_WEIGHT);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_INDICES);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_NORMAL);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_PSIZE);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TEXCOORD);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TANGENT);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BINORMAL);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TESS_FACTOR);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITIONT);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_COLOR);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_FOG);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_DEPTH);
        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_SAMPLE);
1971 1972 1973 1974 1975 1976 1977
#undef WINED3DDECLUSAGE_TO_STR
        default:
            FIXME("Unrecognized %u declaration usage!\n", usage);
            return "unrecognized";
    }
}

1978
const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type)
1979
{
1980
    switch (resource_type)
1981
    {
1982
#define RES_TO_STR(res) case res: return #res
1983 1984 1985 1986 1987 1988
        RES_TO_STR(WINED3D_RTYPE_SURFACE);
        RES_TO_STR(WINED3D_RTYPE_VOLUME);
        RES_TO_STR(WINED3D_RTYPE_TEXTURE);
        RES_TO_STR(WINED3D_RTYPE_VOLUME_TEXTURE);
        RES_TO_STR(WINED3D_RTYPE_CUBE_TEXTURE);
        RES_TO_STR(WINED3D_RTYPE_BUFFER);
1989
#undef  RES_TO_STR
1990
        default:
1991
            FIXME("Unrecognized resource type %#x.\n", resource_type);
1992 1993
            return "unrecognized";
    }
1994
}
1995

1996
const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type)
1997
{
1998
    switch (primitive_type)
1999
    {
2000
#define PRIM_TO_STR(prim) case prim: return #prim
2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011
        PRIM_TO_STR(WINED3D_PT_UNDEFINED);
        PRIM_TO_STR(WINED3D_PT_POINTLIST);
        PRIM_TO_STR(WINED3D_PT_LINELIST);
        PRIM_TO_STR(WINED3D_PT_LINESTRIP);
        PRIM_TO_STR(WINED3D_PT_TRIANGLELIST);
        PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP);
        PRIM_TO_STR(WINED3D_PT_TRIANGLEFAN);
        PRIM_TO_STR(WINED3D_PT_LINELIST_ADJ);
        PRIM_TO_STR(WINED3D_PT_LINESTRIP_ADJ);
        PRIM_TO_STR(WINED3D_PT_TRIANGLELIST_ADJ);
        PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP_ADJ);
2012
#undef  PRIM_TO_STR
2013
        default:
2014
            FIXME("Unrecognized %u primitive type!\n", primitive_type);
2015 2016
            return "unrecognized";
    }
2017
}
2018

2019
const char *debug_d3drenderstate(enum wined3d_render_state state)
2020 2021 2022
{
    switch (state)
    {
2023
#define D3DSTATE_TO_STR(u) case u: return #u
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
        D3DSTATE_TO_STR(WINED3D_RS_ANTIALIAS);
        D3DSTATE_TO_STR(WINED3D_RS_TEXTUREPERSPECTIVE);
        D3DSTATE_TO_STR(WINED3D_RS_WRAPU);
        D3DSTATE_TO_STR(WINED3D_RS_WRAPV);
        D3DSTATE_TO_STR(WINED3D_RS_ZENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_FILLMODE);
        D3DSTATE_TO_STR(WINED3D_RS_SHADEMODE);
        D3DSTATE_TO_STR(WINED3D_RS_LINEPATTERN);
        D3DSTATE_TO_STR(WINED3D_RS_MONOENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_ROP2);
        D3DSTATE_TO_STR(WINED3D_RS_PLANEMASK);
        D3DSTATE_TO_STR(WINED3D_RS_ZWRITEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_ALPHATESTENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_LASTPIXEL);
        D3DSTATE_TO_STR(WINED3D_RS_SRCBLEND);
        D3DSTATE_TO_STR(WINED3D_RS_DESTBLEND);
        D3DSTATE_TO_STR(WINED3D_RS_CULLMODE);
        D3DSTATE_TO_STR(WINED3D_RS_ZFUNC);
        D3DSTATE_TO_STR(WINED3D_RS_ALPHAREF);
        D3DSTATE_TO_STR(WINED3D_RS_ALPHAFUNC);
        D3DSTATE_TO_STR(WINED3D_RS_DITHERENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_ALPHABLENDENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_FOGENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_SPECULARENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_ZVISIBLE);
        D3DSTATE_TO_STR(WINED3D_RS_SUBPIXEL);
        D3DSTATE_TO_STR(WINED3D_RS_SUBPIXELX);
        D3DSTATE_TO_STR(WINED3D_RS_STIPPLEDALPHA);
        D3DSTATE_TO_STR(WINED3D_RS_FOGCOLOR);
        D3DSTATE_TO_STR(WINED3D_RS_FOGTABLEMODE);
        D3DSTATE_TO_STR(WINED3D_RS_FOGSTART);
        D3DSTATE_TO_STR(WINED3D_RS_FOGEND);
        D3DSTATE_TO_STR(WINED3D_RS_FOGDENSITY);
        D3DSTATE_TO_STR(WINED3D_RS_STIPPLEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_EDGEANTIALIAS);
        D3DSTATE_TO_STR(WINED3D_RS_COLORKEYENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_MIPMAPLODBIAS);
        D3DSTATE_TO_STR(WINED3D_RS_RANGEFOGENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_ANISOTROPY);
        D3DSTATE_TO_STR(WINED3D_RS_FLUSHBATCH);
        D3DSTATE_TO_STR(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILFAIL);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILZFAIL);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILPASS);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILFUNC);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILREF);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILMASK);
        D3DSTATE_TO_STR(WINED3D_RS_STENCILWRITEMASK);
        D3DSTATE_TO_STR(WINED3D_RS_TEXTUREFACTOR);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP0);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP1);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP2);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP3);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP4);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP5);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP6);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP7);
        D3DSTATE_TO_STR(WINED3D_RS_CLIPPING);
        D3DSTATE_TO_STR(WINED3D_RS_LIGHTING);
        D3DSTATE_TO_STR(WINED3D_RS_EXTENTS);
        D3DSTATE_TO_STR(WINED3D_RS_AMBIENT);
        D3DSTATE_TO_STR(WINED3D_RS_FOGVERTEXMODE);
        D3DSTATE_TO_STR(WINED3D_RS_COLORVERTEX);
        D3DSTATE_TO_STR(WINED3D_RS_LOCALVIEWER);
        D3DSTATE_TO_STR(WINED3D_RS_NORMALIZENORMALS);
        D3DSTATE_TO_STR(WINED3D_RS_COLORKEYBLENDENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_DIFFUSEMATERIALSOURCE);
        D3DSTATE_TO_STR(WINED3D_RS_SPECULARMATERIALSOURCE);
        D3DSTATE_TO_STR(WINED3D_RS_AMBIENTMATERIALSOURCE);
        D3DSTATE_TO_STR(WINED3D_RS_EMISSIVEMATERIALSOURCE);
        D3DSTATE_TO_STR(WINED3D_RS_VERTEXBLEND);
        D3DSTATE_TO_STR(WINED3D_RS_CLIPPLANEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_SOFTWAREVERTEXPROCESSING);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MIN);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSPRITEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_A);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_B);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_C);
        D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEANTIALIAS);
        D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEMASK);
        D3DSTATE_TO_STR(WINED3D_RS_PATCHEDGESTYLE);
        D3DSTATE_TO_STR(WINED3D_RS_PATCHSEGMENTS);
        D3DSTATE_TO_STR(WINED3D_RS_DEBUGMONITORTOKEN);
        D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MAX);
        D3DSTATE_TO_STR(WINED3D_RS_INDEXEDVERTEXBLENDENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_TWEENFACTOR);
        D3DSTATE_TO_STR(WINED3D_RS_BLENDOP);
        D3DSTATE_TO_STR(WINED3D_RS_POSITIONDEGREE);
        D3DSTATE_TO_STR(WINED3D_RS_NORMALDEGREE);
        D3DSTATE_TO_STR(WINED3D_RS_SCISSORTESTENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_SLOPESCALEDEPTHBIAS);
        D3DSTATE_TO_STR(WINED3D_RS_ANTIALIASEDLINEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_MINTESSELLATIONLEVEL);
        D3DSTATE_TO_STR(WINED3D_RS_MAXTESSELLATIONLEVEL);
        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_X);
        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Y);
        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Z);
        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_W);
        D3DSTATE_TO_STR(WINED3D_RS_ENABLEADAPTIVETESSELLATION);
        D3DSTATE_TO_STR(WINED3D_RS_TWOSIDEDSTENCILMODE);
        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILFAIL);
        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILZFAIL);
        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILPASS);
        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILFUNC);
        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE1);
        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE2);
        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE3);
        D3DSTATE_TO_STR(WINED3D_RS_BLENDFACTOR);
        D3DSTATE_TO_STR(WINED3D_RS_SRGBWRITEENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_DEPTHBIAS);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP8);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP9);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP10);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP11);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP12);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP13);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP14);
        D3DSTATE_TO_STR(WINED3D_RS_WRAP15);
        D3DSTATE_TO_STR(WINED3D_RS_SEPARATEALPHABLENDENABLE);
        D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA);
        D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA);
        D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA);
2150
#undef D3DSTATE_TO_STR
2151 2152 2153 2154
        default:
            FIXME("Unrecognized %u render state!\n", state);
            return "unrecognized";
    }
2155 2156
}

2157
const char *debug_d3dsamplerstate(enum wined3d_sampler_state state)
2158 2159 2160
{
    switch (state)
    {
2161
#define D3DSTATE_TO_STR(u) case u: return #u
2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
        D3DSTATE_TO_STR(WINED3D_SAMP_BORDER_COLOR);
        D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_U);
        D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_V);
        D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_W);
        D3DSTATE_TO_STR(WINED3D_SAMP_MAG_FILTER);
        D3DSTATE_TO_STR(WINED3D_SAMP_MIN_FILTER);
        D3DSTATE_TO_STR(WINED3D_SAMP_MIP_FILTER);
        D3DSTATE_TO_STR(WINED3D_SAMP_MIPMAP_LOD_BIAS);
        D3DSTATE_TO_STR(WINED3D_SAMP_MAX_MIP_LEVEL);
        D3DSTATE_TO_STR(WINED3D_SAMP_MAX_ANISOTROPY);
        D3DSTATE_TO_STR(WINED3D_SAMP_SRGB_TEXTURE);
        D3DSTATE_TO_STR(WINED3D_SAMP_ELEMENT_INDEX);
        D3DSTATE_TO_STR(WINED3D_SAMP_DMAP_OFFSET);
2175
#undef D3DSTATE_TO_STR
2176 2177 2178 2179
        default:
            FIXME("Unrecognized %u sampler state!\n", state);
            return "unrecognized";
    }
2180 2181
}

2182 2183 2184 2185
const char *debug_d3dtexturefiltertype(enum wined3d_texture_filter_type filter_type)
{
    switch (filter_type)
    {
2186
#define D3DTEXTUREFILTERTYPE_TO_STR(u) case u: return #u
2187 2188 2189 2190 2191 2192 2193 2194
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_NONE);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_POINT);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_LINEAR);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_ANISOTROPIC);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_FLAT_CUBIC);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_CUBIC);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_PYRAMIDAL_QUAD);
        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_QUAD);
2195 2196
#undef D3DTEXTUREFILTERTYPE_TO_STR
        default:
2197
            FIXME("Unrecognied texture filter type 0x%08x.\n", filter_type);
2198 2199 2200 2201
            return "unrecognized";
    }
}

2202
const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state)
2203 2204 2205
{
    switch (state)
    {
2206
#define D3DSTATE_TO_STR(u) case u: return #u
2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224
        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_OP);
        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG1);
        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG2);
        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_OP);
        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG1);
        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG2);
        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT00);
        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT01);
        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT10);
        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT11);
        D3DSTATE_TO_STR(WINED3D_TSS_TEXCOORD_INDEX);
        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LSCALE);
        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LOFFSET);
        D3DSTATE_TO_STR(WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS);
        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG0);
        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG0);
        D3DSTATE_TO_STR(WINED3D_TSS_RESULT_ARG);
        D3DSTATE_TO_STR(WINED3D_TSS_CONSTANT);
2225
#undef D3DSTATE_TO_STR
2226 2227 2228 2229
        default:
            FIXME("Unrecognized %u texture state!\n", state);
            return "unrecognized";
    }
2230 2231
}

2232 2233 2234 2235
const char *debug_d3dtop(enum wined3d_texture_op d3dtop)
{
    switch (d3dtop)
    {
2236
#define D3DTOP_TO_STR(u) case u: return #u
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262
        D3DTOP_TO_STR(WINED3D_TOP_DISABLE);
        D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG1);
        D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG2);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_2X);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_4X);
        D3DTOP_TO_STR(WINED3D_TOP_ADD);
        D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED);
        D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED_2X);
        D3DTOP_TO_STR(WINED3D_TOP_SUBTRACT);
        D3DTOP_TO_STR(WINED3D_TOP_ADD_SMOOTH);
        D3DTOP_TO_STR(WINED3D_TOP_BLEND_DIFFUSE_ALPHA);
        D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA);
        D3DTOP_TO_STR(WINED3D_TOP_BLEND_FACTOR_ALPHA);
        D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM);
        D3DTOP_TO_STR(WINED3D_TOP_BLEND_CURRENT_ALPHA);
        D3DTOP_TO_STR(WINED3D_TOP_PREMODULATE);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR);
        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA);
        D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP);
        D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP_LUMINANCE);
        D3DTOP_TO_STR(WINED3D_TOP_DOTPRODUCT3);
        D3DTOP_TO_STR(WINED3D_TOP_MULTIPLY_ADD);
        D3DTOP_TO_STR(WINED3D_TOP_LERP);
2263 2264
#undef D3DTOP_TO_STR
        default:
2265
            FIXME("Unrecognized texture op %#x.\n", d3dtop);
2266 2267 2268 2269
            return "unrecognized";
    }
}

2270 2271 2272 2273
const char *debug_d3dtstype(enum wined3d_transform_state tstype)
{
    switch (tstype)
    {
2274
#define TSTYPE_TO_STR(tstype) case tstype: return #tstype
2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
    TSTYPE_TO_STR(WINED3D_TS_VIEW);
    TSTYPE_TO_STR(WINED3D_TS_PROJECTION);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE0);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE1);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE2);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE3);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE4);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE5);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE6);
    TSTYPE_TO_STR(WINED3D_TS_TEXTURE7);
    TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(0));
2286 2287
#undef TSTYPE_TO_STR
    default:
2288 2289 2290 2291
        if (tstype > 256 && tstype < 512)
        {
            FIXME("WINED3D_TS_WORLD_MATRIX(%u). 1..255 not currently supported.\n", tstype);
            return ("WINED3D_TS_WORLD_MATRIX > 0");
2292
        }
2293
        FIXME("Unrecognized transform state %#x.\n", tstype);
2294 2295 2296 2297
        return "unrecognized";
    }
}

2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322
const char *debug_d3dstate(DWORD state)
{
    if (STATE_IS_RENDER(state))
        return wine_dbg_sprintf("STATE_RENDER(%s)", debug_d3drenderstate(state - STATE_RENDER(0)));
    if (STATE_IS_TEXTURESTAGE(state))
    {
        DWORD texture_stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
        DWORD texture_state = state - STATE_TEXTURESTAGE(texture_stage, 0);
        return wine_dbg_sprintf("STATE_TEXTURESTAGE(%#x, %s)",
                texture_stage, debug_d3dtexturestate(texture_state));
    }
    if (STATE_IS_SAMPLER(state))
        return wine_dbg_sprintf("STATE_SAMPLER(%#x)", state - STATE_SAMPLER(0));
    if (STATE_IS_PIXELSHADER(state))
        return "STATE_PIXELSHADER";
    if (STATE_IS_TRANSFORM(state))
        return wine_dbg_sprintf("STATE_TRANSFORM(%s)", debug_d3dtstype(state - STATE_TRANSFORM(0)));
    if (STATE_IS_STREAMSRC(state))
        return "STATE_STREAMSRC";
    if (STATE_IS_INDEXBUFFER(state))
        return "STATE_INDEXBUFFER";
    if (STATE_IS_VDECL(state))
        return "STATE_VDECL";
    if (STATE_IS_VSHADER(state))
        return "STATE_VSHADER";
2323 2324
    if (STATE_IS_GEOMETRY_SHADER(state))
        return "STATE_GEOMETRY_SHADER";
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
    if (STATE_IS_VIEWPORT(state))
        return "STATE_VIEWPORT";
    if (STATE_IS_VERTEXSHADERCONSTANT(state))
        return "STATE_VERTEXSHADERCONSTANT";
    if (STATE_IS_PIXELSHADERCONSTANT(state))
        return "STATE_PIXELSHADERCONSTANT";
    if (STATE_IS_ACTIVELIGHT(state))
        return wine_dbg_sprintf("STATE_ACTIVELIGHT(%#x)", state - STATE_ACTIVELIGHT(0));
    if (STATE_IS_SCISSORRECT(state))
        return "STATE_SCISSORRECT";
    if (STATE_IS_CLIPPLANE(state))
        return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0));
    if (STATE_IS_MATERIAL(state))
        return "STATE_MATERIAL";
    if (STATE_IS_FRONTFACE(state))
        return "STATE_FRONTFACE";
2341 2342
    if (STATE_IS_POINTSPRITECOORDORIGIN(state))
        return "STATE_POINTSPRITECOORDORIGIN";
2343 2344
    if (STATE_IS_BASEVERTEXINDEX(state))
        return "STATE_BASEVERTEXINDEX";
2345 2346
    if (STATE_IS_FRAMEBUFFER(state))
        return "STATE_FRAMEBUFFER";
2347 2348 2349 2350

    return wine_dbg_sprintf("UNKNOWN_STATE(%#x)", state);
}

2351
const char *debug_d3dpool(enum wined3d_pool pool)
2352 2353 2354
{
    switch (pool)
    {
2355
#define POOL_TO_STR(p) case p: return #p
2356 2357 2358 2359
        POOL_TO_STR(WINED3D_POOL_DEFAULT);
        POOL_TO_STR(WINED3D_POOL_MANAGED);
        POOL_TO_STR(WINED3D_POOL_SYSTEM_MEM);
        POOL_TO_STR(WINED3D_POOL_SCRATCH);
2360
#undef  POOL_TO_STR
2361
        default:
2362
            FIXME("Unrecognized pool %#x.\n", pool);
2363 2364
            return "unrecognized";
    }
2365
}
2366

2367 2368 2369
const char *debug_fbostatus(GLenum status) {
    switch(status) {
#define FBOSTATUS_TO_STR(u) case u: return #u
2370 2371 2372
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_COMPLETE);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
2373 2374
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
2375 2376 2377 2378 2379
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNSUPPORTED);
        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNDEFINED);
2380 2381 2382 2383 2384 2385 2386
#undef FBOSTATUS_TO_STR
        default:
            FIXME("Unrecognied FBO status 0x%08x\n", status);
            return "unrecognized";
    }
}

2387 2388 2389 2390 2391 2392 2393 2394 2395 2396
const char *debug_glerror(GLenum error) {
    switch(error) {
#define GLERROR_TO_STR(u) case u: return #u
        GLERROR_TO_STR(GL_NO_ERROR);
        GLERROR_TO_STR(GL_INVALID_ENUM);
        GLERROR_TO_STR(GL_INVALID_VALUE);
        GLERROR_TO_STR(GL_INVALID_OPERATION);
        GLERROR_TO_STR(GL_STACK_OVERFLOW);
        GLERROR_TO_STR(GL_STACK_UNDERFLOW);
        GLERROR_TO_STR(GL_OUT_OF_MEMORY);
2397
        GLERROR_TO_STR(GL_INVALID_FRAMEBUFFER_OPERATION);
2398 2399 2400 2401 2402 2403 2404
#undef GLERROR_TO_STR
        default:
            FIXME("Unrecognied GL error 0x%08x\n", error);
            return "unrecognized";
    }
}

2405 2406 2407 2408 2409 2410 2411
const char *debug_d3dbasis(enum wined3d_basis_type basis)
{
    switch (basis)
    {
        case WINED3D_BASIS_BEZIER:      return "WINED3D_BASIS_BEZIER";
        case WINED3D_BASIS_BSPLINE:     return "WINED3D_BASIS_BSPLINE";
        case WINED3D_BASIS_INTERPOLATE: return "WINED3D_BASIS_INTERPOLATE";
2412 2413 2414 2415
        default:                        return "unrecognized";
    }
}

2416 2417 2418 2419 2420 2421 2422 2423
const char *debug_d3ddegree(enum wined3d_degree_type degree)
{
    switch (degree)
    {
        case WINED3D_DEGREE_LINEAR:     return "WINED3D_DEGREE_LINEAR";
        case WINED3D_DEGREE_QUADRATIC:  return "WINED3D_DEGREE_QUADRATIC";
        case WINED3D_DEGREE_CUBIC:      return "WINED3D_DEGREE_CUBIC";
        case WINED3D_DEGREE_QUINTIC:    return "WINED3D_DEGREE_QUINTIC";
2424 2425 2426 2427
        default:                        return "unrecognized";
    }
}

2428
static const char *debug_fixup_channel_source(enum fixup_channel_source source)
2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
{
    switch(source)
    {
#define WINED3D_TO_STR(x) case x: return #x
        WINED3D_TO_STR(CHANNEL_SOURCE_ZERO);
        WINED3D_TO_STR(CHANNEL_SOURCE_ONE);
        WINED3D_TO_STR(CHANNEL_SOURCE_X);
        WINED3D_TO_STR(CHANNEL_SOURCE_Y);
        WINED3D_TO_STR(CHANNEL_SOURCE_Z);
        WINED3D_TO_STR(CHANNEL_SOURCE_W);
2439 2440
        WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX0);
        WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX1);
2441 2442 2443 2444 2445 2446 2447
#undef WINED3D_TO_STR
        default:
            FIXME("Unrecognized fixup_channel_source %#x\n", source);
            return "unrecognized";
    }
}

2448
static const char *debug_complex_fixup(enum complex_fixup fixup)
2449
{
2450
    switch(fixup)
2451 2452
    {
#define WINED3D_TO_STR(x) case x: return #x
2453 2454 2455
        WINED3D_TO_STR(COMPLEX_FIXUP_YUY2);
        WINED3D_TO_STR(COMPLEX_FIXUP_UYVY);
        WINED3D_TO_STR(COMPLEX_FIXUP_YV12);
2456
        WINED3D_TO_STR(COMPLEX_FIXUP_P8);
2457 2458
#undef WINED3D_TO_STR
        default:
2459
            FIXME("Unrecognized complex fixup %#x\n", fixup);
2460 2461 2462 2463 2464 2465
            return "unrecognized";
    }
}

void dump_color_fixup_desc(struct color_fixup_desc fixup)
{
2466
    if (is_complex_fixup(fixup))
2467
    {
2468
        TRACE("\tComplex: %s\n", debug_complex_fixup(get_complex_fixup(fixup)));
2469 2470 2471 2472 2473 2474 2475 2476 2477
        return;
    }

    TRACE("\tX: %s%s\n", debug_fixup_channel_source(fixup.x_source), fixup.x_sign_fixup ? ", SIGN_FIXUP" : "");
    TRACE("\tY: %s%s\n", debug_fixup_channel_source(fixup.y_source), fixup.y_sign_fixup ? ", SIGN_FIXUP" : "");
    TRACE("\tZ: %s%s\n", debug_fixup_channel_source(fixup.z_source), fixup.z_sign_fixup ? ", SIGN_FIXUP" : "");
    TRACE("\tW: %s%s\n", debug_fixup_channel_source(fixup.w_source), fixup.w_sign_fixup ? ", SIGN_FIXUP" : "");
}

2478 2479 2480 2481
const char *debug_surflocation(DWORD flag) {
    char buf[128];

    buf[0] = 0;
2482 2483 2484 2485 2486 2487
    if (flag & SFLAG_INSYSMEM) strcat(buf, " | SFLAG_INSYSMEM");                    /* 17 */
    if (flag & SFLAG_INDRAWABLE) strcat(buf, " | SFLAG_INDRAWABLE");                /* 19 */
    if (flag & SFLAG_INTEXTURE) strcat(buf, " | SFLAG_INTEXTURE");                  /* 18 */
    if (flag & SFLAG_INSRGBTEX) strcat(buf, " | SFLAG_INSRGBTEX");                  /* 18 */
    if (flag & SFLAG_INRB_MULTISAMPLE) strcat(buf, " | SFLAG_INRB_MULTISAMPLE");    /* 25 */
    if (flag & SFLAG_INRB_RESOLVED) strcat(buf, " | SFLAG_INRB_RESOLVED");          /* 22 */
2488 2489 2490
    return wine_dbg_sprintf("%s", buf[0] ? buf + 3 : "0");
}

2491
BOOL is_invalid_op(const struct wined3d_state *state, int stage,
2492
        enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
2493
{
2494 2495 2496 2497
    if (op == WINED3D_TOP_DISABLE)
        return FALSE;
    if (state->textures[stage])
        return FALSE;
2498

2499
    if ((arg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
2500 2501
            && op != WINED3D_TOP_SELECT_ARG2)
        return TRUE;
2502
    if ((arg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
2503 2504
            && op != WINED3D_TOP_SELECT_ARG1)
        return TRUE;
2505
    if ((arg3 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
2506 2507
            && (op == WINED3D_TOP_MULTIPLY_ADD || op == WINED3D_TOP_LERP))
        return TRUE;
2508 2509 2510 2511

    return FALSE;
}

2512 2513
/* Setup this textures matrix according to the texture flags. */
/* Context activation is done by the caller (state handler). */
2514 2515
void set_texture_matrix(const struct wined3d_gl_info *gl_info, const float *smat, DWORD flags,
        BOOL calculatedCoords, BOOL transformed, enum wined3d_format_id vtx_fmt, BOOL ffp_proj_control)
2516 2517 2518
{
    float mat[16];

2519
    gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
2520
    checkGLcall("glMatrixMode(GL_TEXTURE)");
2521

2522 2523
    if (flags == WINED3D_TTFF_DISABLE || flags == WINED3D_TTFF_COUNT1 || transformed)
    {
2524
        gl_info->gl_ops.gl.p_glLoadIdentity();
2525 2526 2527 2528
        checkGLcall("glLoadIdentity()");
        return;
    }

2529 2530 2531
    if (flags == (WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED))
    {
        ERR("Invalid texture transform flags: WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED.\n");
2532 2533 2534
        return;
    }

2535
    memcpy(mat, smat, 16 * sizeof(float));
2536

2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556
    if (flags & WINED3D_TTFF_PROJECTED)
    {
        if (!ffp_proj_control)
        {
            switch (flags & ~WINED3D_TTFF_PROJECTED)
            {
                case WINED3D_TTFF_COUNT2:
                    mat[ 3] = mat[ 1];
                    mat[ 7] = mat[ 5];
                    mat[11] = mat[ 9];
                    mat[15] = mat[13];
                    mat[ 1] = mat[ 5] = mat[ 9] = mat[13] = 0.0f;
                    break;
                case WINED3D_TTFF_COUNT3:
                    mat[ 3] = mat[ 2];
                    mat[ 7] = mat[ 6];
                    mat[11] = mat[10];
                    mat[15] = mat[14];
                    mat[ 2] = mat[ 6] = mat[10] = mat[14] = 0.0f;
                    break;
2557
            }
2558
        }
2559 2560
    } else { /* under directx the R/Z coord can be used for translation, under opengl we use the Q coord instead */
        if(!calculatedCoords) {
2561 2562 2563
            switch(vtx_fmt)
            {
                case WINED3DFMT_R32_FLOAT:
2564 2565 2566 2567 2568 2569 2570 2571 2572
                    /* Direct3D passes the default 1.0 in the 2nd coord, while gl passes it in the 4th.
                     * swap 2nd and 4th coord. No need to store the value of mat[12] in mat[4] because
                     * the input value to the transformation will be 0, so the matrix value is irrelevant
                     */
                    mat[12] = mat[4];
                    mat[13] = mat[5];
                    mat[14] = mat[6];
                    mat[15] = mat[7];
                    break;
2573
                case WINED3DFMT_R32G32_FLOAT:
2574 2575 2576 2577 2578 2579 2580
                    /* See above, just 3rd and 4th coord
                    */
                    mat[12] = mat[8];
                    mat[13] = mat[9];
                    mat[14] = mat[10];
                    mat[15] = mat[11];
                    break;
2581 2582
                case WINED3DFMT_R32G32B32_FLOAT: /* Opengl defaults match dx defaults */
                case WINED3DFMT_R32G32B32A32_FLOAT: /* No defaults apply, all app defined */
2583

2584
                /* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0
2585 2586 2587
                 * into a bad place. The division elimination below will apply to make sure the
                 * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0
                 */
2588
                case WINED3DFMT_UNKNOWN: /* No texture coords, 0/0/0/1 defaults are passed */
2589 2590 2591 2592
                    break;
                default:
                    FIXME("Unexpected fixed function texture coord input\n");
            }
2593
        }
2594 2595 2596 2597 2598 2599 2600
        if (!ffp_proj_control)
        {
            switch (flags & ~WINED3D_TTFF_PROJECTED)
            {
                /* case WINED3D_TTFF_COUNT1: Won't ever get here. */
                case WINED3D_TTFF_COUNT2:
                    mat[2] = mat[6] = mat[10] = mat[14] = 0;
2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611
                /* OpenGL divides the first 3 vertex coord by the 4th by default,
                * which is essentially the same as D3DTTFF_PROJECTED. Make sure that
                * the 4th coord evaluates to 1.0 to eliminate that.
                *
                * If the fixed function pipeline is used, the 4th value remains unused,
                * so there is no danger in doing this. With vertex shaders we have a
                * problem. Should an app hit that problem, the code here would have to
                * check for pixel shaders, and the shader has to undo the default gl divide.
                *
                * A more serious problem occurs if the app passes 4 coordinates in, and the
                * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow
2612 2613 2614
                * or a replacement shader. */
                default:
                    mat[3] = mat[7] = mat[11] = 0; mat[15] = 1;
2615
            }
2616
        }
2617
    }
2618

2619
    gl_info->gl_ops.gl.p_glLoadMatrixf(mat);
2620 2621 2622
    checkGLcall("glLoadMatrixf(mat)");
}

2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
/* This small helper function is used to convert a bitmask into the number of masked bits */
unsigned int count_bits(unsigned int mask)
{
    unsigned int count;
    for (count = 0; mask; ++count)
    {
        mask &= mask - 1;
    }
    return count;
}

/* Helper function for retrieving color info for ChoosePixelFormat and wglChoosePixelFormatARB.
 * The later function requires individual color components. */
2636
BOOL getColorBits(const struct wined3d_format *format,
2637
        BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize)
2638
{
2639
    TRACE("format %s.\n", debug_d3dformat(format->id));
2640

2641
    switch (format->id)
2642
    {
2643 2644
        case WINED3DFMT_B10G10R10A2_UNORM:
        case WINED3DFMT_R10G10B10A2_UNORM:
2645 2646 2647
        case WINED3DFMT_B8G8R8X8_UNORM:
        case WINED3DFMT_B8G8R8_UNORM:
        case WINED3DFMT_B8G8R8A8_UNORM:
2648
        case WINED3DFMT_R8G8B8A8_UNORM:
2649 2650 2651 2652 2653 2654 2655 2656
        case WINED3DFMT_B5G5R5X1_UNORM:
        case WINED3DFMT_B5G5R5A1_UNORM:
        case WINED3DFMT_B5G6R5_UNORM:
        case WINED3DFMT_B4G4R4X4_UNORM:
        case WINED3DFMT_B4G4R4A4_UNORM:
        case WINED3DFMT_B2G3R3_UNORM:
        case WINED3DFMT_P8_UINT_A8_UNORM:
        case WINED3DFMT_P8_UINT:
2657 2658
            break;
        default:
2659
            FIXME("Unsupported format %s.\n", debug_d3dformat(format->id));
2660 2661 2662
            return FALSE;
    }

2663 2664 2665 2666
    *redSize = format->red_size;
    *greenSize = format->green_size;
    *blueSize = format->blue_size;
    *alphaSize = format->alpha_size;
2667 2668
    *totalSize = *redSize + *greenSize + *blueSize + *alphaSize;

2669
    TRACE("Returning red: %d, green: %d, blue: %d, alpha: %d, total: %d for format %s.\n",
2670
            *redSize, *greenSize, *blueSize, *alphaSize, *totalSize, debug_d3dformat(format->id));
2671 2672 2673 2674
    return TRUE;
}

/* Helper function for retrieving depth/stencil info for ChoosePixelFormat and wglChoosePixelFormatARB */
2675
BOOL getDepthStencilBits(const struct wined3d_format *format, BYTE *depthSize, BYTE *stencilSize)
2676
{
2677
    TRACE("format %s.\n", debug_d3dformat(format->id));
2678

2679
    switch (format->id)
2680 2681
    {
        case WINED3DFMT_D16_LOCKABLE:
2682
        case WINED3DFMT_D16_UNORM:
2683 2684 2685
        case WINED3DFMT_S1_UINT_D15_UNORM:
        case WINED3DFMT_X8D24_UNORM:
        case WINED3DFMT_S4X4_UINT_D24_UNORM:
2686
        case WINED3DFMT_D24_UNORM_S8_UINT:
2687 2688 2689
        case WINED3DFMT_S8_UINT_D24_FLOAT:
        case WINED3DFMT_D32_UNORM:
        case WINED3DFMT_D32_FLOAT:
2690
        case WINED3DFMT_INTZ:
2691 2692
            break;
        default:
2693
            FIXME("Unsupported depth/stencil format %s.\n", debug_d3dformat(format->id));
2694 2695 2696
            return FALSE;
    }

2697 2698
    *depthSize = format->depth_size;
    *stencilSize = format->stencil_size;
2699

2700
    TRACE("Returning depthSize: %d and stencilSize: %d for format %s.\n",
2701
            *depthSize, *stencilSize, debug_d3dformat(format->id));
2702 2703 2704
    return TRUE;
}

2705 2706 2707
/* Note: It's the caller's responsibility to ensure values can be expressed
 * in the requested format. UNORM formats for example can only express values
 * in the range 0.0f -> 1.0f. */
2708
DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface, const struct wined3d_color *color)
2709
{
2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738
    static const struct
    {
        enum wined3d_format_id format_id;
        float r_mul;
        float g_mul;
        float b_mul;
        float a_mul;
        BYTE r_shift;
        BYTE g_shift;
        BYTE b_shift;
        BYTE a_shift;
    }
    conv[] =
    {
        {WINED3DFMT_B8G8R8A8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f, 16,  8,  0, 24},
        {WINED3DFMT_B8G8R8X8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f, 16,  8,  0, 24},
        {WINED3DFMT_B8G8R8_UNORM,       255.0f,  255.0f,  255.0f,  255.0f, 16,  8,  0, 24},
        {WINED3DFMT_B5G6R5_UNORM,        31.0f,   63.0f,   31.0f,    0.0f, 11,  5,  0,  0},
        {WINED3DFMT_B5G5R5A1_UNORM,      31.0f,   31.0f,   31.0f,    1.0f, 10,  5,  0, 15},
        {WINED3DFMT_B5G5R5X1_UNORM,      31.0f,   31.0f,   31.0f,    1.0f, 10,  5,  0, 15},
        {WINED3DFMT_A8_UNORM,             0.0f,    0.0f,    0.0f,  255.0f,  0,  0,  0,  0},
        {WINED3DFMT_B4G4R4A4_UNORM,      15.0f,   15.0f,   15.0f,   15.0f,  8,  4,  0, 12},
        {WINED3DFMT_B4G4R4X4_UNORM,      15.0f,   15.0f,   15.0f,   15.0f,  8,  4,  0, 12},
        {WINED3DFMT_B2G3R3_UNORM,         7.0f,    7.0f,    3.0f,    0.0f,  5,  2,  0,  0},
        {WINED3DFMT_R8G8B8A8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f,  0,  8, 16, 24},
        {WINED3DFMT_R8G8B8X8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f,  0,  8, 16, 24},
        {WINED3DFMT_B10G10R10A2_UNORM, 1023.0f, 1023.0f, 1023.0f,    3.0f, 20, 10,  0, 30},
        {WINED3DFMT_R10G10B10A2_UNORM, 1023.0f, 1023.0f, 1023.0f,    3.0f,  0, 10, 20, 30},
    };
2739
    const struct wined3d_format *format = surface->resource.format;
2740
    unsigned int i;
2741

2742
    TRACE("Converting color {%.8e %.8e %.8e %.8e} to format %s.\n",
2743
            color->r, color->g, color->b, color->a, debug_d3dformat(format->id));
2744

2745
    for (i = 0; i < sizeof(conv) / sizeof(*conv); ++i)
2746
    {
2747
        DWORD ret;
2748

2749
        if (format->id != conv[i].format_id) continue;
2750

2751 2752 2753 2754
        ret = ((DWORD)((color->r * conv[i].r_mul) + 0.5f)) << conv[i].r_shift;
        ret |= ((DWORD)((color->g * conv[i].g_mul) + 0.5f)) << conv[i].g_shift;
        ret |= ((DWORD)((color->b * conv[i].b_mul) + 0.5f)) << conv[i].b_shift;
        ret |= ((DWORD)((color->a * conv[i].a_mul) + 0.5f)) << conv[i].a_shift;
2755

2756
        TRACE("Returning 0x%08x.\n", ret);
2757

2758 2759
        return ret;
    }
2760

2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794
    if (format->id == WINED3DFMT_P8_UINT)
    {
        PALETTEENTRY *e;
        BYTE r, g, b, a;

        if (!surface->palette)
        {
            WARN("Surface doesn't have a palette, returning 0.\n");
            return 0;
        }

        r = (BYTE)((color->r * 255.0f) + 0.5f);
        g = (BYTE)((color->g * 255.0f) + 0.5f);
        b = (BYTE)((color->b * 255.0f) + 0.5f);
        a = (BYTE)((color->a * 255.0f) + 0.5f);

        e = &surface->palette->palents[a];
        if (e->peRed == r && e->peGreen == g && e->peBlue == b)
            return a;

        WARN("Alpha didn't match index, searching full palette.\n");

        for (i = 0; i < 256; ++i)
        {
            e = &surface->palette->palents[i];
            if (e->peRed == r && e->peGreen == g && e->peBlue == b)
                return i;
        }

        FIXME("Unable to convert color to palette index.\n");

        return 0;
    }

2795
    FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format->id));
2796

2797
    return 0;
2798 2799
}

2800
/* DirectDraw stuff */
2801 2802 2803 2804
enum wined3d_format_id pixelformat_for_depth(DWORD depth)
{
    switch (depth)
    {
2805 2806 2807 2808 2809
        case 8:  return WINED3DFMT_P8_UINT;
        case 15: return WINED3DFMT_B5G5R5X1_UNORM;
        case 16: return WINED3DFMT_B5G6R5_UNORM;
        case 24: return WINED3DFMT_B8G8R8X8_UNORM; /* Robots needs 24bit to be WINED3DFMT_B8G8R8X8_UNORM */
        case 32: return WINED3DFMT_B8G8R8X8_UNORM; /* EVE online and the Fur demo need 32bit AdapterDisplayMode to return WINED3DFMT_B8G8R8X8_UNORM */
2810 2811 2812
        default: return WINED3DFMT_UNKNOWN;
    }
}
2813

2814 2815 2816 2817
void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1,
        const struct wined3d_matrix *src2)
{
    struct wined3d_matrix temp;
2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847

    /* Now do the multiplication 'by hand'.
       I know that all this could be optimised, but this will be done later :-) */
    temp.u.s._11 = (src1->u.s._11 * src2->u.s._11) + (src1->u.s._21 * src2->u.s._12) + (src1->u.s._31 * src2->u.s._13) + (src1->u.s._41 * src2->u.s._14);
    temp.u.s._21 = (src1->u.s._11 * src2->u.s._21) + (src1->u.s._21 * src2->u.s._22) + (src1->u.s._31 * src2->u.s._23) + (src1->u.s._41 * src2->u.s._24);
    temp.u.s._31 = (src1->u.s._11 * src2->u.s._31) + (src1->u.s._21 * src2->u.s._32) + (src1->u.s._31 * src2->u.s._33) + (src1->u.s._41 * src2->u.s._34);
    temp.u.s._41 = (src1->u.s._11 * src2->u.s._41) + (src1->u.s._21 * src2->u.s._42) + (src1->u.s._31 * src2->u.s._43) + (src1->u.s._41 * src2->u.s._44);

    temp.u.s._12 = (src1->u.s._12 * src2->u.s._11) + (src1->u.s._22 * src2->u.s._12) + (src1->u.s._32 * src2->u.s._13) + (src1->u.s._42 * src2->u.s._14);
    temp.u.s._22 = (src1->u.s._12 * src2->u.s._21) + (src1->u.s._22 * src2->u.s._22) + (src1->u.s._32 * src2->u.s._23) + (src1->u.s._42 * src2->u.s._24);
    temp.u.s._32 = (src1->u.s._12 * src2->u.s._31) + (src1->u.s._22 * src2->u.s._32) + (src1->u.s._32 * src2->u.s._33) + (src1->u.s._42 * src2->u.s._34);
    temp.u.s._42 = (src1->u.s._12 * src2->u.s._41) + (src1->u.s._22 * src2->u.s._42) + (src1->u.s._32 * src2->u.s._43) + (src1->u.s._42 * src2->u.s._44);

    temp.u.s._13 = (src1->u.s._13 * src2->u.s._11) + (src1->u.s._23 * src2->u.s._12) + (src1->u.s._33 * src2->u.s._13) + (src1->u.s._43 * src2->u.s._14);
    temp.u.s._23 = (src1->u.s._13 * src2->u.s._21) + (src1->u.s._23 * src2->u.s._22) + (src1->u.s._33 * src2->u.s._23) + (src1->u.s._43 * src2->u.s._24);
    temp.u.s._33 = (src1->u.s._13 * src2->u.s._31) + (src1->u.s._23 * src2->u.s._32) + (src1->u.s._33 * src2->u.s._33) + (src1->u.s._43 * src2->u.s._34);
    temp.u.s._43 = (src1->u.s._13 * src2->u.s._41) + (src1->u.s._23 * src2->u.s._42) + (src1->u.s._33 * src2->u.s._43) + (src1->u.s._43 * src2->u.s._44);

    temp.u.s._14 = (src1->u.s._14 * src2->u.s._11) + (src1->u.s._24 * src2->u.s._12) + (src1->u.s._34 * src2->u.s._13) + (src1->u.s._44 * src2->u.s._14);
    temp.u.s._24 = (src1->u.s._14 * src2->u.s._21) + (src1->u.s._24 * src2->u.s._22) + (src1->u.s._34 * src2->u.s._23) + (src1->u.s._44 * src2->u.s._24);
    temp.u.s._34 = (src1->u.s._14 * src2->u.s._31) + (src1->u.s._24 * src2->u.s._32) + (src1->u.s._34 * src2->u.s._33) + (src1->u.s._44 * src2->u.s._34);
    temp.u.s._44 = (src1->u.s._14 * src2->u.s._41) + (src1->u.s._24 * src2->u.s._42) + (src1->u.s._34 * src2->u.s._43) + (src1->u.s._44 * src2->u.s._44);

    /* And copy the new matrix in the good storage.. */
    memcpy(dest, &temp, 16 * sizeof(float));
}

DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
    DWORD size = 0;
    int i;
2848 2849 2850 2851 2852 2853 2854
    int numTextures = (d3dvtVertexType & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;

    if (d3dvtVertexType & WINED3DFVF_NORMAL) size += 3 * sizeof(float);
    if (d3dvtVertexType & WINED3DFVF_DIFFUSE) size += sizeof(DWORD);
    if (d3dvtVertexType & WINED3DFVF_SPECULAR) size += sizeof(DWORD);
    if (d3dvtVertexType & WINED3DFVF_PSIZE) size += sizeof(DWORD);
    switch (d3dvtVertexType & WINED3DFVF_POSITION_MASK) {
2855
        case WINED3DFVF_XYZ:    size += 3 * sizeof(float); break;
2856
        case WINED3DFVF_XYZRHW: size += 4 * sizeof(float); break;
2857 2858 2859 2860 2861
        case WINED3DFVF_XYZB1:  size += 4 * sizeof(float); break;
        case WINED3DFVF_XYZB2:  size += 5 * sizeof(float); break;
        case WINED3DFVF_XYZB3:  size += 6 * sizeof(float); break;
        case WINED3DFVF_XYZB4:  size += 7 * sizeof(float); break;
        case WINED3DFVF_XYZB5:  size += 8 * sizeof(float); break;
2862
        case WINED3DFVF_XYZW:   size += 4 * sizeof(float); break;
2863
        default: ERR("Unexpected position mask\n");
2864 2865 2866 2867 2868 2869 2870
    }
    for (i = 0; i < numTextures; i++) {
        size += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i) * sizeof(float);
    }

    return size;
}
2871

2872 2873
void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_state *state,
        struct ffp_frag_settings *settings, BOOL ignore_textype)
2874
{
2875 2876 2877
#define ARG1 0x01
#define ARG2 0x02
#define ARG0 0x04
2878 2879
    static const unsigned char args[WINED3D_TOP_LERP + 1] =
    {
2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909
        /* undefined                        */  0,
        /* D3DTOP_DISABLE                   */  0,
        /* D3DTOP_SELECTARG1                */  ARG1,
        /* D3DTOP_SELECTARG2                */  ARG2,
        /* D3DTOP_MODULATE                  */  ARG1 | ARG2,
        /* D3DTOP_MODULATE2X                */  ARG1 | ARG2,
        /* D3DTOP_MODULATE4X                */  ARG1 | ARG2,
        /* D3DTOP_ADD                       */  ARG1 | ARG2,
        /* D3DTOP_ADDSIGNED                 */  ARG1 | ARG2,
        /* D3DTOP_ADDSIGNED2X               */  ARG1 | ARG2,
        /* D3DTOP_SUBTRACT                  */  ARG1 | ARG2,
        /* D3DTOP_ADDSMOOTH                 */  ARG1 | ARG2,
        /* D3DTOP_BLENDDIFFUSEALPHA         */  ARG1 | ARG2,
        /* D3DTOP_BLENDTEXTUREALPHA         */  ARG1 | ARG2,
        /* D3DTOP_BLENDFACTORALPHA          */  ARG1 | ARG2,
        /* D3DTOP_BLENDTEXTUREALPHAPM       */  ARG1 | ARG2,
        /* D3DTOP_BLENDCURRENTALPHA         */  ARG1 | ARG2,
        /* D3DTOP_PREMODULATE               */  ARG1 | ARG2,
        /* D3DTOP_MODULATEALPHA_ADDCOLOR    */  ARG1 | ARG2,
        /* D3DTOP_MODULATECOLOR_ADDALPHA    */  ARG1 | ARG2,
        /* D3DTOP_MODULATEINVALPHA_ADDCOLOR */  ARG1 | ARG2,
        /* D3DTOP_MODULATEINVCOLOR_ADDALPHA */  ARG1 | ARG2,
        /* D3DTOP_BUMPENVMAP                */  ARG1 | ARG2,
        /* D3DTOP_BUMPENVMAPLUMINANCE       */  ARG1 | ARG2,
        /* D3DTOP_DOTPRODUCT3               */  ARG1 | ARG2,
        /* D3DTOP_MULTIPLYADD               */  ARG1 | ARG2 | ARG0,
        /* D3DTOP_LERP                      */  ARG1 | ARG2 | ARG0
    };
    unsigned int i;
    DWORD ttff;
2910
    DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
2911
    const struct wined3d_surface *rt = state->fb->render_targets[0];
2912
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
2913

2914
    for (i = 0; i < gl_info->limits.texture_stages; ++i)
2915
    {
2916 2917
        const struct wined3d_texture *texture;

2918
        settings->op[i].padding = 0;
2919
        if (state->texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
2920
        {
2921 2922
            settings->op[i].cop = WINED3D_TOP_DISABLE;
            settings->op[i].aop = WINED3D_TOP_DISABLE;
2923 2924
            settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
            settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
2925
            settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
2926
            settings->op[i].dst = resultreg;
2927 2928
            settings->op[i].tex_type = tex_1d;
            settings->op[i].projected = proj_none;
2929 2930 2931
            i++;
            break;
        }
2932

2933
        if ((texture = state->textures[i]))
2934 2935 2936 2937
        {
            settings->op[i].color_fixup = texture->resource.format->color_fixup;
            if (ignore_textype)
            {
2938
                settings->op[i].tex_type = tex_1d;
2939 2940 2941
            }
            else
            {
2942
                switch (texture->target)
2943
                {
2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959
                    case GL_TEXTURE_1D:
                        settings->op[i].tex_type = tex_1d;
                        break;
                    case GL_TEXTURE_2D:
                        settings->op[i].tex_type = tex_2d;
                        break;
                    case GL_TEXTURE_3D:
                        settings->op[i].tex_type = tex_3d;
                        break;
                    case GL_TEXTURE_CUBE_MAP_ARB:
                        settings->op[i].tex_type = tex_cube;
                        break;
                    case GL_TEXTURE_RECTANGLE_ARB:
                        settings->op[i].tex_type = tex_rect;
                        break;
                }
2960 2961
            }
        } else {
2962
            settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
2963
            settings->op[i].tex_type = tex_1d;
2964
        }
2965

2966 2967
        cop = state->texture_states[i][WINED3D_TSS_COLOR_OP];
        aop = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
2968

2969 2970 2971
        carg1 = (args[cop] & ARG1) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG1] : ARG_UNUSED;
        carg2 = (args[cop] & ARG2) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG2] : ARG_UNUSED;
        carg0 = (args[cop] & ARG0) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG0] : ARG_UNUSED;
2972

2973
        if (is_invalid_op(state, i, cop, carg1, carg2, carg0))
2974
        {
2975 2976
            carg0 = ARG_UNUSED;
            carg2 = ARG_UNUSED;
2977
            carg1 = WINED3DTA_CURRENT;
2978
            cop = WINED3D_TOP_SELECT_ARG1;
2979 2980
        }

2981 2982
        if (cop == WINED3D_TOP_DOTPRODUCT3)
        {
2983 2984 2985 2986 2987 2988 2989
            /* A dotproduct3 on the colorop overwrites the alphaop operation and replicates
             * the color result to the alpha component of the destination
             */
            aop = cop;
            aarg1 = carg1;
            aarg2 = carg2;
            aarg0 = carg0;
2990 2991 2992
        }
        else
        {
2993 2994 2995
            aarg1 = (args[aop] & ARG1) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] : ARG_UNUSED;
            aarg2 = (args[aop] & ARG2) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] : ARG_UNUSED;
            aarg0 = (args[aop] & ARG0) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] : ARG_UNUSED;
2996
        }
2997

2998
        if (!i && state->textures[0] && state->render_states[WINED3D_RS_COLORKEYENABLE])
2999
        {
3000 3001
            GLenum texture_dimensions;

3002
            texture = state->textures[0];
3003
            texture_dimensions = texture->target;
3004

3005 3006
            if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
            {
3007
                struct wined3d_surface *surf = surface_from_resource(texture->sub_resources[0]);
3008

3009
                if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format->alpha_size)
3010
                {
3011
                    if (aop == WINED3D_TOP_DISABLE)
3012 3013
                    {
                       aarg1 = WINED3DTA_TEXTURE;
3014
                       aop = WINED3D_TOP_SELECT_ARG1;
3015
                    }
3016
                    else if (aop == WINED3D_TOP_SELECT_ARG1 && aarg1 != WINED3DTA_TEXTURE)
3017
                    {
3018
                        if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3019 3020
                        {
                            aarg2 = WINED3DTA_TEXTURE;
3021
                            aop = WINED3D_TOP_MODULATE;
3022 3023 3024
                        }
                        else aarg1 = WINED3DTA_TEXTURE;
                    }
3025
                    else if (aop == WINED3D_TOP_SELECT_ARG2 && aarg2 != WINED3DTA_TEXTURE)
3026
                    {
3027
                        if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3028 3029
                        {
                            aarg1 = WINED3DTA_TEXTURE;
3030
                            aop = WINED3D_TOP_MODULATE;
3031 3032
                        }
                        else aarg2 = WINED3DTA_TEXTURE;
3033 3034 3035 3036 3037
                    }
                }
            }
        }

3038
        if (is_invalid_op(state, i, aop, aarg1, aarg2, aarg0))
3039
        {
3040 3041
               aarg0 = ARG_UNUSED;
               aarg2 = ARG_UNUSED;
3042
               aarg1 = WINED3DTA_CURRENT;
3043
               aop = WINED3D_TOP_SELECT_ARG1;
3044 3045
        }

3046 3047 3048
        if (carg1 == WINED3DTA_TEXTURE || carg2 == WINED3DTA_TEXTURE || carg0 == WINED3DTA_TEXTURE
                || aarg1 == WINED3DTA_TEXTURE || aarg2 == WINED3DTA_TEXTURE || aarg0 == WINED3DTA_TEXTURE)
        {
3049
            ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
3050
            if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3))
3051
                settings->op[i].projected = proj_count3;
3052
            else if (ttff & WINED3D_TTFF_PROJECTED)
3053
                settings->op[i].projected = proj_count4;
3054
            else
3055
                settings->op[i].projected = proj_none;
3056 3057 3058
        }
        else
        {
3059
            settings->op[i].projected = proj_none;
3060
        }
3061

3062 3063 3064 3065 3066 3067 3068 3069 3070
        settings->op[i].cop = cop;
        settings->op[i].aop = aop;
        settings->op[i].carg0 = carg0;
        settings->op[i].carg1 = carg1;
        settings->op[i].carg2 = carg2;
        settings->op[i].aarg0 = aarg0;
        settings->op[i].aarg1 = aarg1;
        settings->op[i].aarg2 = aarg2;

3071
        if (state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP)
3072
            settings->op[i].dst = tempreg;
3073
        else
3074
            settings->op[i].dst = resultreg;
3075 3076 3077 3078
    }

    /* Clear unsupported stages */
    for(; i < MAX_TEXTURES; i++) {
3079 3080 3081
        memset(&settings->op[i], 0xff, sizeof(settings->op[i]));
    }

3082
    if (!state->render_states[WINED3D_RS_FOGENABLE])
3083
    {
3084
        settings->fog = FOG_OFF;
3085
    }
3086
    else if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
3087
    {
3088
        if (use_vs(state) || state->vertex_declaration->position_transformed)
3089
        {
3090
            settings->fog = FOG_LINEAR;
3091 3092 3093
        }
        else
        {
3094
            switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
3095
            {
3096 3097
                case WINED3D_FOG_NONE:
                case WINED3D_FOG_LINEAR:
3098 3099
                    settings->fog = FOG_LINEAR;
                    break;
3100
                case WINED3D_FOG_EXP:
3101 3102
                    settings->fog = FOG_EXP;
                    break;
3103
                case WINED3D_FOG_EXP2:
3104 3105 3106
                    settings->fog = FOG_EXP2;
                    break;
            }
3107
        }
3108 3109 3110
    }
    else
    {
3111
        switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
3112
        {
3113
            case WINED3D_FOG_LINEAR:
3114 3115
                settings->fog = FOG_LINEAR;
                break;
3116
            case WINED3D_FOG_EXP:
3117 3118
                settings->fog = FOG_EXP;
                break;
3119
            case WINED3D_FOG_EXP2:
3120 3121 3122
                settings->fog = FOG_EXP2;
                break;
        }
3123
    }
3124 3125
    if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB]
            && state->render_states[WINED3D_RS_SRGBWRITEENABLE]
3126
            && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
3127
    {
3128 3129 3130 3131
        settings->sRGB_write = 1;
    } else {
        settings->sRGB_write = 0;
    }
3132 3133
    if (device->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
            || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
3134
    {
3135
        /* No need to emulate clipplanes if GL supports native vertex shader clipping or if
3136 3137
         * the fixed function vertex pipeline is used(which always supports clipplanes), or
         * if no clipplane is enabled
3138 3139 3140 3141 3142
         */
        settings->emul_clipplanes = 0;
    } else {
        settings->emul_clipplanes = 1;
    }
3143 3144
}

3145
const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
3146
        const struct ffp_frag_settings *settings)
3147
{
3148 3149
    struct wine_rb_entry *entry = wine_rb_get(fragment_shaders, settings);
    return entry ? WINE_RB_ENTRY_VALUE(entry, struct ffp_frag_desc, entry) : NULL;
3150
}
3151

3152 3153
void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc)
{
3154
    /* Note that the key is the implementation independent part of the ffp_frag_desc structure,
3155 3156 3157 3158 3159
     * whereas desc points to an extended structure with implementation specific parts. */
    if (wine_rb_put(shaders, &desc->settings, &desc->entry) == -1)
    {
        ERR("Failed to insert ffp frag shader.\n");
    }
3160
}
3161

3162 3163 3164 3165
/* Activates the texture dimension according to the bound D3D texture. Does
 * not care for the colorop or correct gl texture unit (when using nvrc).
 * Requires the caller to activate the correct unit. */
/* Context activation is done by the caller (state handler). */
3166
void texture_activate_dimensions(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
3167
{
3168
    if (texture)
3169
    {
3170
        switch (texture->target)
3171
        {
3172
            case GL_TEXTURE_2D:
3173
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3174
                checkGLcall("glDisable(GL_TEXTURE_3D)");
3175 3176
                if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
                {
3177
                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3178 3179
                    checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
                }
3180 3181
                if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
                {
3182
                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3183
                    checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3184
                }
3185
                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3186
                checkGLcall("glEnable(GL_TEXTURE_2D)");
3187 3188
                break;
            case GL_TEXTURE_RECTANGLE_ARB:
3189
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3190
                checkGLcall("glDisable(GL_TEXTURE_2D)");
3191
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3192
                checkGLcall("glDisable(GL_TEXTURE_3D)");
3193 3194
                if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
                {
3195
                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3196
                    checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3197
                }
3198
                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_RECTANGLE_ARB);
3199
                checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
3200 3201
                break;
            case GL_TEXTURE_3D:
3202 3203
                if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
                {
3204
                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3205
                    checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3206
                }
3207 3208
                if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
                {
3209
                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3210 3211
                    checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
                }
3212
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3213
                checkGLcall("glDisable(GL_TEXTURE_2D)");
3214
                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D);
3215
                checkGLcall("glEnable(GL_TEXTURE_3D)");
3216 3217
                break;
            case GL_TEXTURE_CUBE_MAP_ARB:
3218
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3219
                checkGLcall("glDisable(GL_TEXTURE_2D)");
3220
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3221
                checkGLcall("glDisable(GL_TEXTURE_3D)");
3222 3223
                if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
                {
3224
                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3225
                    checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3226
                }
3227
                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3228
                checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
3229 3230
              break;
        }
3231 3232 3233 3234
    }
    else
    {
        gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3235
        checkGLcall("glEnable(GL_TEXTURE_2D)");
3236
        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3237
        checkGLcall("glDisable(GL_TEXTURE_3D)");
3238 3239
        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
        {
3240
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3241 3242
            checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
        }
3243 3244
        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
        {
3245
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3246
            checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3247
        }
3248
        /* Binding textures is done by samplers. A dummy texture will be bound */
3249 3250
    }
}
3251

3252
/* Context activation is done by the caller (state handler). */
3253
void sampler_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3254
{
3255 3256
    DWORD sampler = state_id - STATE_SAMPLER(0);
    DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
3257

3258 3259 3260 3261 3262 3263 3264
    /* No need to enable / disable anything here for unused samplers. The
     * tex_colorop handler takes care. Also no action is needed with pixel
     * shaders, or if tex_colorop will take care of this business. */
    if (mapped_stage == WINED3D_UNMAPPED_STAGE || mapped_stage >= context->gl_info->limits.textures)
        return;
    if (sampler >= state->lowest_disabled_stage)
        return;
3265
    if (isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)))
3266
        return;
3267

3268
    texture_activate_dimensions(state->textures[sampler], context->gl_info);
3269
}
3270

3271
void *wined3d_rb_alloc(size_t size)
3272
{
3273 3274
    return HeapAlloc(GetProcessHeap(), 0, size);
}
3275

3276 3277 3278 3279
void *wined3d_rb_realloc(void *ptr, size_t size)
{
    return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
}
3280

3281 3282 3283
void wined3d_rb_free(void *ptr)
{
    HeapFree(GetProcessHeap(), 0, ptr);
3284 3285
}

3286
static int ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry)
3287
{
3288 3289
    const struct ffp_frag_settings *ka = key;
    const struct ffp_frag_settings *kb = &WINE_RB_ENTRY_VALUE(entry, const struct ffp_frag_desc, entry)->settings;
3290

3291
    return memcmp(ka, kb, sizeof(*ka));
3292
}
3293

3294 3295 3296 3297 3298 3299 3300 3301
const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions =
{
    wined3d_rb_alloc,
    wined3d_rb_realloc,
    wined3d_rb_free,
    ffp_frag_program_key_compare,
};

3302 3303
UINT wined3d_log2i(UINT32 x)
{
3304
    static const UINT l[] =
3305
    {
3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321
        ~0U, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3322 3323 3324 3325 3326
    };
    UINT32 i;

    return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
}
3327 3328 3329 3330 3331

/* Set the shader type for this device, depending on the given capabilities
 * and the user preferences in wined3d_settings. */
void select_shader_mode(const struct wined3d_gl_info *gl_info, int *ps_selected, int *vs_selected)
{
3332 3333
    BOOL glsl = wined3d_settings.glslRequested && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 20);

3334
    if (wined3d_settings.vs_mode == VS_NONE) *vs_selected = SHADER_NONE;
3335
    else if (gl_info->supported[ARB_VERTEX_SHADER] && glsl)
3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346
    {
        /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
         * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
         * shaders only on this card. */
        if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2]) *vs_selected = SHADER_ARB;
        else *vs_selected = SHADER_GLSL;
    }
    else if (gl_info->supported[ARB_VERTEX_PROGRAM]) *vs_selected = SHADER_ARB;
    else *vs_selected = SHADER_NONE;

    if (wined3d_settings.ps_mode == PS_NONE) *ps_selected = SHADER_NONE;
3347
    else if (gl_info->supported[ARB_FRAGMENT_SHADER] && glsl) *ps_selected = SHADER_GLSL;
3348 3349 3350 3351
    else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) *ps_selected = SHADER_ARB;
    else if (gl_info->supported[ATI_FRAGMENT_SHADER]) *ps_selected = SHADER_ATI;
    else *ps_selected = SHADER_NONE;
}
3352

3353
const struct blit_shader *wined3d_select_blitter(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
3354 3355
        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374
{
    static const struct blit_shader * const blitters[] =
    {
        &arbfp_blit,
        &ffp_blit,
        &cpu_blit,
    };
    unsigned int i;

    for (i = 0; i < sizeof(blitters) / sizeof(*blitters); ++i)
    {
        if (blitters[i]->blit_supported(gl_info, blit_op,
                src_rect, src_usage, src_pool, src_format,
                dst_rect, dst_usage, dst_pool, dst_format))
            return blitters[i];
    }

    return NULL;
}
3375 3376 3377

void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect)
{
3378
    const struct wined3d_viewport *vp = &state->viewport;
3379

3380
    SetRect(rect, vp->x, vp->y, vp->x + vp->width, vp->y + vp->height);
3381

3382
    if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
3383 3384
        IntersectRect(rect, rect, &state->scissor_rect);
}