device.c 123 KB
Newer Older
1 2 3
/*
 * IDirect3DDevice9 implementation
 *
4
 * Copyright 2002-2005 Jason Edmeades
5 6
 * Copyright 2002-2005 Raphael Junqueira
 * Copyright 2005 Oliver Stieber
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24 25
 */

#include "config.h"
#include "d3d9_private.h"

26
WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
27

28
D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
29 30 31 32 33 34 35 36 37
{
    BYTE *c = (BYTE *)&format;

    /* Don't translate FOURCC formats */
    if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;

    switch(format)
    {
        case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
38 39 40 41 42 43 44 45
        case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
        case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
        case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
        case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
        case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
        case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
        case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
        case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
46
        case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
47 48
        case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
        case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
49 50
        case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
        case WINED3DFMT_R8G8B8A8_UNORM: return D3DFMT_A8B8G8R8;
51
        case WINED3DFMT_R8G8B8X8_UNORM: return D3DFMT_X8B8G8R8;
52
        case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
53
        case WINED3DFMT_B10G10R10A2_UNORM: return D3DFMT_A2R10G10B10;
54
        case WINED3DFMT_R16G16B16A16_UNORM: return D3DFMT_A16B16G16R16;
55 56 57 58 59
        case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
        case WINED3DFMT_P8_UINT: return D3DFMT_P8;
        case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
        case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
        case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
60
        case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
61 62
        case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
        case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
63 64
        case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
        case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
65
        case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
66
        case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
67 68
        case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
        case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
69
        case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
70 71
        case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
        case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
72
        case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
73 74 75
        case WINED3DFMT_L16_UNORM: return D3DFMT_L16;
        case WINED3DFMT_D32_FLOAT: return D3DFMT_D32F_LOCKABLE;
        case WINED3DFMT_S8_UINT_D24_FLOAT: return D3DFMT_D24FS8;
76
        case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
77 78 79 80 81 82 83 84 85
        case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
        case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
        case WINED3DFMT_R16G16B16A16_SNORM: return D3DFMT_Q16W16V16U16;
        case WINED3DFMT_R16_FLOAT: return D3DFMT_R16F;
        case WINED3DFMT_R16G16_FLOAT: return D3DFMT_G16R16F;
        case WINED3DFMT_R16G16B16A16_FLOAT: return D3DFMT_A16B16G16R16F;
        case WINED3DFMT_R32_FLOAT: return D3DFMT_R32F;
        case WINED3DFMT_R32G32_FLOAT: return D3DFMT_G32R32F;
        case WINED3DFMT_R32G32B32A32_FLOAT: return D3DFMT_A32B32G32R32F;
86
        case WINED3DFMT_R8G8_SNORM_Cx: return D3DFMT_CxV8U8;
87
        default:
88
            FIXME("Unhandled wined3d format %#x.\n", format);
89 90 91 92
            return D3DFMT_UNKNOWN;
    }
}

93
enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
94 95 96 97 98 99 100 101 102
{
    BYTE *c = (BYTE *)&format;

    /* Don't translate FOURCC formats */
    if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;

    switch(format)
    {
        case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
103 104 105 106 107 108 109 110
        case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
        case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
        case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
        case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
        case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
        case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
        case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
        case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
111
        case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
112 113
        case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
        case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
114 115
        case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
        case D3DFMT_A8B8G8R8: return WINED3DFMT_R8G8B8A8_UNORM;
116
        case D3DFMT_X8B8G8R8: return WINED3DFMT_R8G8B8X8_UNORM;
117
        case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
118
        case D3DFMT_A2R10G10B10: return WINED3DFMT_B10G10R10A2_UNORM;
119
        case D3DFMT_A16B16G16R16: return WINED3DFMT_R16G16B16A16_UNORM;
120 121 122 123 124
        case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
        case D3DFMT_P8: return WINED3DFMT_P8_UINT;
        case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
        case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
        case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
125
        case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
126 127
        case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
        case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
128 129
        case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
        case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
130
        case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
131
        case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
132 133
        case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
        case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
134
        case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
135 136
        case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
        case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
137
        case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
138 139 140
        case D3DFMT_L16: return WINED3DFMT_L16_UNORM;
        case D3DFMT_D32F_LOCKABLE: return WINED3DFMT_D32_FLOAT;
        case D3DFMT_D24FS8: return WINED3DFMT_S8_UINT_D24_FLOAT;
141
        case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
142 143 144 145 146 147 148 149 150
        case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
        case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
        case D3DFMT_Q16W16V16U16: return WINED3DFMT_R16G16B16A16_SNORM;
        case D3DFMT_R16F: return WINED3DFMT_R16_FLOAT;
        case D3DFMT_G16R16F: return WINED3DFMT_R16G16_FLOAT;
        case D3DFMT_A16B16G16R16F: return WINED3DFMT_R16G16B16A16_FLOAT;
        case D3DFMT_R32F: return WINED3DFMT_R32_FLOAT;
        case D3DFMT_G32R32F: return WINED3DFMT_R32G32_FLOAT;
        case D3DFMT_A32B32G32R32F: return WINED3DFMT_R32G32B32A32_FLOAT;
151
        case D3DFMT_CxV8U8: return WINED3DFMT_R8G8_SNORM_Cx;
152 153 154 155 156
        default:
            FIXME("Unhandled D3DFORMAT %#x\n", format);
            return WINED3DFMT_UNKNOWN;
    }
}
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
{
    switch(primitive_type)
    {
        case D3DPT_POINTLIST:
            return primitive_count;

        case D3DPT_LINELIST:
            return primitive_count * 2;

        case D3DPT_LINESTRIP:
            return primitive_count + 1;

        case D3DPT_TRIANGLELIST:
            return primitive_count * 3;

        case D3DPT_TRIANGLESTRIP:
        case D3DPT_TRIANGLEFAN:
            return primitive_count + 2;

        default:
            FIXME("Unhandled primitive type %#x\n", primitive_type);
            return 0;
    }
}

184 185
static inline IDirect3DDevice9Impl *impl_from_IDirect3DDevice9Ex(IDirect3DDevice9Ex *iface)
{
186
    return CONTAINING_RECORD(iface, IDirect3DDevice9Impl, IDirect3DDevice9Ex_iface);
187 188
}

189
static HRESULT WINAPI IDirect3DDevice9Impl_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
190
{
191
    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
Henri Verbeet's avatar
Henri Verbeet committed
192

193 194 195
    if (IsEqualGUID(riid, &IID_IDirect3DDevice9)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
196
        IDirect3DDevice9Ex_AddRef(iface);
197
        *out = iface;
H. Verbeet's avatar
H. Verbeet committed
198
        return S_OK;
199 200 201 202 203 204
    }

    if (IsEqualGUID(riid, &IID_IDirect3DDevice9Ex))
    {
        IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);

205
        /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
206
         * It doesn't matter with which function the device was created. */
207
        if (!device->d3d_parent->extended)
208
        {
209 210
            WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n");
            *out = NULL;
211 212
            return E_NOINTERFACE;
        }
213 214 215 216

        IDirect3DDevice9Ex_AddRef(iface);
        *out = iface;
        return S_OK;
217 218
    }

219 220 221
    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));

    *out = NULL;
222 223 224
    return E_NOINTERFACE;
}

225 226 227
static ULONG WINAPI IDirect3DDevice9Impl_AddRef(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
228 229
    ULONG ref = InterlockedIncrement(&This->ref);

Henri Verbeet's avatar
Henri Verbeet committed
230
    TRACE("%p increasing refcount to %u.\n", iface, ref);
231 232

    return ref;
233 234
}

235 236
static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(IDirect3DDevice9Ex *iface)
{
237
    IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
238 239
    ULONG ref;

240 241 242 243
    if (device->inDestruction)
        return 0;

    ref = InterlockedDecrement(&device->ref);
244

Henri Verbeet's avatar
Henri Verbeet committed
245
    TRACE("%p decreasing refcount to %u.\n", iface, ref);
246

247 248 249 250
    if (!ref)
    {
        unsigned i;
        device->inDestruction = TRUE;
251

252 253 254 255 256 257
        wined3d_mutex_lock();
        for (i = 0; i < device->fvf_decl_count; ++i)
        {
            wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
        }
        HeapFree(GetProcessHeap(), 0, device->fvf_decls);
258

259 260 261 262
        wined3d_device_uninit_3d(device->wined3d_device);
        wined3d_device_release_focus_window(device->wined3d_device);
        wined3d_device_decref(device->wined3d_device);
        wined3d_mutex_unlock();
263

264
        IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
265

266
        HeapFree(GetProcessHeap(), 0, device);
267
    }
268

269 270 271
    return ref;
}

272 273
static HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(IDirect3DDevice9Ex *iface)
{
274
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
Henri Verbeet's avatar
Henri Verbeet committed
275 276

    TRACE("iface %p.\n", iface);
277

278 279 280 281
    if (This->notreset)
    {
        TRACE("D3D9 device is marked not reset.\n");
        return D3DERR_DEVICENOTRESET;
282 283
    }

284
    return D3D_OK;
285 286
}

287 288 289
static UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
290
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
291 292

    TRACE("iface %p.\n", iface);
293

294
    wined3d_mutex_lock();
295
    hr = wined3d_device_get_available_texture_mem(This->wined3d_device);
296 297
    wined3d_mutex_unlock();

298
    return hr;
299 300
}

301 302 303
static HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
Henri Verbeet's avatar
Henri Verbeet committed
304 305

    TRACE("iface %p.\n", iface);
306

307
    wined3d_mutex_lock();
308
    wined3d_device_evict_managed_resources(This->wined3d_device);
309 310
    wined3d_mutex_unlock();

311
    return D3D_OK;
312 313
}

314 315
static HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(IDirect3DDevice9Ex *iface,
        IDirect3D9 **ppD3D9)
316
{
317
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
318

Henri Verbeet's avatar
Henri Verbeet committed
319
    TRACE("iface %p, d3d9 %p.\n", iface, ppD3D9);
320 321 322 323

    if (NULL == ppD3D9) {
        return D3DERR_INVALIDCALL;
    }
324

325 326
    return IDirect3D9Ex_QueryInterface(&This->d3d_parent->IDirect3D9Ex_iface,
            &IID_IDirect3D9, (void **)ppD3D9);
327 328
}

329 330 331
static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *pCaps)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
332 333 334
    HRESULT hrc = D3D_OK;
    WINED3DCAPS *pWineCaps;

Henri Verbeet's avatar
Henri Verbeet committed
335 336
    TRACE("iface %p, caps %p.\n", iface, pCaps);

337 338 339 340 341 342 343 344
    if(NULL == pCaps){
        return D3DERR_INVALIDCALL;
    }
    pWineCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINED3DCAPS));
    if(pWineCaps == NULL){
        return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
    }

345
    memset(pCaps, 0, sizeof(*pCaps));
346 347

    wined3d_mutex_lock();
348
    hrc = wined3d_device_get_device_caps(This->wined3d_device, pWineCaps);
349 350
    wined3d_mutex_unlock();

351
    WINECAPSTOD3D9CAPS(pCaps, pWineCaps)
352
    HeapFree(GetProcessHeap(), 0, pWineCaps);
353 354 355 356 357 358

    /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */
    pCaps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;

    filter_caps(pCaps);

359 360
    TRACE("Returning %p %p\n", This, pCaps);
    return hrc;
361 362
}

363 364 365 366
static HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(IDirect3DDevice9Ex *iface,
        UINT iSwapChain, D3DDISPLAYMODE *pMode)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
367
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
368 369

    TRACE("iface %p, swapchain %u, mode %p.\n", iface, iSwapChain, pMode);
370

371
    wined3d_mutex_lock();
372
    hr = wined3d_device_get_display_mode(This->wined3d_device, iSwapChain, (struct wined3d_display_mode *)pMode);
373
    wined3d_mutex_unlock();
374 375 376

    if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format);

377
    return hr;
378 379
}

380 381 382 383
static HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(IDirect3DDevice9Ex *iface,
        D3DDEVICE_CREATION_PARAMETERS *pParameters)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
384
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
385 386

    TRACE("iface %p, parameters %p.\n", iface, pParameters);
387

388
    wined3d_mutex_lock();
389
    hr = wined3d_device_get_creation_parameters(This->wined3d_device,
390
            (struct wined3d_device_creation_parameters *)pParameters);
391 392
    wined3d_mutex_unlock();

393
    return hr;
394 395
}

396 397 398 399
static HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(IDirect3DDevice9Ex *iface,
        UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9 *pCursorBitmap)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
400
    IDirect3DSurface9Impl *pSurface = unsafe_impl_from_IDirect3DSurface9(pCursorBitmap);
401 402
    HRESULT hr;

Henri Verbeet's avatar
Henri Verbeet committed
403 404 405
    TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
            iface, XHotSpot, YHotSpot, pCursorBitmap);

406 407 408 409
    if (!pCursorBitmap)
    {
        WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
        return D3DERR_INVALIDCALL;
410
    }
411

412
    wined3d_mutex_lock();
413
    hr = wined3d_device_set_cursor_properties(This->wined3d_device, XHotSpot, YHotSpot, pSurface->wined3d_surface);
414 415
    wined3d_mutex_unlock();

416
    return hr;
417 418
}

419 420 421 422
static void WINAPI IDirect3DDevice9Impl_SetCursorPosition(IDirect3DDevice9Ex *iface,
        int XScreenSpace, int YScreenSpace, DWORD Flags)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
Henri Verbeet's avatar
Henri Verbeet committed
423 424

    TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, XScreenSpace, YScreenSpace, Flags);
425

426
    wined3d_mutex_lock();
427
    wined3d_device_set_cursor_position(This->wined3d_device, XScreenSpace, YScreenSpace, Flags);
428
    wined3d_mutex_unlock();
429 430
}

431 432 433
static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(IDirect3DDevice9Ex *iface, BOOL bShow)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
434
    BOOL ret;
Henri Verbeet's avatar
Henri Verbeet committed
435 436

    TRACE("iface %p, show %#x.\n", iface, bShow);
437

438
    wined3d_mutex_lock();
439
    ret = wined3d_device_show_cursor(This->wined3d_device, bShow);
440 441
    wined3d_mutex_unlock();

442
    return ret;
443 444
}

445 446 447
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_CreateAdditionalSwapChain(IDirect3DDevice9Ex *iface,
        D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain)
{
448
    IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
449 450 451 452 453 454
    IDirect3DSwapChain9Impl *object;
    HRESULT hr;

    TRACE("iface %p, present_parameters %p, swapchain %p.\n",
            iface, present_parameters, swapchain);

455
    if (SUCCEEDED(hr = d3d9_swapchain_create(device, present_parameters, &object)))
456
        *swapchain = &object->IDirect3DSwapChain9_iface;
457

458
    return hr;
459 460
}

461 462 463
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_GetSwapChain(IDirect3DDevice9Ex *iface,
        UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
{
464
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
465
    struct wined3d_swapchain *wined3d_swapchain = NULL;
466
    IDirect3DSwapChain9Impl *swapchain_impl;
467 468 469 470 471
    HRESULT hr;

    TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);

    wined3d_mutex_lock();
472
    hr = wined3d_device_get_swapchain(This->wined3d_device, swapchain_idx, &wined3d_swapchain);
473
    if (SUCCEEDED(hr) && wined3d_swapchain)
474
    {
475 476
       swapchain_impl = wined3d_swapchain_get_parent(wined3d_swapchain);
       *swapchain = &swapchain_impl->IDirect3DSwapChain9_iface;
477
       IDirect3DSwapChain9_AddRef(*swapchain);
478
       wined3d_swapchain_decref(wined3d_swapchain);
479 480 481 482 483 484 485 486 487 488 489 490
    }
    else
    {
        *swapchain = NULL;
    }
    wined3d_mutex_unlock();

    return hr;
}

static UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface)
{
491
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
492 493 494 495 496
    UINT count;

    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
497
    count = wined3d_device_get_swapchain_count(This->wined3d_device);
498 499 500 501 502
    wined3d_mutex_unlock();

    return count;
}

503
static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
504
{
505
    struct wined3d_resource_desc desc;
506

507
    wined3d_resource_get_desc(resource, &desc);
508
    if (desc.pool == WINED3D_POOL_DEFAULT)
509
    {
510
        IDirect3DSurface9Impl *surface;
511

512
        if (desc.resource_type != WINED3D_RTYPE_SURFACE)
513
        {
514
            WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
515
            return D3DERR_INVALIDCALL;
516 517 518
        }

        surface = wined3d_resource_get_parent(resource);
519
        if (surface->ref)
520 521
        {
            WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
522
            return D3DERR_INVALIDCALL;
523
        }
524 525

        WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
526 527
    }

528
    return D3D_OK;
529 530
}

531 532 533 534
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Reset(IDirect3DDevice9Ex *iface,
        D3DPRESENT_PARAMETERS *pPresentationParameters)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
535
    struct wined3d_swapchain_desc swapchain_desc;
536 537
    HRESULT hr;

Henri Verbeet's avatar
Henri Verbeet committed
538
    TRACE("iface %p, present_parameters %p.\n", iface, pPresentationParameters);
539

540 541 542 543 544 545 546 547
    /* Reset states that hold a COM object. WineD3D holds an internal reference to set objects, because
     * such objects can still be used for rendering after their external d3d9 object has been destroyed.
     * These objects must not be enumerated. Unsetting them tells WineD3D that the application will not
     * make use of the hidden reference and destroys the objects.
     *
     * Unsetting them is no problem, because the states are supposed to be reset anyway. If the validation
     * below fails, the device is considered "lost", and _Reset and _Release are the only allowed calls
     */
548
    wined3d_mutex_lock();
549

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
    swapchain_desc.backbuffer_width = pPresentationParameters->BackBufferWidth;
    swapchain_desc.backbuffer_height = pPresentationParameters->BackBufferHeight;
    swapchain_desc.backbuffer_format = wined3dformat_from_d3dformat(pPresentationParameters->BackBufferFormat);
    swapchain_desc.backbuffer_count = pPresentationParameters->BackBufferCount;
    swapchain_desc.multisample_type = pPresentationParameters->MultiSampleType;
    swapchain_desc.multisample_quality = pPresentationParameters->MultiSampleQuality;
    swapchain_desc.swap_effect = pPresentationParameters->SwapEffect;
    swapchain_desc.device_window = pPresentationParameters->hDeviceWindow;
    swapchain_desc.windowed = pPresentationParameters->Windowed;
    swapchain_desc.enable_auto_depth_stencil = pPresentationParameters->EnableAutoDepthStencil;
    swapchain_desc.auto_depth_stencil_format = wined3dformat_from_d3dformat(pPresentationParameters->AutoDepthStencilFormat);
    swapchain_desc.flags = pPresentationParameters->Flags;
    swapchain_desc.refresh_rate = pPresentationParameters->FullScreen_RefreshRateInHz;
    swapchain_desc.swap_interval = pPresentationParameters->PresentationInterval;
    swapchain_desc.auto_restore_display_mode = TRUE;

    hr = wined3d_device_reset(This->wined3d_device, &swapchain_desc, reset_enum_callback);
567
    if (FAILED(hr))
568
        This->notreset = TRUE;
569
    else
570
        This->notreset = FALSE;
571

572
    wined3d_mutex_unlock();
Henri Verbeet's avatar
Henri Verbeet committed
573

574
    return hr;
575 576
}

577 578 579 580 581
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Present(IDirect3DDevice9Ex *iface,
        const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride,
        const RGNDATA *pDirtyRegion)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
582
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
583 584 585

    TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
            iface, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
586

587
    wined3d_mutex_lock();
588
    hr = wined3d_device_present(This->wined3d_device, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
589 590
    wined3d_mutex_unlock();

591 592
    return hr;
 }
593

594 595 596
static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(IDirect3DDevice9Ex *iface,
        UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer)
{
597
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
598
    struct wined3d_surface *wined3d_surface = NULL;
599
    IDirect3DSurface9Impl *surface_impl;
600
    HRESULT hr;
601

Henri Verbeet's avatar
Henri Verbeet committed
602 603
    TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
            iface, iSwapChain, BackBuffer, Type, ppBackBuffer);
604

605
    wined3d_mutex_lock();
606
    hr = wined3d_device_get_back_buffer(This->wined3d_device, iSwapChain,
607
            BackBuffer, (enum wined3d_backbuffer_type)Type, &wined3d_surface);
608
    if (SUCCEEDED(hr) && wined3d_surface && ppBackBuffer)
609
    {
610 611
        surface_impl = wined3d_surface_get_parent(wined3d_surface);
        *ppBackBuffer = &surface_impl->IDirect3DSurface9_iface;
612
        IDirect3DSurface9_AddRef(*ppBackBuffer);
613
        wined3d_surface_decref(wined3d_surface);
614
    }
615 616
    wined3d_mutex_unlock();

617
    return hr;
618
}
619 620 621 622
static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(IDirect3DDevice9Ex *iface,
        UINT iSwapChain, D3DRASTER_STATUS *pRasterStatus)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
623
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
624 625

    TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, iSwapChain, pRasterStatus);
626

627
    wined3d_mutex_lock();
628 629
    hr = wined3d_device_get_raster_status(This->wined3d_device,
            iSwapChain, (struct wined3d_raster_status *)pRasterStatus);
630 631
    wined3d_mutex_unlock();

632
    return hr;
633 634
}

635 636 637 638
static HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(IDirect3DDevice9Ex *iface,
        BOOL bEnableDialogs)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
639
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
640 641

    TRACE("iface %p, enable %#x.\n", iface, bEnableDialogs);
642

643
    wined3d_mutex_lock();
644
    hr = wined3d_device_set_dialog_box_mode(This->wined3d_device, bEnableDialogs);
645 646
    wined3d_mutex_unlock();

647
    return hr;
648 649
}

650 651 652
static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(IDirect3DDevice9Ex *iface, UINT iSwapChain,
        DWORD Flags, const D3DGAMMARAMP *pRamp)
{
653
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
Henri Verbeet's avatar
Henri Verbeet committed
654 655

    TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, iSwapChain, Flags, pRamp);
656

657
    /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
658
    wined3d_mutex_lock();
659
    wined3d_device_set_gamma_ramp(This->wined3d_device, iSwapChain, Flags, (const struct wined3d_gamma_ramp *)pRamp);
660
    wined3d_mutex_unlock();
661 662
}

663 664 665 666
static void WINAPI IDirect3DDevice9Impl_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT iSwapChain,
        D3DGAMMARAMP *pRamp)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
Henri Verbeet's avatar
Henri Verbeet committed
667 668

    TRACE("iface %p, swapchain %u, ramp %p.\n", iface, iSwapChain, pRamp);
669

670
    /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
671
    wined3d_mutex_lock();
672
    wined3d_device_get_gamma_ramp(This->wined3d_device, iSwapChain, (struct wined3d_gamma_ramp *)pRamp);
673
    wined3d_mutex_unlock();
674 675
}

676 677 678 679
static HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(IDirect3DDevice9Ex *iface,
        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
        D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle)
{
680
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
681
    struct d3d9_texture *object;
682
    BOOL set_mem = FALSE;
683 684 685 686 687
    HRESULT hr;

    TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
            iface, width, height, levels, usage, format, pool, texture, shared_handle);

688
    if (shared_handle)
689 690 691 692 693 694 695 696 697 698
    {
        if (pool == D3DPOOL_SYSTEMMEM)
        {
            if (levels != 1)
                return D3DERR_INVALIDCALL;
            set_mem = TRUE;
        }
        else
            FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
    }
699

700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate texture memory.\n");
        return D3DERR_OUTOFVIDEOMEMORY;
    }

    hr = texture_init(object, This, width, height, levels, usage, format, pool);
    if (FAILED(hr))
    {
        WARN("Failed to initialize texture, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

715 716 717 718 719 720 721 722 723 724
    if (set_mem)
    {
        struct wined3d_resource *resource;
        IDirect3DSurface9Impl *surface;

        resource = wined3d_texture_get_sub_resource(object->wined3d_texture, 0);
        surface = wined3d_resource_get_parent(resource);
        wined3d_surface_set_mem(surface->wined3d_surface, *shared_handle);
    }

725
    TRACE("Created texture %p.\n", object);
726
    *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
727 728 729 730

    return D3D_OK;
}

731 732 733 734
static HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
        D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle)
{
735
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
736
    struct d3d9_texture *object;
737 738 739 740 741 742 743
    HRESULT hr;

    TRACE("iface %p, width %u, height %u, depth %u, levels %u\n",
            iface, width, height, depth, levels);
    TRACE("usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
            usage, format, pool, texture, shared_handle);

744 745 746
    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);

747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate volume texture memory.\n");
        return D3DERR_OUTOFVIDEOMEMORY;
    }

    hr = volumetexture_init(object, This, width, height, depth, levels, usage, format, pool);
    if (FAILED(hr))
    {
        WARN("Failed to initialize volume texture, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created volume texture %p.\n", object);
763
    *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface;
764 765 766 767

    return D3D_OK;
}

768 769 770 771
static HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(IDirect3DDevice9Ex *iface,
        UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool,
        IDirect3DCubeTexture9 **texture, HANDLE *shared_handle)
{
772
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
773
    struct d3d9_texture *object;
774 775 776 777 778
    HRESULT hr;

    TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
            iface, edge_length, levels, usage, format, pool, texture, shared_handle);

779 780 781
    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);

782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate cube texture memory.\n");
        return D3DERR_OUTOFVIDEOMEMORY;
    }

    hr = cubetexture_init(object, This, edge_length, levels, usage, format, pool);
    if (FAILED(hr))
    {
        WARN("Failed to initialize cube texture, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created cube texture %p.\n", object);
798
    *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface;
799 800 801 802

    return D3D_OK;
}

803 804 805
static HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size,
        DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer,
        HANDLE *shared_handle)
806
{
807
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
808 809 810 811 812 813
    IDirect3DVertexBuffer9Impl *object;
    HRESULT hr;

    TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n",
            iface, size, usage, fvf, pool, buffer, shared_handle);

814 815 816
    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);

817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate buffer memory.\n");
        return D3DERR_OUTOFVIDEOMEMORY;
    }

    hr = vertexbuffer_init(object, This, size, usage, fvf, pool);
    if (FAILED(hr))
    {
        WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created vertex buffer %p.\n", object);
833
    *buffer = &object->IDirect3DVertexBuffer9_iface;
834 835 836 837

    return D3D_OK;
}

838 839 840
static HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size,
        DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer,
        HANDLE *shared_handle)
841
{
842
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
843 844 845 846 847 848
    IDirect3DIndexBuffer9Impl *object;
    HRESULT hr;

    TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n",
            iface, size, usage, format, pool, buffer, shared_handle);

849 850 851
    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate buffer memory.\n");
        return D3DERR_OUTOFVIDEOMEMORY;
    }

    hr = indexbuffer_init(object, This, size, usage, format, pool);
    if (FAILED(hr))
    {
        WARN("Failed to initialize index buffer, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created index buffer %p.\n", object);
868
    *buffer = &object->IDirect3DIndexBuffer9_iface;
869 870 871 872

    return D3D_OK;
}

873 874 875 876
static HRESULT IDirect3DDevice9Impl_CreateSurface(IDirect3DDevice9Impl *device, UINT Width,
        UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level,
        IDirect3DSurface9 **ppSurface, UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample,
        DWORD MultisampleQuality)
877
{
878
    IDirect3DSurface9Impl *object;
879
    HRESULT hr;
880

881
    TRACE("device %p, width %u, height %u, format %#x, lockable %#x, discard %#x, level %u, surface %p.\n"
Henri Verbeet's avatar
Henri Verbeet committed
882
            "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
883 884
            device, Width, Height, Format, Lockable, Discard, Level, ppSurface, Usage, Pool,
            MultiSample, MultisampleQuality);
885 886

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface9Impl));
887 888 889
    if (!object)
    {
        FIXME("Failed to allocate surface memory.\n");
890 891 892
        return D3DERR_OUTOFVIDEOMEMORY;
    }

893 894
    hr = surface_init(object, device, Width, Height, Format, Lockable, Discard, Level, Usage, Pool,
            MultiSample, MultisampleQuality);
895
    if (FAILED(hr))
896
    {
897 898 899
        WARN("Failed to initialize surface, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
900 901
    }

902
    TRACE("Created surface %p.\n", object);
903
    *ppSurface = &object->IDirect3DSurface9_iface;
904

905
    return D3D_OK;
906 907
}

908 909
static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(IDirect3DDevice9Ex *iface, UINT Width,
        UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
910
        BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *shared_handle)
911
{
912
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
913
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
914 915 916 917

    TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
            "lockable %#x, surface %p, shared_handle %p.\n",
            iface, Width, Height, Format, MultiSample, MultisampleQuality,
918 919 920 921
            Lockable, ppSurface, shared_handle);

    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
922

923 924 925
    hr = IDirect3DDevice9Impl_CreateSurface(This, Width, Height, Format, Lockable,
            FALSE /* Discard */, 0 /* Level */, ppSurface, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT,
            MultiSample, MultisampleQuality);
926 927

    return hr;
928 929
}

930 931 932
static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(IDirect3DDevice9Ex *iface,
        UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample,
        DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface,
933
        HANDLE *shared_handle)
934 935
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
936
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
937 938 939 940

    TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
            "discard %#x, surface %p, shared_handle %p.\n",
            iface, Width, Height, Format, MultiSample, MultisampleQuality,
941 942 943 944
            Discard, ppSurface, shared_handle);

    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
945

946 947 948
    hr = IDirect3DDevice9Impl_CreateSurface(This, Width, Height, Format, TRUE /* Lockable */,
            Discard, 0 /* Level */, ppSurface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, MultiSample,
            MultisampleQuality);
949 950

    return hr;
951 952
}

953

954 955 956 957 958
static HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(IDirect3DDevice9Ex *iface,
        IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect,
        IDirect3DSurface9 *pDestinationSurface, const POINT *pDestPoint)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
959 960
    IDirect3DSurface9Impl *src = unsafe_impl_from_IDirect3DSurface9(pSourceSurface);
    IDirect3DSurface9Impl *dst = unsafe_impl_from_IDirect3DSurface9(pDestinationSurface);
961
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
962 963 964

    TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n",
            iface, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
965

966
    wined3d_mutex_lock();
967 968
    hr = wined3d_device_update_surface(This->wined3d_device, src->wined3d_surface, pSourceRect,
            dst->wined3d_surface, pDestPoint);
969 970
    wined3d_mutex_unlock();

971
    return hr;
972 973
}

974 975 976
static HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(IDirect3DDevice9Ex *iface,
        IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture)
{
977
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
978
    struct d3d9_texture *src_impl, *dst_impl;
979
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
980

981
    TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
982

983 984 985
    src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture);
    dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);

986
    wined3d_mutex_lock();
987
    hr = wined3d_device_update_texture(This->wined3d_device,
988
            src_impl->wined3d_texture, dst_impl->wined3d_texture);
989 990
    wined3d_mutex_unlock();

991
    return hr;
992 993
}

Henri Verbeet's avatar
Henri Verbeet committed
994 995 996
static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(IDirect3DDevice9Ex *iface,
        IDirect3DSurface9 *pRenderTarget, IDirect3DSurface9 *pDestSurface)
{
997 998
    IDirect3DSurface9Impl *renderTarget = unsafe_impl_from_IDirect3DSurface9(pRenderTarget);
    IDirect3DSurface9Impl *destSurface = unsafe_impl_from_IDirect3DSurface9(pDestSurface);
999
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1000 1001

    TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, pRenderTarget, pDestSurface);
1002

1003
    wined3d_mutex_lock();
1004
    hr = wined3d_surface_get_render_target_data(destSurface->wined3d_surface, renderTarget->wined3d_surface);
1005 1006
    wined3d_mutex_unlock();

1007
    return hr;
1008 1009
}

1010 1011 1012 1013
static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(IDirect3DDevice9Ex *iface,
        UINT iSwapChain, IDirect3DSurface9 *pDestSurface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1014
    IDirect3DSurface9Impl *destSurface = unsafe_impl_from_IDirect3DSurface9(pDestSurface);
1015
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1016 1017

    TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, iSwapChain, pDestSurface);
1018

1019
    wined3d_mutex_lock();
1020
    hr = wined3d_device_get_front_buffer_data(This->wined3d_device, iSwapChain, destSurface->wined3d_surface);
1021 1022
    wined3d_mutex_unlock();

1023
    return hr;
1024 1025
}

1026 1027
static HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *src_surface,
        const RECT *src_rect, IDirect3DSurface9 *dst_surface, const RECT *dst_rect, D3DTEXTUREFILTERTYPE filter)
Henri Verbeet's avatar
Henri Verbeet committed
1028
{
1029 1030 1031 1032 1033 1034
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
    IDirect3DSurface9Impl *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
    IDirect3DSurface9Impl *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
    HRESULT hr = D3DERR_INVALIDCALL;
    struct wined3d_resource_desc src_desc, dst_desc;
    struct wined3d_resource *wined3d_resource;
1035

Henri Verbeet's avatar
Henri Verbeet committed
1036
    TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
1037
            iface, src_surface, src_rect, dst_surface, dst_rect, filter);
1038 1039

    wined3d_mutex_lock();
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface);
    wined3d_resource_get_desc(wined3d_resource, &dst_desc);

    wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface);
    wined3d_resource_get_desc(wined3d_resource, &src_desc);

    if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
    {
        if (This->in_scene)
        {
            WARN("Rejecting depth / stencil blit while in scene.\n");
            goto done;
        }

        if (src_rect)
        {
            if (src_rect->left || src_rect->top || src_rect->right != src_desc.width
                    || src_rect->bottom != src_desc.height)
            {
                WARN("Rejecting depth / stencil blit with invalid source rect %s.\n",
                        wine_dbgstr_rect(src_rect));
                goto done;
            }
        }
        if (dst_rect)
        {
            if (dst_rect->left || dst_rect->top || dst_rect->right != dst_desc.width
                    || dst_rect->bottom != dst_desc.height)
            {
                WARN("Rejecting depth / stencil blit with invalid destination rect %s.\n",
                        wine_dbgstr_rect(dst_rect));
                goto done;
            }
        }
        if (src_desc.width != dst_desc.width || src_desc.height != dst_desc.height)
        {
            WARN("Rejecting depth / stencil blit with mismatched surface sizes.\n");
            goto done;
        }
    }

    hr = wined3d_surface_blt(dst->wined3d_surface, dst_rect, src->wined3d_surface, src_rect, 0, NULL, filter);
1082 1083
    if (hr == WINEDDERR_INVALIDRECT)
        hr = D3DERR_INVALIDCALL;
1084

1085 1086
done:
    wined3d_mutex_unlock();
1087
    return hr;
1088 1089
}

1090 1091 1092
static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(IDirect3DDevice9Ex *iface,
        IDirect3DSurface9 *pSurface, const RECT *pRect, D3DCOLOR color)
{
1093
    const struct wined3d_color c =
1094 1095 1096 1097 1098 1099
    {
        ((color >> 16) & 0xff) / 255.0f,
        ((color >>  8) & 0xff) / 255.0f,
        (color & 0xff) / 255.0f,
        ((color >> 24) & 0xff) / 255.0f,
    };
1100
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1101
    IDirect3DSurface9Impl *surface = unsafe_impl_from_IDirect3DSurface9(pSurface);
1102
    struct wined3d_resource *wined3d_resource;
1103
    struct wined3d_resource_desc desc;
1104
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1105 1106

    TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, pSurface, pRect, color);
1107

1108 1109
    wined3d_mutex_lock();

1110
    wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
1111
    wined3d_resource_get_desc(wined3d_resource, &desc);
1112

1113 1114
    /* This method is only allowed with surfaces that are render targets, or
     * offscreen plain surfaces in D3DPOOL_DEFAULT. */
1115
    if (!(desc.usage & WINED3DUSAGE_RENDERTARGET) && desc.pool != WINED3D_POOL_DEFAULT)
1116
    {
1117
        wined3d_mutex_unlock();
1118 1119 1120 1121 1122
        WARN("Surface is not a render target, or not a stand-alone D3DPOOL_DEFAULT surface\n");
        return D3DERR_INVALIDCALL;
    }

    /* Colorfill can only be used on rendertarget surfaces, or offscreen plain surfaces in D3DPOOL_DEFAULT */
1123
    hr = wined3d_device_color_fill(This->wined3d_device, surface->wined3d_surface, pRect, &c);
1124 1125 1126

    wined3d_mutex_unlock();

1127
    return hr;
1128 1129
}

1130 1131
static HRESULT  WINAPI  IDirect3DDevice9Impl_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface,
        UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface,
1132
        HANDLE *shared_handle)
1133 1134
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1135
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1136 1137

    TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
1138 1139 1140 1141
            iface, Width, Height, Format, Pool, ppSurface, shared_handle);

    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
Henri Verbeet's avatar
Henri Verbeet committed
1142

1143 1144
    if (Pool == D3DPOOL_MANAGED)
    {
1145 1146
        FIXME("Attempting to create a managed offscreen plain surface\n");
        return D3DERR_INVALIDCALL;
1147
    }
1148
        /*
1149 1150 1151 1152
        'Off-screen plain surfaces are always lockable, regardless of their pool types.'
        but then...
        D3DPOOL_DEFAULT is the appropriate pool for use with the IDirect3DDevice9::StretchRect and IDirect3DDevice9::ColorFill.
        Why, their always lockable?
1153
        should I change the usage to dynamic?
1154
        */
1155 1156
    hr = IDirect3DDevice9Impl_CreateSurface(This, Width, Height, Format, TRUE /* Lockable */,
            FALSE /* Discard */, 0 /* Level */, ppSurface, 0 /* Usage (undefined/none) */,
1157
            Pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
Henri Verbeet's avatar
Henri Verbeet committed
1158

1159
    return hr;
1160 1161 1162
}

/* TODO: move to wineD3D */
1163 1164 1165 1166
static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(IDirect3DDevice9Ex *iface,
        DWORD RenderTargetIndex, IDirect3DSurface9 *pRenderTarget)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1167
    IDirect3DSurface9Impl *pSurface = unsafe_impl_from_IDirect3DSurface9(pRenderTarget);
1168
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1169 1170

    TRACE("iface %p, idx %u, surface %p.\n", iface, RenderTargetIndex, pRenderTarget);
1171

1172 1173 1174 1175 1176 1177
    if (RenderTargetIndex >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
    {
        WARN("Invalid index %u specified.\n", RenderTargetIndex);
        return D3DERR_INVALIDCALL;
    }

1178
    wined3d_mutex_lock();
1179
    hr = wined3d_device_set_render_target(This->wined3d_device, RenderTargetIndex,
1180
            pSurface ? pSurface->wined3d_surface : NULL, TRUE);
1181 1182
    wined3d_mutex_unlock();

1183
    return hr;
1184
}
1185

1186 1187 1188
static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(IDirect3DDevice9Ex *iface,
        DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget)
{
1189
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1190
    struct wined3d_surface *wined3d_surface;
1191
    HRESULT hr;
1192

Henri Verbeet's avatar
Henri Verbeet committed
1193
    TRACE("iface %p, idx %u, surface %p.\n", iface, RenderTargetIndex, ppRenderTarget);
1194 1195 1196

    if (ppRenderTarget == NULL) {
        return D3DERR_INVALIDCALL;
1197
    }
1198

1199 1200 1201 1202 1203 1204
    if (RenderTargetIndex >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
    {
        WARN("Invalid index %u specified.\n", RenderTargetIndex);
        return D3DERR_INVALIDCALL;
    }

1205
    wined3d_mutex_lock();
1206
    hr = wined3d_device_get_render_target(This->wined3d_device, RenderTargetIndex, &wined3d_surface);
1207
    if (SUCCEEDED(hr))
1208
    {
1209
        *ppRenderTarget = wined3d_surface_get_parent(wined3d_surface);
1210
        IDirect3DSurface9_AddRef(*ppRenderTarget);
1211
        wined3d_surface_decref(wined3d_surface);
1212
    }
1213 1214 1215 1216 1217 1218
    else
    {
        if (hr != WINED3DERR_NOTFOUND)
            WARN("Failed to get render target %u, hr %#x.\n", RenderTargetIndex, hr);
        *ppRenderTarget = NULL;
    }
1219
    wined3d_mutex_unlock();
1220

1221
    return hr;
1222 1223
}

1224 1225 1226 1227
static HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(IDirect3DDevice9Ex *iface,
        IDirect3DSurface9 *pZStencilSurface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1228
    IDirect3DSurface9Impl *pSurface = unsafe_impl_from_IDirect3DSurface9(pZStencilSurface);
1229
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1230 1231

    TRACE("iface %p, depth_stencil %p.\n", iface, pZStencilSurface);
1232

1233
    wined3d_mutex_lock();
1234
    hr = wined3d_device_set_depth_stencil(This->wined3d_device, pSurface ? pSurface->wined3d_surface : NULL);
1235 1236
    wined3d_mutex_unlock();

1237
    return hr;
1238 1239
}

1240 1241 1242
static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(IDirect3DDevice9Ex *iface,
        IDirect3DSurface9 **ppZStencilSurface)
{
1243
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1244
    struct wined3d_surface *wined3d_surface;
1245
    HRESULT hr;
1246

Henri Verbeet's avatar
Henri Verbeet committed
1247 1248
    TRACE("iface %p, depth_stencil %p.\n", iface, ppZStencilSurface);

1249 1250
    if(ppZStencilSurface == NULL){
        return D3DERR_INVALIDCALL;
1251
    }
1252

1253
    wined3d_mutex_lock();
1254
    hr = wined3d_device_get_depth_stencil(This->wined3d_device, &wined3d_surface);
1255 1256
    if (SUCCEEDED(hr))
    {
1257
        *ppZStencilSurface = wined3d_surface_get_parent(wined3d_surface);
1258
        IDirect3DSurface9_AddRef(*ppZStencilSurface);
1259
        wined3d_surface_decref(wined3d_surface);
1260 1261 1262
    }
    else
    {
1263 1264
        if (hr != WINED3DERR_NOTFOUND)
                WARN("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr);
1265
        *ppZStencilSurface = NULL;
1266
    }
1267 1268
    wined3d_mutex_unlock();

1269
    return hr;
1270 1271
}

1272 1273 1274
static HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1275
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1276 1277

    TRACE("iface %p.\n", iface);
1278

1279
    wined3d_mutex_lock();
1280
    hr = wined3d_device_begin_scene(This->wined3d_device);
1281
    if (SUCCEEDED(hr)) This->in_scene = TRUE;
1282 1283
    wined3d_mutex_unlock();

1284
    return hr;
1285 1286
}

1287 1288 1289
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_EndScene(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1290
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1291 1292

    TRACE("iface %p.\n", iface);
1293

1294
    wined3d_mutex_lock();
1295
    hr = wined3d_device_end_scene(This->wined3d_device);
1296
    if (SUCCEEDED(hr)) This->in_scene = FALSE;
1297 1298
    wined3d_mutex_unlock();

1299
    return hr;
1300 1301
}

1302 1303
static HRESULT WINAPI IDirect3DDevice9Impl_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count,
        const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
1304
{
1305 1306 1307 1308 1309 1310 1311
    const struct wined3d_color c =
    {
        ((color >> 16) & 0xff) / 255.0f,
        ((color >>  8) & 0xff) / 255.0f,
        (color & 0xff) / 255.0f,
        ((color >> 24) & 0xff) / 255.0f,
    };
1312
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1313
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1314 1315

    TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1316
            iface, rect_count, rects, flags, color, z, stencil);
1317

1318
    wined3d_mutex_lock();
1319
    hr = wined3d_device_clear(This->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
1320 1321
    wined3d_mutex_unlock();

1322
    return hr;
1323 1324
}

1325 1326 1327 1328
static HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(IDirect3DDevice9Ex *iface,
        D3DTRANSFORMSTATETYPE State, const D3DMATRIX *lpMatrix)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1329
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1330 1331

    TRACE("iface %p, state %#x, matrix %p.\n", iface, State, lpMatrix);
1332

1333
    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1334
    wined3d_mutex_lock();
1335
    hr = wined3d_device_set_transform(This->wined3d_device, State, (const struct wined3d_matrix *)lpMatrix);
1336 1337
    wined3d_mutex_unlock();

1338
    return hr;
1339 1340
}

1341 1342 1343 1344
static HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(IDirect3DDevice9Ex *iface,
        D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
Henri Verbeet's avatar
Henri Verbeet committed
1345 1346
    HRESULT hr;

Henri Verbeet's avatar
Henri Verbeet committed
1347
    TRACE("iface %p, state %#x, matrix %p.\n", iface, State, pMatrix);
1348

1349
    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1350
    wined3d_mutex_lock();
1351
    hr = wined3d_device_get_transform(This->wined3d_device, State, (struct wined3d_matrix *)pMatrix);
1352
    wined3d_mutex_unlock();
Henri Verbeet's avatar
Henri Verbeet committed
1353 1354

    return hr;
1355 1356
}

1357 1358 1359 1360
static HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(IDirect3DDevice9Ex *iface,
        D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1361
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1362 1363

    TRACE("iface %p, state %#x, matrix %p.\n", iface, State, pMatrix);
1364

1365
    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1366
    wined3d_mutex_lock();
1367
    hr = wined3d_device_multiply_transform(This->wined3d_device, State, (const struct wined3d_matrix *)pMatrix);
1368 1369
    wined3d_mutex_unlock();

1370
    return hr;
1371 1372
}

1373 1374 1375 1376
static HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(IDirect3DDevice9Ex *iface,
        const D3DVIEWPORT9 *pViewport)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1377
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1378 1379

    TRACE("iface %p, viewport %p.\n", iface, pViewport);
1380

1381
    /* Note: D3DVIEWPORT9 is compatible with struct wined3d_viewport. */
1382
    wined3d_mutex_lock();
1383
    hr = wined3d_device_set_viewport(This->wined3d_device, (const struct wined3d_viewport *)pViewport);
1384 1385
    wined3d_mutex_unlock();

1386
    return hr;
1387 1388
}

1389 1390 1391 1392
static HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(IDirect3DDevice9Ex *iface,
        D3DVIEWPORT9 *pViewport)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1393
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1394 1395

    TRACE("iface %p, viewport %p.\n", iface, pViewport);
1396

1397
    /* Note: D3DVIEWPORT9 is compatible with struct wined3d_viewport. */
1398
    wined3d_mutex_lock();
1399
    hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)pViewport);
1400 1401
    wined3d_mutex_unlock();

1402
    return hr;
1403 1404
}

1405 1406 1407 1408
static HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(IDirect3DDevice9Ex *iface,
        const D3DMATERIAL9 *pMaterial)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1409
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1410 1411

    TRACE("iface %p, material %p.\n", iface, pMaterial);
1412

1413
    /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
1414
    wined3d_mutex_lock();
1415
    hr = wined3d_device_set_material(This->wined3d_device, (const struct wined3d_material *)pMaterial);
1416 1417
    wined3d_mutex_unlock();

1418
    return hr;
1419 1420
}

1421 1422 1423 1424
static HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(IDirect3DDevice9Ex *iface,
        D3DMATERIAL9 *pMaterial)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1425
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1426 1427

    TRACE("iface %p, material %p.\n", iface, pMaterial);
1428

1429
    /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
1430
    wined3d_mutex_lock();
1431
    hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)pMaterial);
1432 1433
    wined3d_mutex_unlock();

1434
    return hr;
1435 1436
}

1437 1438 1439 1440
static HRESULT WINAPI IDirect3DDevice9Impl_SetLight(IDirect3DDevice9Ex *iface, DWORD Index,
        const D3DLIGHT9 *pLight)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1441
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1442 1443

    TRACE("iface %p, index %u, light %p.\n", iface, Index, pLight);
1444

1445
    /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
1446
    wined3d_mutex_lock();
1447
    hr = wined3d_device_set_light(This->wined3d_device, Index, (const struct wined3d_light *)pLight);
1448 1449
    wined3d_mutex_unlock();

1450
    return hr;
1451 1452
}

1453 1454 1455 1456
static HRESULT WINAPI IDirect3DDevice9Impl_GetLight(IDirect3DDevice9Ex *iface, DWORD Index,
        D3DLIGHT9 *pLight)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1457
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1458 1459

    TRACE("iface %p, index %u, light %p.\n", iface, Index, pLight);
1460

1461
    /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
1462
    wined3d_mutex_lock();
1463
    hr = wined3d_device_get_light(This->wined3d_device, Index, (struct wined3d_light *)pLight);
1464 1465
    wined3d_mutex_unlock();

1466
    return hr;
1467 1468
}

1469 1470 1471 1472
static HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(IDirect3DDevice9Ex *iface, DWORD Index,
        BOOL Enable)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1473
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1474 1475

    TRACE("iface %p, index %u, enable %#x.\n", iface, Index, Enable);
1476

1477
    wined3d_mutex_lock();
1478
    hr = wined3d_device_set_light_enable(This->wined3d_device, Index, Enable);
1479 1480
    wined3d_mutex_unlock();

1481
    return hr;
1482 1483
}

1484 1485 1486 1487
static HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD Index,
        BOOL *pEnable)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1488
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1489 1490

    TRACE("iface %p, index %u, enable %p.\n", iface, Index, pEnable);
1491

1492
    wined3d_mutex_lock();
1493
    hr = wined3d_device_get_light_enable(This->wined3d_device, Index, pEnable);
1494 1495
    wined3d_mutex_unlock();

1496
    return hr;
1497 1498
}

1499 1500 1501 1502
static HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD Index,
        const float *pPlane)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1503
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1504 1505

    TRACE("iface %p, index %u, plane %p.\n", iface, Index, pPlane);
1506

1507
    wined3d_mutex_lock();
1508
    hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, pPlane);
1509 1510
    wined3d_mutex_unlock();

1511
    return hr;
1512 1513
}

1514 1515 1516 1517
static HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD Index,
        float *pPlane)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1518
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1519 1520

    TRACE("iface %p, index %u, plane %p.\n", iface, Index, pPlane);
1521

1522
    wined3d_mutex_lock();
1523
    hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, pPlane);
1524 1525
    wined3d_mutex_unlock();

1526
    return hr;
1527 1528
}

1529 1530 1531 1532
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_SetRenderState(IDirect3DDevice9Ex *iface,
        D3DRENDERSTATETYPE State, DWORD Value)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1533
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1534 1535

    TRACE("iface %p, state %#x, value %#x.\n", iface, State, Value);
1536

1537
    wined3d_mutex_lock();
1538
    hr = wined3d_device_set_render_state(This->wined3d_device, State, Value);
1539 1540
    wined3d_mutex_unlock();

1541
    return hr;
1542 1543
}

1544 1545 1546 1547
static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(IDirect3DDevice9Ex *iface,
        D3DRENDERSTATETYPE State, DWORD *pValue)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1548
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1549 1550

    TRACE("iface %p, state %#x, value %p.\n", iface, State, pValue);
1551

1552
    wined3d_mutex_lock();
1553
    hr = wined3d_device_get_render_state(This->wined3d_device, State, pValue);
1554 1555
    wined3d_mutex_unlock();

1556
    return hr;
1557 1558
}

1559 1560 1561
static HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(IDirect3DDevice9Ex *iface,
        D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock)
{
1562
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
    IDirect3DStateBlock9Impl *object;
    HRESULT hr;

    TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);

    if (type != D3DSBT_ALL && type != D3DSBT_PIXELSTATE && type != D3DSBT_VERTEXSTATE)
    {
        WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n");
        return D3DERR_INVALIDCALL;
    }

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate stateblock memory.\n");
        return E_OUTOFMEMORY;
    }

    hr = stateblock_init(object, This, type, NULL);
    if (FAILED(hr))
    {
        WARN("Failed to initialize stateblock, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created stateblock %p.\n", object);
1590
    *stateblock = &object->IDirect3DStateBlock9_iface;
1591 1592 1593 1594 1595 1596

    return D3D_OK;
}

static HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(IDirect3DDevice9Ex *iface)
{
1597
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1598 1599 1600 1601 1602
    HRESULT hr;

    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
1603
    hr = wined3d_device_begin_stateblock(This->wined3d_device);
1604 1605 1606 1607 1608
    wined3d_mutex_unlock();

    return hr;
}

1609 1610
static HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(IDirect3DDevice9Ex *iface,
        IDirect3DStateBlock9 **stateblock)
1611
{
1612
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1613
    struct wined3d_stateblock *wined3d_stateblock;
1614 1615 1616 1617 1618 1619
    IDirect3DStateBlock9Impl *object;
    HRESULT hr;

    TRACE("iface %p, stateblock %p.\n", iface, stateblock);

    wined3d_mutex_lock();
1620
    hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_stateblock);
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631
    wined3d_mutex_unlock();
    if (FAILED(hr))
    {
       WARN("IWineD3DDevice_EndStateBlock() failed, hr %#x.\n", hr);
       return hr;
    }

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate stateblock memory.\n");
1632
        wined3d_mutex_lock();
1633
        wined3d_stateblock_decref(wined3d_stateblock);
1634
        wined3d_mutex_unlock();
1635 1636 1637 1638 1639 1640 1641
        return E_OUTOFMEMORY;
    }

    hr = stateblock_init(object, This, 0, wined3d_stateblock);
    if (FAILED(hr))
    {
        WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1642
        wined3d_mutex_lock();
1643
        wined3d_stateblock_decref(wined3d_stateblock);
1644
        wined3d_mutex_unlock();
1645 1646 1647 1648 1649
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created stateblock %p.\n", object);
1650
    *stateblock = &object->IDirect3DStateBlock9_iface;
1651 1652 1653 1654

    return D3D_OK;
}

1655 1656 1657 1658
static HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(IDirect3DDevice9Ex *iface,
        const D3DCLIPSTATUS9 *pClipStatus)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1659
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1660 1661

    TRACE("iface %p, clip_status %p.\n", iface, pClipStatus);
1662

1663
    wined3d_mutex_lock();
1664
    hr = wined3d_device_set_clip_status(This->wined3d_device, (const struct wined3d_clip_status *)pClipStatus);
1665 1666
    wined3d_mutex_unlock();

1667
    return hr;
1668 1669
}

1670 1671 1672 1673
static HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(IDirect3DDevice9Ex *iface,
        D3DCLIPSTATUS9 *pClipStatus)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1674
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1675 1676

    TRACE("iface %p, clip_status %p.\n", iface, pClipStatus);
1677

1678
    wined3d_mutex_lock();
1679
    hr = wined3d_device_get_clip_status(This->wined3d_device, (struct wined3d_clip_status *)pClipStatus);
1680 1681
    wined3d_mutex_unlock();

1682
    return hr;
1683 1684
}

1685 1686
static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(IDirect3DDevice9Ex *iface, DWORD Stage,
        IDirect3DBaseTexture9 **ppTexture)
1687
{
1688
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1689
    struct wined3d_texture *wined3d_texture = NULL;
1690
    HRESULT hr;
1691

Henri Verbeet's avatar
Henri Verbeet committed
1692
    TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, ppTexture);
1693 1694 1695 1696 1697

    if(ppTexture == NULL){
        return D3DERR_INVALIDCALL;
    }

1698
    wined3d_mutex_lock();
1699
    hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
1700
    if (SUCCEEDED(hr) && wined3d_texture)
1701
    {
1702 1703 1704
        *ppTexture = wined3d_texture_get_parent(wined3d_texture);
        IDirect3DBaseTexture9_AddRef(*ppTexture);
        wined3d_texture_decref(wined3d_texture);
1705 1706 1707 1708 1709
    }
    else
    {
        if (FAILED(hr))
        {
1710
            WARN("Call to get texture (%u) failed (%p).\n", Stage, wined3d_texture);
1711
        }
1712
        *ppTexture = NULL;
1713
    }
1714
    wined3d_mutex_unlock();
1715

1716
    return hr;
1717 1718
}

1719 1720
static HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage,
        IDirect3DBaseTexture9 *texture)
1721
{
1722
    IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
1723
    struct d3d9_texture *texture_impl;
1724
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1725

1726
    TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
1727

1728 1729
    texture_impl = unsafe_impl_from_IDirect3DBaseTexture9(texture);

1730
    wined3d_mutex_lock();
1731
    hr = wined3d_device_set_texture(device->wined3d_device, stage,
1732
            texture_impl ? texture_impl->wined3d_texture : NULL);
1733 1734
    wined3d_mutex_unlock();

1735
    return hr;
1736 1737
}

1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772
static const enum wined3d_texture_stage_state tss_lookup[] =
{
    WINED3D_TSS_INVALID,                    /*  0, unused */
    WINED3D_TSS_COLOR_OP,                   /*  1, D3DTSS_COLOROP */
    WINED3D_TSS_COLOR_ARG1,                 /*  2, D3DTSS_COLORARG1 */
    WINED3D_TSS_COLOR_ARG2,                 /*  3, D3DTSS_COLORARG2 */
    WINED3D_TSS_ALPHA_OP,                   /*  4, D3DTSS_ALPHAOP */
    WINED3D_TSS_ALPHA_ARG1,                 /*  5, D3DTSS_ALPHAARG1 */
    WINED3D_TSS_ALPHA_ARG2,                 /*  6, D3DTSS_ALPHAARG2 */
    WINED3D_TSS_BUMPENV_MAT00,              /*  7, D3DTSS_BUMPENVMAT00 */
    WINED3D_TSS_BUMPENV_MAT01,              /*  8, D3DTSS_BUMPENVMAT01 */
    WINED3D_TSS_BUMPENV_MAT10,              /*  9, D3DTSS_BUMPENVMAT10 */
    WINED3D_TSS_BUMPENV_MAT11,              /* 10, D3DTSS_BUMPENVMAT11 */
    WINED3D_TSS_TEXCOORD_INDEX,             /* 11, D3DTSS_TEXCOORDINDEX */
    WINED3D_TSS_INVALID,                    /* 12, unused */
    WINED3D_TSS_INVALID,                    /* 13, unused */
    WINED3D_TSS_INVALID,                    /* 14, unused */
    WINED3D_TSS_INVALID,                    /* 15, unused */
    WINED3D_TSS_INVALID,                    /* 16, unused */
    WINED3D_TSS_INVALID,                    /* 17, unused */
    WINED3D_TSS_INVALID,                    /* 18, unused */
    WINED3D_TSS_INVALID,                    /* 19, unused */
    WINED3D_TSS_INVALID,                    /* 20, unused */
    WINED3D_TSS_INVALID,                    /* 21, unused */
    WINED3D_TSS_BUMPENV_LSCALE,             /* 22, D3DTSS_BUMPENVLSCALE */
    WINED3D_TSS_BUMPENV_LOFFSET,            /* 23, D3DTSS_BUMPENVLOFFSET */
    WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,    /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
    WINED3D_TSS_INVALID,                    /* 25, unused */
    WINED3D_TSS_COLOR_ARG0,                 /* 26, D3DTSS_COLORARG0 */
    WINED3D_TSS_ALPHA_ARG0,                 /* 27, D3DTSS_ALPHAARG0 */
    WINED3D_TSS_RESULT_ARG,                 /* 28, D3DTSS_RESULTARG */
    WINED3D_TSS_INVALID,                    /* 29, unused */
    WINED3D_TSS_INVALID,                    /* 30, unused */
    WINED3D_TSS_INVALID,                    /* 31, unused */
    WINED3D_TSS_CONSTANT,                   /* 32, D3DTSS_CONSTANT */
1773 1774
};

1775 1776
static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(IDirect3DDevice9Ex *iface,
        DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue)
1777
{
1778
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1779
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1780 1781

    TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, Stage, Type, pValue);
1782

1783 1784 1785 1786 1787 1788
    if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
    {
        WARN("Invalid Type %#x passed.\n", Type);
        return D3D_OK;
    }

1789
    wined3d_mutex_lock();
1790
    hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, tss_lookup[Type], pValue);
1791 1792
    wined3d_mutex_unlock();

1793
    return hr;
1794 1795
}

1796 1797
static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(IDirect3DDevice9Ex *iface,
        DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
1798
{
1799
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1800
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1801 1802

    TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, Stage, Type, Value);
1803

1804 1805 1806 1807 1808 1809
    if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
    {
        WARN("Invalid Type %#x passed.\n", Type);
        return D3D_OK;
    }

1810
    wined3d_mutex_lock();
1811
    hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, tss_lookup[Type], Value);
1812 1813
    wined3d_mutex_unlock();

1814
    return hr;
1815 1816
}

1817 1818 1819
static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(IDirect3DDevice9Ex *iface, DWORD Sampler,
        D3DSAMPLERSTATETYPE Type, DWORD *pValue)
{
1820
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1821
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1822 1823

    TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, Sampler, Type, pValue);
1824

1825
    wined3d_mutex_lock();
1826
    hr = wined3d_device_get_sampler_state(This->wined3d_device, Sampler, Type, pValue);
1827 1828
    wined3d_mutex_unlock();

1829
    return hr;
1830 1831
}

1832 1833 1834 1835
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_SetSamplerState(IDirect3DDevice9Ex *iface,
        DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1836
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1837 1838

    TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, Sampler, Type, Value);
1839

1840
    wined3d_mutex_lock();
1841
    hr = wined3d_device_set_sampler_state(This->wined3d_device, Sampler, Type, Value);
1842 1843
    wined3d_mutex_unlock();

1844
    return hr;
1845 1846
}

1847 1848 1849 1850
static HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(IDirect3DDevice9Ex *iface,
        DWORD *pNumPasses)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1851
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1852 1853

    TRACE("iface %p, pass_count %p.\n", iface, pNumPasses);
1854

1855
    wined3d_mutex_lock();
1856
    hr = wined3d_device_validate_device(This->wined3d_device, pNumPasses);
1857 1858
    wined3d_mutex_unlock();

1859
    return hr;
1860 1861
}

1862 1863
static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(IDirect3DDevice9Ex *iface,
        UINT PaletteNumber, const PALETTEENTRY *pEntries)
1864
{
1865
    FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, PaletteNumber, pEntries);
Henri Verbeet's avatar
Henri Verbeet committed
1866

1867
    return D3DERR_INVALIDCALL;
1868 1869
}

1870 1871 1872
static HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(IDirect3DDevice9Ex *iface,
        UINT PaletteNumber, PALETTEENTRY *pEntries)
{
1873
    FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, PaletteNumber, pEntries);
Henri Verbeet's avatar
Henri Verbeet committed
1874

1875
    return D3DERR_INVALIDCALL;
1876 1877
}

1878 1879 1880
static HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface,
        UINT PaletteNumber)
{
1881
    FIXME("iface %p, palette_idx %u unimplemented.\n", iface, PaletteNumber);
Henri Verbeet's avatar
Henri Verbeet committed
1882

1883
    return D3DERR_INVALIDCALL;
1884 1885
}

1886 1887 1888
static HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface,
        UINT *PaletteNumber)
{
1889
    FIXME("iface %p, palette_idx %p.\n", iface, PaletteNumber);
Henri Verbeet's avatar
Henri Verbeet committed
1890

1891
    return D3DERR_INVALIDCALL;
1892 1893
}

1894 1895 1896 1897
static HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(IDirect3DDevice9Ex *iface,
        const RECT *pRect)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1898
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1899 1900

    TRACE("iface %p, rect %p.\n", iface, pRect);
1901

1902
    wined3d_mutex_lock();
1903
    hr = wined3d_device_set_scissor_rect(This->wined3d_device, pRect);
1904 1905
    wined3d_mutex_unlock();

1906
    return hr;
1907 1908
}

1909 1910 1911
static HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *pRect)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1912
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1913 1914

    TRACE("iface %p, rect %p.\n", iface, pRect);
1915

1916
    wined3d_mutex_lock();
1917
    hr = wined3d_device_get_scissor_rect(This->wined3d_device, pRect);
1918 1919
    wined3d_mutex_unlock();

1920
    return hr;
1921 1922
}

1923 1924 1925 1926
static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface,
        BOOL bSoftware)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1927
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1928 1929

    TRACE("iface %p, software %#x.\n", iface, bSoftware);
1930

1931
    wined3d_mutex_lock();
1932
    hr = wined3d_device_set_software_vertex_processing(This->wined3d_device, bSoftware);
1933 1934
    wined3d_mutex_unlock();

1935
    return hr;
1936 1937
}

1938 1939 1940
static BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1941
    BOOL ret;
Henri Verbeet's avatar
Henri Verbeet committed
1942 1943

    TRACE("iface %p.\n", iface);
1944

1945
    wined3d_mutex_lock();
1946
    ret = wined3d_device_get_software_vertex_processing(This->wined3d_device);
1947 1948
    wined3d_mutex_unlock();

1949
    return ret;
1950 1951
}

1952 1953 1954
static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(IDirect3DDevice9Ex *iface, float nSegments)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1955
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1956 1957

    TRACE("iface %p, segment_count %.8e.\n", iface, nSegments);
1958

1959
    wined3d_mutex_lock();
1960
    hr = wined3d_device_set_npatch_mode(This->wined3d_device, nSegments);
1961 1962
    wined3d_mutex_unlock();

1963
    return hr;
1964 1965
}

1966 1967 1968
static float WINAPI IDirect3DDevice9Impl_GetNPatchMode(IDirect3DDevice9Ex *iface)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1969
    float ret;
Henri Verbeet's avatar
Henri Verbeet committed
1970 1971

    TRACE("iface %p.\n", iface);
1972

1973
    wined3d_mutex_lock();
1974
    ret = wined3d_device_get_npatch_mode(This->wined3d_device);
1975 1976
    wined3d_mutex_unlock();

1977
    return ret;
1978 1979
}

1980 1981
static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(IDirect3DDevice9Ex *iface,
        D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount)
1982
{
1983
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1984
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
1985 1986 1987

    TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
            iface, PrimitiveType, StartVertex, PrimitiveCount);
1988

1989
    wined3d_mutex_lock();
1990 1991
    wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
    hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex,
1992
            vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount));
1993 1994
    wined3d_mutex_unlock();

1995
    return hr;
1996 1997
}

1998 1999 2000 2001 2002
static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface,
        D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices,
        UINT startIndex, UINT primCount)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2003
    HRESULT hr;
2004

Henri Verbeet's avatar
Henri Verbeet committed
2005 2006 2007 2008 2009
    TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u,\n"
            "vertex_count %u, start_idx %u, primitive_count %u.\n",
            iface, PrimitiveType, BaseVertexIndex, MinVertexIndex,
            NumVertices, startIndex, primCount);

2010
    wined3d_mutex_lock();
2011 2012 2013
    wined3d_device_set_base_vertex_index(This->wined3d_device, BaseVertexIndex);
    wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
    hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, startIndex,
2014
            vertex_count_from_primitive_count(PrimitiveType, primCount));
2015 2016
    wined3d_mutex_unlock();

2017
    return hr;
2018 2019
}

2020 2021 2022
static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
        D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData,
        UINT VertexStreamZeroStride)
2023
{
2024
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2025
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2026 2027 2028

    TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
            iface, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
2029

2030
    wined3d_mutex_lock();
2031 2032
    wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
    hr = wined3d_device_draw_primitive_up(This->wined3d_device,
2033 2034
            vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount),
            pVertexStreamZeroData, VertexStreamZeroStride);
2035 2036
    wined3d_mutex_unlock();

2037
    return hr;
2038 2039
}

2040 2041 2042 2043 2044 2045
static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface,
        D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices,
        UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat,
        const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2046
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2047 2048 2049 2050 2051

    TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, index_count %u, primitive_count %u,\n"
            "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
            iface, PrimitiveType, MinVertexIndex, NumVertexIndices, PrimitiveCount,
            pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
2052

2053
    wined3d_mutex_lock();
2054 2055
    wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
    hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device,
2056
            vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pIndexData,
2057
            wined3dformat_from_d3dformat(IndexDataFormat), pVertexStreamZeroData, VertexStreamZeroStride);
2058 2059
    wined3d_mutex_unlock();

2060
    return hr;
2061 2062
}

2063 2064 2065 2066 2067
static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(IDirect3DDevice9Ex *iface,
        UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9 *pDestBuffer,
        IDirect3DVertexDeclaration9 *pVertexDecl, DWORD Flags)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2068
    IDirect3DVertexBuffer9Impl *dest = unsafe_impl_from_IDirect3DVertexBuffer9(pDestBuffer);
2069
    IDirect3DVertexDeclaration9Impl *Decl = unsafe_impl_from_IDirect3DVertexDeclaration9(pVertexDecl);
2070
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2071 2072 2073

    TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n",
            iface, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
2074

2075
    wined3d_mutex_lock();
2076 2077
    hr = wined3d_device_process_vertices(This->wined3d_device, SrcStartIndex, DestIndex, VertexCount,
            dest->wineD3DVertexBuffer, Decl ? Decl->wineD3DVertexDeclaration : NULL, Flags, dest->fvf);
2078 2079
    wined3d_mutex_unlock();

2080
    return hr;
2081 2082
}

2083 2084 2085
static HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(IDirect3DDevice9Ex *iface,
        const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration)
{
2086
    IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097
    IDirect3DVertexDeclaration9Impl *object;
    HRESULT hr;

    TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration);

    if (!declaration)
    {
        WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n");
        return D3DERR_INVALIDCALL;
    }

2098
    if (SUCCEEDED(hr = d3d9_vertex_declaration_create(device, elements, &object)))
2099
        *declaration = &object->IDirect3DVertexDeclaration9_iface;
2100

2101
    return hr;
2102 2103
}

2104 2105 2106
static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(IDirect3DDevice9Ex *iface,
        IDirect3DVertexDeclaration9 *declaration)
{
2107
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2108
    IDirect3DVertexDeclaration9Impl *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration);
2109 2110 2111 2112 2113
    HRESULT hr;

    TRACE("iface %p, declaration %p.\n", iface, declaration);

    wined3d_mutex_lock();
2114
    hr = wined3d_device_set_vertex_declaration(This->wined3d_device,
2115
            decl_impl ? decl_impl->wineD3DVertexDeclaration : NULL);
2116 2117 2118 2119 2120 2121 2122 2123
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(IDirect3DDevice9Ex *iface,
        IDirect3DVertexDeclaration9 **declaration)
{
2124
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2125
    struct wined3d_vertex_declaration *wined3d_declaration = NULL;
2126 2127 2128 2129 2130 2131 2132
    HRESULT hr;

    TRACE("iface %p, declaration %p.\n", iface, declaration);

    if (!declaration) return D3DERR_INVALIDCALL;

    wined3d_mutex_lock();
2133
    hr = wined3d_device_get_vertex_declaration(This->wined3d_device, &wined3d_declaration);
2134 2135
    if (SUCCEEDED(hr) && wined3d_declaration)
    {
2136
        *declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2137
        IDirect3DVertexDeclaration9_AddRef(*declaration);
2138
        wined3d_vertex_declaration_decref(wined3d_declaration);
2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
    }
    else
    {
        *declaration = NULL;
    }
    wined3d_mutex_unlock();

    TRACE("Returning %p.\n", *declaration);
    return hr;
}

2150 2151 2152 2153 2154 2155
static struct wined3d_vertex_declaration *device_get_fvf_declaration(IDirect3DDevice9Impl *device, DWORD fvf)
{
    struct wined3d_vertex_declaration *wined3d_declaration;
    struct fvf_declaration *fvf_decls = device->fvf_decls;
    IDirect3DVertexDeclaration9Impl *d3d9_declaration;
    D3DVERTEXELEMENT9 *elements;
2156
    int p, low, high; /* deliberately signed */
2157
    HRESULT hr;
2158 2159 2160 2161

    TRACE("Searching for declaration for fvf %08x... ", fvf);

    low = 0;
2162 2163 2164
    high = device->fvf_decl_count - 1;
    while (low <= high)
    {
2165 2166
        p = (low + high) >> 1;
        TRACE("%d ", p);
2167 2168 2169 2170 2171 2172 2173 2174

        if (fvf_decls[p].fvf == fvf)
        {
            TRACE("found %p.\n", fvf_decls[p].decl);
            return fvf_decls[p].decl;
        }

        if (fvf_decls[p].fvf < fvf)
2175
            low = p + 1;
2176
        else
2177 2178 2179 2180
            high = p - 1;
    }
    TRACE("not found. Creating and inserting at position %d.\n", low);

2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195
    if (FAILED(hr = vdecl_convert_fvf(fvf, &elements)))
        return NULL;

    hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
    HeapFree(GetProcessHeap(), 0, elements);
    if (FAILED(hr))
        return NULL;

    if (device->fvf_decl_size == device->fvf_decl_count)
    {
        UINT grow = max(device->fvf_decl_size / 2, 8);

        fvf_decls = HeapReAlloc(GetProcessHeap(), 0, fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow));
        if (!fvf_decls)
        {
2196
            IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface);
2197 2198
            return NULL;
        }
2199 2200
        device->fvf_decls = fvf_decls;
        device->fvf_decl_size += grow;
2201 2202
    }

2203 2204 2205
    d3d9_declaration->convFVF = fvf;
    wined3d_declaration = d3d9_declaration->wineD3DVertexDeclaration;
    wined3d_vertex_declaration_incref(wined3d_declaration);
2206
    IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface);
2207 2208 2209 2210 2211

    memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
    fvf_decls[low].decl = wined3d_declaration;
    fvf_decls[low].fvf = fvf;
    ++device->fvf_decl_count;
2212

2213
    TRACE("Returning %p. %u declatations in array.\n", wined3d_declaration, device->fvf_decl_count);
2214

2215
    return wined3d_declaration;
2216 2217
}

2218
static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
2219 2220
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2221
    struct wined3d_vertex_declaration *decl;
2222 2223
    HRESULT hr;

2224
    TRACE("iface %p, fvf %#x.\n", iface, fvf);
2225

2226
    if (!fvf)
2227
    {
2228
        WARN("%#x is not a valid FVF.\n", fvf);
2229 2230
        return D3D_OK;
    }
2231

2232
    wined3d_mutex_lock();
2233
    if (!(decl = device_get_fvf_declaration(This, fvf)))
2234
    {
2235 2236 2237
        wined3d_mutex_unlock();
        ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
        return D3DERR_DRIVERINTERNALERROR;
2238
    }
2239

2240 2241 2242 2243
    hr = wined3d_device_set_vertex_declaration(This->wined3d_device, decl);
    if (FAILED(hr))
        ERR("Failed to set vertex declaration.\n");
    wined3d_mutex_unlock();
2244

2245
    return hr;
2246 2247
}

2248
static HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(IDirect3DDevice9Ex *iface, DWORD *fvf)
Henri Verbeet's avatar
Henri Verbeet committed
2249
{
2250 2251 2252
    IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
    struct wined3d_vertex_declaration *wined3d_declaration;
    IDirect3DVertexDeclaration9Impl *d3d9_declaration;
2253
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2254

2255
    TRACE("iface %p, fvf %p.\n", iface, fvf);
2256

2257 2258
    wined3d_mutex_lock();
    if (FAILED(hr = wined3d_device_get_vertex_declaration(device->wined3d_device, &wined3d_declaration)))
2259
    {
2260 2261 2262
        wined3d_mutex_unlock();
        WARN("Failed to get vertex declaration, hr %#x.\n", hr);
        *fvf = 0;
2263 2264 2265
        return hr;
    }

2266
    if (wined3d_declaration)
2267
    {
2268 2269 2270
        d3d9_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
        *fvf = d3d9_declaration->convFVF;
        wined3d_vertex_declaration_decref(wined3d_declaration);
2271 2272 2273
    }
    else
    {
2274
        *fvf = 0;
2275
    }
2276
    wined3d_mutex_unlock();
2277

2278
    TRACE("Returning FVF %#x.\n", *fvf);
2279

2280
    return hr;
2281 2282
}

2283 2284 2285
static HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(IDirect3DDevice9Ex *iface,
        const DWORD *byte_code, IDirect3DVertexShader9 **shader)
{
2286
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
    IDirect3DVertexShader9Impl *object;
    HRESULT hr;

    TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate vertex shader memory.\n");
        return E_OUTOFMEMORY;
    }

    hr = vertexshader_init(object, This, byte_code);
    if (FAILED(hr))
    {
        WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created vertex shader %p.\n", object);
2308
    *shader = &object->IDirect3DVertexShader9_iface;
2309 2310 2311 2312

    return D3D_OK;
}

2313 2314 2315
static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(IDirect3DDevice9Ex *iface,
        IDirect3DVertexShader9 *shader)
{
2316
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2317
    IDirect3DVertexShader9Impl *shader_obj = unsafe_impl_from_IDirect3DVertexShader9(shader);
2318 2319 2320 2321 2322
    HRESULT hr;

    TRACE("iface %p, shader %p.\n", iface, shader);

    wined3d_mutex_lock();
2323
    hr =  wined3d_device_set_vertex_shader(This->wined3d_device,
2324
            shader_obj ? shader_obj->wined3d_shader : NULL);
2325 2326 2327 2328 2329 2330 2331 2332
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(IDirect3DDevice9Ex *iface,
        IDirect3DVertexShader9 **shader)
{
2333
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2334
    struct wined3d_shader *wined3d_shader;
2335 2336 2337 2338

    TRACE("iface %p, shader %p.\n", iface, shader);

    wined3d_mutex_lock();
2339
    wined3d_shader = wined3d_device_get_vertex_shader(This->wined3d_device);
2340
    if (wined3d_shader)
2341
    {
2342
        *shader = wined3d_shader_get_parent(wined3d_shader);
2343
        IDirect3DVertexShader9_AddRef(*shader);
2344
        wined3d_shader_decref(wined3d_shader);
2345 2346 2347
    }
    else
    {
2348
        *shader = NULL;
2349 2350 2351 2352 2353
    }
    wined3d_mutex_unlock();

    TRACE("Returning %p.\n", *shader);

2354
    return D3D_OK;
2355 2356 2357 2358 2359
}

static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
        UINT reg_idx, const float *data, UINT count)
{
2360
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
    {
        WARN("Trying to access %u constants, but d3d9 only supports %u\n",
             reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
        return D3DERR_INVALIDCALL;
    }

    wined3d_mutex_lock();
2373
    hr = wined3d_device_set_vs_consts_f(This->wined3d_device, reg_idx, data, count);
2374 2375 2376 2377 2378 2379 2380 2381
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
        UINT reg_idx, float *data, UINT count)
{
2382
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
    {
        WARN("Trying to access %u constants, but d3d9 only supports %u\n",
             reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
        return D3DERR_INVALIDCALL;
    }

    wined3d_mutex_lock();
2395
    hr = wined3d_device_get_vs_consts_f(This->wined3d_device, reg_idx, data, count);
2396 2397 2398 2399 2400 2401 2402 2403
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
        UINT reg_idx, const int *data, UINT count)
{
2404
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2405 2406 2407 2408 2409
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2410
    hr = wined3d_device_set_vs_consts_i(This->wined3d_device, reg_idx, data, count);
2411 2412 2413 2414 2415 2416 2417 2418
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
        UINT reg_idx, int *data, UINT count)
{
2419
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2420 2421 2422 2423 2424
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2425
    hr = wined3d_device_get_vs_consts_i(This->wined3d_device, reg_idx, data, count);
2426 2427 2428 2429 2430 2431 2432 2433
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
        UINT reg_idx, const BOOL *data, UINT count)
{
2434
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2435 2436 2437 2438 2439
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2440
    hr = wined3d_device_set_vs_consts_b(This->wined3d_device, reg_idx, data, count);
2441 2442 2443 2444 2445 2446 2447 2448
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
        UINT reg_idx, BOOL *data, UINT count)
{
2449
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2450 2451 2452 2453 2454
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2455
    hr = wined3d_device_get_vs_consts_b(This->wined3d_device, reg_idx, data, count);
2456 2457 2458 2459 2460
    wined3d_mutex_unlock();

    return hr;
}

2461 2462 2463 2464
static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(IDirect3DDevice9Ex *iface,
        UINT StreamNumber, IDirect3DVertexBuffer9 *pStreamData, UINT OffsetInBytes, UINT Stride)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2465
    IDirect3DVertexBuffer9Impl *streamdata = unsafe_impl_from_IDirect3DVertexBuffer9(pStreamData);
2466
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2467 2468 2469

    TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
            iface, StreamNumber, pStreamData, OffsetInBytes, Stride);
2470

2471
    wined3d_mutex_lock();
2472
    hr = wined3d_device_set_stream_source(This->wined3d_device, StreamNumber,
2473
            streamdata ? streamdata->wineD3DVertexBuffer : NULL,
2474
            OffsetInBytes, Stride);
2475 2476
    wined3d_mutex_unlock();

2477
    return hr;
2478 2479
}

2480
static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(IDirect3DDevice9Ex *iface,
2481
        UINT StreamNumber, IDirect3DVertexBuffer9 **pStream, UINT *OffsetInBytes, UINT *pStride)
2482
{
2483
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2484
    struct wined3d_buffer *retStream = NULL;
2485
    HRESULT hr;
2486

Henri Verbeet's avatar
Henri Verbeet committed
2487 2488
    TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
            iface, StreamNumber, pStream, OffsetInBytes, pStride);
2489 2490 2491 2492 2493

    if(pStream == NULL){
        return D3DERR_INVALIDCALL;
    }

2494
    wined3d_mutex_lock();
2495
    hr = wined3d_device_get_stream_source(This->wined3d_device, StreamNumber, &retStream, OffsetInBytes, pStride);
2496 2497
    if (SUCCEEDED(hr) && retStream)
    {
2498
        *pStream = wined3d_buffer_get_parent(retStream);
2499
        IDirect3DVertexBuffer9_AddRef(*pStream);
2500
        wined3d_buffer_decref(retStream);
2501 2502 2503 2504 2505
    }
    else
    {
        if (FAILED(hr))
        {
2506 2507
            FIXME("Call to GetStreamSource failed %p %p\n", OffsetInBytes, pStride);
        }
2508
        *pStream = NULL;
2509
    }
2510
    wined3d_mutex_unlock();
2511

2512
    return hr;
2513 2514
}

2515 2516
static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(IDirect3DDevice9Ex *iface,
        UINT StreamNumber, UINT Divider)
2517
{
2518
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2519
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2520 2521

    TRACE("iface %p, stream_idx %u, freq %u.\n", iface, StreamNumber, Divider);
2522

2523
    wined3d_mutex_lock();
2524
    hr = wined3d_device_set_stream_source_freq(This->wined3d_device, StreamNumber, Divider);
2525 2526
    wined3d_mutex_unlock();

2527
    return hr;
2528 2529
}

2530 2531 2532 2533
static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(IDirect3DDevice9Ex *iface,
        UINT StreamNumber, UINT *Divider)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2534
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2535 2536

    TRACE("iface %p, stream_idx %u, freq %p.\n", iface, StreamNumber, Divider);
2537

2538
    wined3d_mutex_lock();
2539
    hr = wined3d_device_get_stream_source_freq(This->wined3d_device, StreamNumber, Divider);
2540 2541
    wined3d_mutex_unlock();

2542
    return hr;
2543 2544
}

2545 2546 2547 2548
static HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(IDirect3DDevice9Ex *iface,
        IDirect3DIndexBuffer9 *pIndexData)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2549
    IDirect3DIndexBuffer9Impl *ib = unsafe_impl_from_IDirect3DIndexBuffer9(pIndexData);
2550
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2551 2552

    TRACE("iface %p, buffer %p.\n", iface, pIndexData);
2553

2554
    wined3d_mutex_lock();
2555
    hr = wined3d_device_set_index_buffer(This->wined3d_device,
2556 2557
            ib ? ib->wineD3DIndexBuffer : NULL,
            ib ? ib->format : WINED3DFMT_UNKNOWN);
2558 2559
    wined3d_mutex_unlock();

2560
    return hr;
2561 2562
}

2563 2564
static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(IDirect3DDevice9Ex *iface,
        IDirect3DIndexBuffer9 **ppIndexData)
2565
{
2566
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2567
    struct wined3d_buffer *retIndexData = NULL;
2568
    HRESULT hr;
2569

Henri Verbeet's avatar
Henri Verbeet committed
2570
    TRACE("iface %p, buffer %p.\n", iface, ppIndexData);
2571 2572 2573 2574 2575

    if(ppIndexData == NULL){
        return D3DERR_INVALIDCALL;
    }

2576
    wined3d_mutex_lock();
2577
    hr = wined3d_device_get_index_buffer(This->wined3d_device, &retIndexData);
2578 2579
    if (SUCCEEDED(hr) && retIndexData)
    {
2580
        *ppIndexData = wined3d_buffer_get_parent(retIndexData);
2581
        IDirect3DIndexBuffer9_AddRef(*ppIndexData);
2582
        wined3d_buffer_decref(retIndexData);
2583 2584 2585 2586
    }
    else
    {
        if (FAILED(hr)) FIXME("Call to GetIndices failed\n");
2587
        *ppIndexData = NULL;
2588
    }
2589 2590
    wined3d_mutex_unlock();

2591
    return hr;
2592 2593
}

2594 2595 2596
static HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(IDirect3DDevice9Ex *iface,
        const DWORD *byte_code, IDirect3DPixelShader9 **shader)
{
2597
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618
    IDirect3DPixelShader9Impl *object;
    HRESULT hr;

    TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        FIXME("Failed to allocate pixel shader memory.\n");
        return E_OUTOFMEMORY;
    }

    hr = pixelshader_init(object, This, byte_code);
    if (FAILED(hr))
    {
        WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created pixel shader %p.\n", object);
2619
    *shader = &object->IDirect3DPixelShader9_iface;
2620 2621 2622 2623

    return D3D_OK;
}

2624 2625 2626
static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(IDirect3DDevice9Ex *iface,
        IDirect3DPixelShader9 *shader)
{
2627
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2628
    IDirect3DPixelShader9Impl *shader_obj = unsafe_impl_from_IDirect3DPixelShader9(shader);
2629 2630 2631 2632 2633
    HRESULT hr;

    TRACE("iface %p, shader %p.\n", iface, shader);

    wined3d_mutex_lock();
2634
    hr = wined3d_device_set_pixel_shader(This->wined3d_device,
2635
            shader_obj ? shader_obj->wined3d_shader : NULL);
2636 2637 2638 2639 2640 2641 2642 2643
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(IDirect3DDevice9Ex *iface,
        IDirect3DPixelShader9 **shader)
{
2644
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2645
    struct wined3d_shader *wined3d_shader;
2646 2647 2648 2649 2650 2651

    TRACE("iface %p, shader %p.\n", iface, shader);

    if (!shader) return D3DERR_INVALIDCALL;

    wined3d_mutex_lock();
2652
    wined3d_shader = wined3d_device_get_pixel_shader(This->wined3d_device);
2653
    if (wined3d_shader)
2654
    {
2655
        *shader = wined3d_shader_get_parent(wined3d_shader);
2656
        IDirect3DPixelShader9_AddRef(*shader);
2657
        wined3d_shader_decref(wined3d_shader);
2658 2659 2660
    }
    else
    {
2661
        *shader = NULL;
2662 2663 2664 2665 2666
    }
    wined3d_mutex_unlock();

    TRACE("Returning %p.\n", *shader);

2667
    return D3D_OK;
2668 2669 2670 2671 2672
}

static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
        UINT reg_idx, const float *data, UINT count)
{
2673
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2674 2675 2676 2677 2678
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2679
    hr = wined3d_device_set_ps_consts_f(This->wined3d_device, reg_idx, data, count);
2680 2681 2682 2683 2684 2685 2686 2687
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
        UINT reg_idx, float *data, UINT count)
{
2688
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2689 2690 2691 2692 2693
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2694
    hr = wined3d_device_get_ps_consts_f(This->wined3d_device, reg_idx, data, count);
2695 2696 2697 2698 2699 2700 2701 2702
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
        UINT reg_idx, const int *data, UINT count)
{
2703
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2704 2705 2706 2707 2708
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2709
    hr = wined3d_device_set_ps_consts_i(This->wined3d_device, reg_idx, data, count);
2710 2711 2712 2713 2714 2715 2716 2717
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
        UINT reg_idx, int *data, UINT count)
{
2718
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2719 2720 2721 2722 2723
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2724
    hr = wined3d_device_get_ps_consts_i(This->wined3d_device, reg_idx, data, count);
2725 2726 2727 2728 2729 2730 2731 2732
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
        UINT reg_idx, const BOOL *data, UINT count)
{
2733
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2734 2735 2736 2737 2738
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2739
    hr = wined3d_device_set_ps_consts_b(This->wined3d_device, reg_idx, data, count);
2740 2741 2742 2743 2744 2745 2746 2747
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
        UINT reg_idx, BOOL *data, UINT count)
{
2748
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2749 2750 2751 2752 2753
    HRESULT hr;

    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);

    wined3d_mutex_lock();
2754
    hr = wined3d_device_get_ps_consts_b(This->wined3d_device, reg_idx, data, count);
2755 2756 2757 2758 2759
    wined3d_mutex_unlock();

    return hr;
}

2760 2761 2762 2763
static HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT Handle,
        const float *pNumSegs, const D3DRECTPATCH_INFO *pRectPatchInfo)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2764
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2765 2766 2767

    TRACE("iface %p, handle %#x, segment_count %p, patch_info %p.\n",
            iface, Handle, pNumSegs, pRectPatchInfo);
2768

2769
    wined3d_mutex_lock();
2770
    hr = wined3d_device_draw_rect_patch(This->wined3d_device, Handle,
2771
            pNumSegs, (const struct wined3d_rect_patch_info *)pRectPatchInfo);
2772 2773
    wined3d_mutex_unlock();

2774
    return hr;
2775
}
2776

2777 2778 2779 2780
static HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT Handle,
        const float *pNumSegs, const D3DTRIPATCH_INFO *pTriPatchInfo)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2781
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2782 2783 2784

    TRACE("iface %p, handle %#x, segment_count %p, patch_info %p.\n",
            iface, Handle, pNumSegs, pTriPatchInfo);
2785

2786
    wined3d_mutex_lock();
2787
    hr = wined3d_device_draw_tri_patch(This->wined3d_device, Handle,
2788
            pNumSegs, (const struct wined3d_tri_patch_info *)pTriPatchInfo);
2789 2790
    wined3d_mutex_unlock();

2791
    return hr;
2792 2793
}

2794 2795 2796
static HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(IDirect3DDevice9Ex *iface, UINT Handle)
{
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2797
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
2798 2799

    TRACE("iface %p, handle %#x.\n", iface, Handle);
2800

2801
    wined3d_mutex_lock();
2802
    hr = wined3d_device_delete_patch(This->wined3d_device, Handle);
2803 2804
    wined3d_mutex_unlock();

2805
    return hr;
2806 2807
}

2808 2809
static HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type,
        IDirect3DQuery9 **query)
2810
{
2811
    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832
    IDirect3DQuery9Impl *object;
    HRESULT hr;

    TRACE("iface %p, type %#x, query %p.\n", iface, type, query);

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate query memory.\n");
        return E_OUTOFMEMORY;
    }

    hr = query_init(object, This, type);
    if (FAILED(hr))
    {
        WARN("Failed to initialize query, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created query %p.\n", object);
2833 2834
    if (query) *query = &object->IDirect3DQuery9_iface;
    else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface);
2835 2836 2837 2838

    return D3D_OK;
}

Henri Verbeet's avatar
Henri Verbeet committed
2839 2840 2841 2842 2843 2844
static HRESULT WINAPI IDirect3DDevice9ExImpl_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface,
        UINT width, UINT height, float *rows, float *columns)
{
    FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n",
            iface, width, height, rows, columns);

2845
    return E_NOTIMPL;
2846 2847
}

2848 2849 2850 2851 2852 2853 2854 2855 2856
static HRESULT WINAPI IDirect3DDevice9ExImpl_ComposeRects(IDirect3DDevice9Ex *iface,
        IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs,
        UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
{
    FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u,\n"
            "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n",
            iface, src_surface, dst_surface, src_descs, rect_count,
            dst_descs, operation, offset_x, offset_y);

2857
    return E_NOTIMPL;
2858 2859
}

Henri Verbeet's avatar
Henri Verbeet committed
2860 2861 2862 2863 2864 2865 2866
static HRESULT WINAPI IDirect3DDevice9ExImpl_PresentEx(IDirect3DDevice9Ex *iface,
        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
        const RGNDATA *dirty_region, DWORD flags)
{
    FIXME("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p, flags %#x stub!\n",
            iface, src_rect, dst_rect, dst_window_override, dirty_region, flags);

2867
    return E_NOTIMPL;
2868 2869
}

Henri Verbeet's avatar
Henri Verbeet committed
2870 2871 2872 2873
static HRESULT WINAPI IDirect3DDevice9ExImpl_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
{
    FIXME("iface %p, priority %p stub!\n", iface, priority);

2874
    return E_NOTIMPL;
2875 2876
}

Henri Verbeet's avatar
Henri Verbeet committed
2877 2878 2879 2880
static HRESULT WINAPI IDirect3DDevice9ExImpl_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority)
{
    FIXME("iface %p, priority %d stub!\n", iface, priority);

2881
    return E_NOTIMPL;
2882 2883
}

Henri Verbeet's avatar
Henri Verbeet committed
2884 2885 2886 2887
static HRESULT WINAPI IDirect3DDevice9ExImpl_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx)
{
    FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx);

2888
    return E_NOTIMPL;
2889 2890
}

2891 2892 2893 2894 2895 2896
static HRESULT WINAPI IDirect3DDevice9ExImpl_CheckResourceResidency(IDirect3DDevice9Ex *iface,
        IDirect3DResource9 **resources, UINT32 resource_count)
{
    FIXME("iface %p, resources %p, resource_count %u stub!\n",
            iface, resources, resource_count);

2897
    return E_NOTIMPL;
2898 2899
}

Henri Verbeet's avatar
Henri Verbeet committed
2900 2901 2902 2903
static HRESULT WINAPI IDirect3DDevice9ExImpl_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency)
{
    FIXME("iface %p, max_latency %u stub!\n", iface, max_latency);

2904
    return E_NOTIMPL;
2905 2906
}

Henri Verbeet's avatar
Henri Verbeet committed
2907 2908 2909 2910 2911 2912
static HRESULT WINAPI IDirect3DDevice9ExImpl_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency)
{
    FIXME("iface %p, max_latency %p stub!\n", iface, max_latency);

    *max_latency = 2;

2913
    return E_NOTIMPL;
2914 2915
}

2916 2917
static HRESULT WINAPI IDirect3DDevice9ExImpl_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
{
2918
    static int i;
2919

2920 2921 2922 2923 2924
    TRACE("iface %p, dst_window %p stub!\n", iface, dst_window);

    if (!i++)
        FIXME("iface %p, dst_window %p stub!\n", iface, dst_window);

2925
    return D3D_OK;
2926 2927
}

Henri Verbeet's avatar
Henri Verbeet committed
2928 2929 2930 2931 2932 2933 2934 2935 2936
static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
        UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
        BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
{
    FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
            "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n",
            iface, width, height, format, multisample_type, multisample_quality,
            lockable, surface, shared_handle, usage);

2937 2938 2939
    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);

2940
    return E_NOTIMPL;
2941 2942
}

Henri Verbeet's avatar
Henri Verbeet committed
2943 2944 2945 2946 2947 2948 2949
static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateOffscreenPlainSurfaceEx(IDirect3DDevice9Ex *iface,
        UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
        HANDLE *shared_handle, DWORD usage)
{
    FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n",
            iface, width, height, format, pool, surface, shared_handle, usage);

2950
    return E_NOTIMPL;
2951 2952
}

2953 2954 2955 2956 2957 2958 2959 2960 2961
static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface,
        UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
        BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
{
    FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
            "discard %#x, surface %p, shared_handle %p, usage %#x stub!\n",
            iface, width, height, format, multisample_type, multisample_quality,
            discard, surface, shared_handle, usage);

2962 2963 2964
    if (shared_handle)
        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);

2965
    return E_NOTIMPL;
2966 2967
}

Henri Verbeet's avatar
Henri Verbeet committed
2968 2969 2970 2971 2972
static HRESULT WINAPI IDirect3DDevice9ExImpl_ResetEx(IDirect3DDevice9Ex *iface,
        D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
{
    FIXME("iface %p, present_parameters %p, mode %p stub!\n", iface, present_parameters, mode);

2973
    return E_NOTIMPL;
2974 2975
}

Henri Verbeet's avatar
Henri Verbeet committed
2976 2977 2978 2979 2980
static HRESULT  WINAPI  IDirect3DDevice9ExImpl_GetDisplayModeEx(IDirect3DDevice9Ex *iface,
        UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
{
    FIXME("iface %p, swapchain_idx %u, mode %p, rotation %p stub!\n", iface, swapchain_idx, mode, rotation);

2981
    return E_NOTIMPL;
2982 2983
}

2984
static const IDirect3DDevice9ExVtbl Direct3DDevice9_Vtbl =
2985
{
2986
    /* IUnknown */
2987 2988 2989
    IDirect3DDevice9Impl_QueryInterface,
    IDirect3DDevice9Impl_AddRef,
    IDirect3DDevice9Impl_Release,
2990
    /* IDirect3DDevice9 */
2991 2992
    IDirect3DDevice9Impl_TestCooperativeLevel,
    IDirect3DDevice9Impl_GetAvailableTextureMem,
2993
    IDirect3DDevice9Impl_EvictManagedResources,
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021
    IDirect3DDevice9Impl_GetDirect3D,
    IDirect3DDevice9Impl_GetDeviceCaps,
    IDirect3DDevice9Impl_GetDisplayMode,
    IDirect3DDevice9Impl_GetCreationParameters,
    IDirect3DDevice9Impl_SetCursorProperties,
    IDirect3DDevice9Impl_SetCursorPosition,
    IDirect3DDevice9Impl_ShowCursor,
    IDirect3DDevice9Impl_CreateAdditionalSwapChain,
    IDirect3DDevice9Impl_GetSwapChain,
    IDirect3DDevice9Impl_GetNumberOfSwapChains,
    IDirect3DDevice9Impl_Reset,
    IDirect3DDevice9Impl_Present,
    IDirect3DDevice9Impl_GetBackBuffer,
    IDirect3DDevice9Impl_GetRasterStatus,
    IDirect3DDevice9Impl_SetDialogBoxMode,
    IDirect3DDevice9Impl_SetGammaRamp,
    IDirect3DDevice9Impl_GetGammaRamp,
    IDirect3DDevice9Impl_CreateTexture,
    IDirect3DDevice9Impl_CreateVolumeTexture,
    IDirect3DDevice9Impl_CreateCubeTexture,
    IDirect3DDevice9Impl_CreateVertexBuffer,
    IDirect3DDevice9Impl_CreateIndexBuffer,
    IDirect3DDevice9Impl_CreateRenderTarget,
    IDirect3DDevice9Impl_CreateDepthStencilSurface,
    IDirect3DDevice9Impl_UpdateSurface,
    IDirect3DDevice9Impl_UpdateTexture,
    IDirect3DDevice9Impl_GetRenderTargetData,
    IDirect3DDevice9Impl_GetFrontBufferData,
3022
    IDirect3DDevice9Impl_StretchRect,
3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
    IDirect3DDevice9Impl_ColorFill,
    IDirect3DDevice9Impl_CreateOffscreenPlainSurface,
    IDirect3DDevice9Impl_SetRenderTarget,
    IDirect3DDevice9Impl_GetRenderTarget,
    IDirect3DDevice9Impl_SetDepthStencilSurface,
    IDirect3DDevice9Impl_GetDepthStencilSurface,
    IDirect3DDevice9Impl_BeginScene,
    IDirect3DDevice9Impl_EndScene,
    IDirect3DDevice9Impl_Clear,
    IDirect3DDevice9Impl_SetTransform,
    IDirect3DDevice9Impl_GetTransform,
    IDirect3DDevice9Impl_MultiplyTransform,
    IDirect3DDevice9Impl_SetViewport,
    IDirect3DDevice9Impl_GetViewport,
    IDirect3DDevice9Impl_SetMaterial,
    IDirect3DDevice9Impl_GetMaterial,
    IDirect3DDevice9Impl_SetLight,
    IDirect3DDevice9Impl_GetLight,
    IDirect3DDevice9Impl_LightEnable,
    IDirect3DDevice9Impl_GetLightEnable,
    IDirect3DDevice9Impl_SetClipPlane,
    IDirect3DDevice9Impl_GetClipPlane,
    IDirect3DDevice9Impl_SetRenderState,
    IDirect3DDevice9Impl_GetRenderState,
    IDirect3DDevice9Impl_CreateStateBlock,
    IDirect3DDevice9Impl_BeginStateBlock,
    IDirect3DDevice9Impl_EndStateBlock,
    IDirect3DDevice9Impl_SetClipStatus,
    IDirect3DDevice9Impl_GetClipStatus,
    IDirect3DDevice9Impl_GetTexture,
    IDirect3DDevice9Impl_SetTexture,
    IDirect3DDevice9Impl_GetTextureStageState,
    IDirect3DDevice9Impl_SetTextureStageState,
    IDirect3DDevice9Impl_GetSamplerState,
    IDirect3DDevice9Impl_SetSamplerState,
    IDirect3DDevice9Impl_ValidateDevice,
    IDirect3DDevice9Impl_SetPaletteEntries,
    IDirect3DDevice9Impl_GetPaletteEntries,
    IDirect3DDevice9Impl_SetCurrentTexturePalette,
    IDirect3DDevice9Impl_GetCurrentTexturePalette,
    IDirect3DDevice9Impl_SetScissorRect,
    IDirect3DDevice9Impl_GetScissorRect,
    IDirect3DDevice9Impl_SetSoftwareVertexProcessing,
    IDirect3DDevice9Impl_GetSoftwareVertexProcessing,
    IDirect3DDevice9Impl_SetNPatchMode,
    IDirect3DDevice9Impl_GetNPatchMode,
    IDirect3DDevice9Impl_DrawPrimitive,
    IDirect3DDevice9Impl_DrawIndexedPrimitive,
    IDirect3DDevice9Impl_DrawPrimitiveUP,
    IDirect3DDevice9Impl_DrawIndexedPrimitiveUP,
    IDirect3DDevice9Impl_ProcessVertices,
    IDirect3DDevice9Impl_CreateVertexDeclaration,
    IDirect3DDevice9Impl_SetVertexDeclaration,
    IDirect3DDevice9Impl_GetVertexDeclaration,
    IDirect3DDevice9Impl_SetFVF,
    IDirect3DDevice9Impl_GetFVF,
    IDirect3DDevice9Impl_CreateVertexShader,
    IDirect3DDevice9Impl_SetVertexShader,
    IDirect3DDevice9Impl_GetVertexShader,
    IDirect3DDevice9Impl_SetVertexShaderConstantF,
    IDirect3DDevice9Impl_GetVertexShaderConstantF,
    IDirect3DDevice9Impl_SetVertexShaderConstantI,
    IDirect3DDevice9Impl_GetVertexShaderConstantI,
    IDirect3DDevice9Impl_SetVertexShaderConstantB,
    IDirect3DDevice9Impl_GetVertexShaderConstantB,
    IDirect3DDevice9Impl_SetStreamSource,
    IDirect3DDevice9Impl_GetStreamSource,
    IDirect3DDevice9Impl_SetStreamSourceFreq,
    IDirect3DDevice9Impl_GetStreamSourceFreq,
    IDirect3DDevice9Impl_SetIndices,
    IDirect3DDevice9Impl_GetIndices,
    IDirect3DDevice9Impl_CreatePixelShader,
    IDirect3DDevice9Impl_SetPixelShader,
    IDirect3DDevice9Impl_GetPixelShader,
    IDirect3DDevice9Impl_SetPixelShaderConstantF,
    IDirect3DDevice9Impl_GetPixelShaderConstantF,
    IDirect3DDevice9Impl_SetPixelShaderConstantI,
    IDirect3DDevice9Impl_GetPixelShaderConstantI,
    IDirect3DDevice9Impl_SetPixelShaderConstantB,
    IDirect3DDevice9Impl_GetPixelShaderConstantB,
    IDirect3DDevice9Impl_DrawRectPatch,
    IDirect3DDevice9Impl_DrawTriPatch,
    IDirect3DDevice9Impl_DeletePatch,
3106 3107 3108 3109 3110 3111 3112 3113
    IDirect3DDevice9Impl_CreateQuery,
    /* IDirect3DDevice9Ex */
    IDirect3DDevice9ExImpl_SetConvolutionMonoKernel,
    IDirect3DDevice9ExImpl_ComposeRects,
    IDirect3DDevice9ExImpl_PresentEx,
    IDirect3DDevice9ExImpl_GetGPUThreadPriority,
    IDirect3DDevice9ExImpl_SetGPUThreadPriority,
    IDirect3DDevice9ExImpl_WaitForVBlank,
3114
    IDirect3DDevice9ExImpl_CheckResourceResidency,
3115 3116
    IDirect3DDevice9ExImpl_SetMaximumFrameLatency,
    IDirect3DDevice9ExImpl_GetMaximumFrameLatency,
3117
    IDirect3DDevice9ExImpl_CheckDeviceState,
3118 3119 3120 3121 3122
    IDirect3DDevice9ExImpl_CreateRenderTargetEx,
    IDirect3DDevice9ExImpl_CreateOffscreenPlainSurfaceEx,
    IDirect3DDevice9ExImpl_CreateDepthStencilSurfaceEx,
    IDirect3DDevice9ExImpl_ResetEx,
    IDirect3DDevice9ExImpl_GetDisplayModeEx
3123
};
3124

3125
static inline struct IDirect3DDevice9Impl *device_from_device_parent(struct wined3d_device_parent *device_parent)
3126
{
3127
    return CONTAINING_RECORD(device_parent, struct IDirect3DDevice9Impl, device_parent);
3128 3129
}

3130
static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
3131
        struct wined3d_device *device)
3132
{
3133
    TRACE("device_parent %p, device %p.\n", device_parent, device);
3134 3135
}

3136 3137 3138 3139 3140
static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
{
    TRACE("device_parent %p.\n", device_parent);
}

3141
static HRESULT CDECL device_parent_create_surface(struct wined3d_device_parent *device_parent,
3142
        void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
3143
        enum wined3d_pool pool, UINT level, enum wined3d_cubemap_face face, struct wined3d_surface **surface)
3144
{
3145
    struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3146 3147 3148 3149
    IDirect3DSurface9Impl *d3d_surface;
    BOOL lockable = TRUE;
    HRESULT hr;

3150 3151 3152
    TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
            "\tpool %#x, level %u, face %u, surface %p.\n",
            device_parent, container_parent, width, height, format, usage, pool, level, face, surface);
3153

3154
    if (pool == WINED3D_POOL_DEFAULT && !(usage & D3DUSAGE_DYNAMIC))
3155
        lockable = FALSE;
3156

3157
    hr = IDirect3DDevice9Impl_CreateSurface(device, width, height,
3158
            d3dformat_from_wined3dformat(format), lockable, FALSE /* Discard */, level,
3159
            (IDirect3DSurface9 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
3160 3161
    if (FAILED(hr))
    {
3162
        WARN("Failed to create surface, hr %#x.\n", hr);
3163 3164 3165
        return hr;
    }

3166 3167
    *surface = d3d_surface->wined3d_surface;
    wined3d_surface_incref(*surface);
3168

3169
    d3d_surface->container = container_parent;
3170 3171
    IDirect3DDevice9Ex_Release(d3d_surface->parentDevice);
    d3d_surface->parentDevice = NULL;
3172

3173
    IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
3174
    d3d_surface->forwardReference = container_parent;
3175 3176 3177 3178

    return hr;
}

3179
static HRESULT CDECL device_parent_create_rendertarget(struct wined3d_device_parent *device_parent,
3180
        void *container_parent, UINT width, UINT height, enum wined3d_format_id format,
3181
        enum wined3d_multisample_type multisample_type, DWORD multisample_quality, BOOL lockable,
3182
        struct wined3d_surface **surface)
3183
{
3184
    struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3185 3186 3187
    IDirect3DSurface9Impl *d3d_surface;
    HRESULT hr;

3188 3189 3190 3191
    TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
            "\tmultisample_quality %u, lockable %u, surface %p.\n",
            device_parent, container_parent, width, height, format, multisample_type,
            multisample_quality, lockable, surface);
3192

3193
    hr = IDirect3DDevice9Impl_CreateRenderTarget(&device->IDirect3DDevice9Ex_iface, width, height,
3194 3195
            d3dformat_from_wined3dformat(format), multisample_type, multisample_quality, lockable,
            (IDirect3DSurface9 **)&d3d_surface, NULL);
3196 3197
    if (FAILED(hr))
    {
3198
        WARN("Failed to create rendertarget, hr %#x.\n", hr);
3199 3200 3201
        return hr;
    }

3202 3203
    *surface = d3d_surface->wined3d_surface;
    wined3d_surface_incref(*surface);
3204

3205
    d3d_surface->container = container_parent;
3206
    /* Implicit surfaces are created with an refcount of 0 */
3207
    IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
3208 3209 3210 3211

    return hr;
}

3212
static HRESULT CDECL device_parent_create_depth_stencil(struct wined3d_device_parent *device_parent,
3213
        UINT width, UINT height, enum wined3d_format_id format, enum wined3d_multisample_type multisample_type,
3214
        DWORD multisample_quality, BOOL discard, struct wined3d_surface **surface)
3215
{
3216
    struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3217 3218 3219
    IDirect3DSurface9Impl *d3d_surface;
    HRESULT hr;

3220 3221 3222
    TRACE("device_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
            "\tmultisample_quality %u, discard %u, surface %p.\n",
            device_parent, width, height, format, multisample_type, multisample_quality, discard, surface);
3223

3224
    hr = IDirect3DDevice9Impl_CreateDepthStencilSurface(&device->IDirect3DDevice9Ex_iface, width,
3225 3226
            height, d3dformat_from_wined3dformat(format), multisample_type, multisample_quality,
            discard, (IDirect3DSurface9 **)&d3d_surface, NULL);
3227 3228
    if (FAILED(hr))
    {
3229
        WARN("Failed to create depth/stencil surface, hr %#x.\n", hr);
3230 3231 3232
        return hr;
    }

3233 3234
    *surface = d3d_surface->wined3d_surface;
    wined3d_surface_incref(*surface);
3235
    d3d_surface->container = (IUnknown *)&device->IDirect3DDevice9Ex_iface;
3236
    /* Implicit surfaces are created with an refcount of 0 */
3237
    IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
3238 3239 3240 3241

    return hr;
}

3242
static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
3243
        void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
3244
        enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
3245
{
3246
    struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3247 3248 3249
    IDirect3DVolume9Impl *object;
    HRESULT hr;

3250 3251 3252 3253
    TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
            "format %#x, pool %#x, usage %#x, volume %p\n",
            device_parent, container_parent, width, height, depth,
            format, pool, usage, volume);
3254 3255 3256 3257 3258 3259 3260 3261 3262 3263

    /* Allocate the storage for the device */
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        FIXME("Allocation of memory failed\n");
        *volume = NULL;
        return D3DERR_OUTOFVIDEOMEMORY;
    }

3264
    hr = volume_init(object, device, width, height, depth, usage, format, pool);
3265 3266
    if (FAILED(hr))
    {
3267
        WARN("Failed to initialize volume, hr %#x.\n", hr);
3268 3269 3270 3271
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

3272 3273
    *volume = object->wined3d_volume;
    wined3d_volume_incref(*volume);
3274
    IDirect3DVolume9_Release(&object->IDirect3DVolume9_iface);
3275

3276 3277
    object->container = container_parent;
    object->forwardReference = container_parent;
3278

3279
    TRACE("Created volume %p.\n", object);
3280 3281 3282 3283

    return hr;
}

3284
static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
3285
        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
3286
{
3287
    struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3288
    D3DPRESENT_PARAMETERS local_parameters;
3289
    IDirect3DSwapChain9Impl *d3d_swapchain;
3290 3291
    HRESULT hr;

3292
    TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc, swapchain);
3293 3294

    /* Copy the presentation parameters */
3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308
    local_parameters.BackBufferWidth = desc->backbuffer_width;
    local_parameters.BackBufferHeight = desc->backbuffer_height;
    local_parameters.BackBufferFormat = d3dformat_from_wined3dformat(desc->backbuffer_format);
    local_parameters.BackBufferCount = desc->backbuffer_count;
    local_parameters.MultiSampleType = desc->multisample_type;
    local_parameters.MultiSampleQuality = desc->multisample_quality;
    local_parameters.SwapEffect = desc->swap_effect;
    local_parameters.hDeviceWindow = desc->device_window;
    local_parameters.Windowed = desc->windowed;
    local_parameters.EnableAutoDepthStencil = desc->enable_auto_depth_stencil;
    local_parameters.AutoDepthStencilFormat = d3dformat_from_wined3dformat(desc->auto_depth_stencil_format);
    local_parameters.Flags = desc->flags;
    local_parameters.FullScreen_RefreshRateInHz = desc->refresh_rate;
    local_parameters.PresentationInterval = desc->swap_interval;
3309

3310
    hr = d3d9_swapchain_create(device, &local_parameters, &d3d_swapchain);
3311 3312
    if (FAILED(hr))
    {
3313
        WARN("Failed to create swapchain, hr %#x.\n", hr);
3314 3315 3316 3317
        *swapchain = NULL;
        return hr;
    }

3318
    *swapchain = d3d_swapchain->wined3d_swapchain;
3319
    wined3d_swapchain_incref(*swapchain);
3320
    IDirect3DSwapChain9_Release(&d3d_swapchain->IDirect3DSwapChain9_iface);
3321 3322

    /* Copy back the presentation parameters */
3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336
    desc->backbuffer_width = local_parameters.BackBufferWidth;
    desc->backbuffer_height = local_parameters.BackBufferHeight;
    desc->backbuffer_format = wined3dformat_from_d3dformat(local_parameters.BackBufferFormat);
    desc->backbuffer_count = local_parameters.BackBufferCount;
    desc->multisample_type = local_parameters.MultiSampleType;
    desc->multisample_quality = local_parameters.MultiSampleQuality;
    desc->swap_effect = local_parameters.SwapEffect;
    desc->device_window = local_parameters.hDeviceWindow;
    desc->windowed = local_parameters.Windowed;
    desc->enable_auto_depth_stencil = local_parameters.EnableAutoDepthStencil;
    desc->auto_depth_stencil_format = wined3dformat_from_d3dformat(local_parameters.AutoDepthStencilFormat);
    desc->flags = local_parameters.Flags;
    desc->refresh_rate = local_parameters.FullScreen_RefreshRateInHz;
    desc->swap_interval = local_parameters.PresentationInterval;
3337 3338 3339 3340

    return hr;
}

3341
static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
3342
{
3343
    device_parent_wined3d_device_created,
3344
    device_parent_mode_changed,
3345 3346 3347 3348 3349
    device_parent_create_surface,
    device_parent_create_rendertarget,
    device_parent_create_depth_stencil,
    device_parent_create_volume,
    device_parent_create_swapchain,
3350
};
3351

3352 3353 3354
static void setup_fpu(void)
{
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3355
    WORD cw;
3356 3357 3358
    __asm__ volatile ("fnstcw %0" : "=m" (cw));
    cw = (cw & ~0xf3f) | 0x3f;
    __asm__ volatile ("fldcw %0" : : "m" (cw));
3359 3360 3361 3362 3363
#elif defined(__i386__) && defined(_MSC_VER)
    WORD cw;
    __asm fnstcw cw;
    cw = (cw & ~0xf3f) | 0x3f;
    __asm fldcw cw;
3364 3365 3366 3367 3368
#else
    FIXME("FPU setup not implemented for this platform.\n");
#endif
}

3369 3370 3371
HRESULT device_init(IDirect3DDevice9Impl *device, IDirect3D9Impl *parent, struct wined3d *wined3d,
        UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags,
        D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode)
3372
{
3373
    struct wined3d_swapchain_desc *swapchain_desc;
3374 3375 3376
    UINT i, count = 1;
    HRESULT hr;

3377 3378 3379
    if (mode)
        FIXME("Ignoring display mode.\n");

3380
    device->IDirect3DDevice9Ex_iface.lpVtbl = &Direct3DDevice9_Vtbl;
3381
    device->device_parent.ops = &d3d9_wined3d_device_parent_ops;
3382 3383
    device->ref = 1;

3384 3385
    if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();

3386
    wined3d_mutex_lock();
3387
    hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
3388
            &device->device_parent, &device->wined3d_device);
3389 3390 3391 3392 3393 3394 3395
    if (FAILED(hr))
    {
        WARN("Failed to create wined3d device, hr %#x.\n", hr);
        wined3d_mutex_unlock();
        return hr;
    }

3396 3397 3398 3399
    if (flags & D3DCREATE_ADAPTERGROUP_DEVICE)
    {
        WINED3DCAPS caps;

3400
        wined3d_get_device_caps(wined3d, adapter, device_type, &caps);
3401 3402 3403
        count = caps.NumberOfAdaptersInGroup;
    }

3404 3405
    if (flags & D3DCREATE_MULTITHREADED)
        wined3d_device_set_multithreaded(device->wined3d_device);
3406

3407 3408
    if (!parameters->Windowed)
    {
3409 3410 3411
        if (!focus_window)
            focus_window = parameters->hDeviceWindow;
        if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
3412 3413
        {
            ERR("Failed to acquire focus window, hr %#x.\n", hr);
3414
            wined3d_device_decref(device->wined3d_device);
3415 3416 3417 3418
            wined3d_mutex_unlock();
            return hr;
        }

3419 3420 3421
        for (i = 0; i < count; ++i)
        {
            HWND device_window = parameters[i].hDeviceWindow;
3422

3423
            if (!device_window) device_window = focus_window;
3424
            wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
3425 3426 3427
                    parameters[i].BackBufferWidth,
                    parameters[i].BackBufferHeight);
        }
3428 3429
    }

3430 3431
    swapchain_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain_desc) * count);
    if (!swapchain_desc)
3432 3433
    {
        ERR("Failed to allocate wined3d parameters.\n");
3434
        wined3d_device_decref(device->wined3d_device);
3435 3436 3437 3438 3439 3440
        wined3d_mutex_unlock();
        return E_OUTOFMEMORY;
    }

    for (i = 0; i < count; ++i)
    {
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451
        swapchain_desc[i].backbuffer_width = parameters[i].BackBufferWidth;
        swapchain_desc[i].backbuffer_height = parameters[i].BackBufferHeight;
        swapchain_desc[i].backbuffer_format = wined3dformat_from_d3dformat(parameters[i].BackBufferFormat);
        swapchain_desc[i].backbuffer_count = parameters[i].BackBufferCount;
        swapchain_desc[i].multisample_type = parameters[i].MultiSampleType;
        swapchain_desc[i].multisample_quality = parameters[i].MultiSampleQuality;
        swapchain_desc[i].swap_effect = parameters[i].SwapEffect;
        swapchain_desc[i].device_window = parameters[i].hDeviceWindow;
        swapchain_desc[i].windowed = parameters[i].Windowed;
        swapchain_desc[i].enable_auto_depth_stencil = parameters[i].EnableAutoDepthStencil;
        swapchain_desc[i].auto_depth_stencil_format =
3452
                wined3dformat_from_d3dformat(parameters[i].AutoDepthStencilFormat);
3453 3454 3455 3456
        swapchain_desc[i].flags = parameters[i].Flags;
        swapchain_desc[i].refresh_rate = parameters[i].FullScreen_RefreshRateInHz;
        swapchain_desc[i].swap_interval = parameters[i].PresentationInterval;
        swapchain_desc[i].auto_restore_display_mode = TRUE;
3457 3458
    }

3459
    hr = wined3d_device_init_3d(device->wined3d_device, swapchain_desc);
3460 3461 3462
    if (FAILED(hr))
    {
        WARN("Failed to initialize 3D, hr %#x.\n", hr);
3463
        wined3d_device_release_focus_window(device->wined3d_device);
3464
        HeapFree(GetProcessHeap(), 0, swapchain_desc);
3465
        wined3d_device_decref(device->wined3d_device);
3466 3467 3468 3469 3470 3471 3472 3473
        wined3d_mutex_unlock();
        return hr;
    }

    wined3d_mutex_unlock();

    for (i = 0; i < count; ++i)
    {
3474 3475 3476 3477 3478 3479 3480 3481 3482 3483
        parameters[i].BackBufferWidth = swapchain_desc[i].backbuffer_width;
        parameters[i].BackBufferHeight = swapchain_desc[i].backbuffer_height;
        parameters[i].BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc[i].backbuffer_format);
        parameters[i].BackBufferCount = swapchain_desc[i].backbuffer_count;
        parameters[i].MultiSampleType = swapchain_desc[i].multisample_type;
        parameters[i].MultiSampleQuality = swapchain_desc[i].multisample_quality;
        parameters[i].SwapEffect = swapchain_desc[i].swap_effect;
        parameters[i].hDeviceWindow = swapchain_desc[i].device_window;
        parameters[i].Windowed = swapchain_desc[i].windowed;
        parameters[i].EnableAutoDepthStencil = swapchain_desc[i].enable_auto_depth_stencil;
3484
        parameters[i].AutoDepthStencilFormat =
3485 3486 3487 3488
                d3dformat_from_wined3dformat(swapchain_desc[i].auto_depth_stencil_format);
        parameters[i].Flags = swapchain_desc[i].flags;
        parameters[i].FullScreen_RefreshRateInHz = swapchain_desc[i].refresh_rate;
        parameters[i].PresentationInterval = swapchain_desc[i].swap_interval;
3489
    }
3490
    HeapFree(GetProcessHeap(), 0, swapchain_desc);
3491 3492 3493

    /* Initialize the converted declaration array. This creates a valid pointer
     * and when adding decls HeapReAlloc() can be used without further checking. */
3494 3495
    device->fvf_decls = HeapAlloc(GetProcessHeap(), 0, 0);
    if (!device->fvf_decls)
3496 3497 3498
    {
        ERR("Failed to allocate FVF vertex declaration map memory.\n");
        wined3d_mutex_lock();
3499 3500 3501
        wined3d_device_uninit_3d(device->wined3d_device);
        wined3d_device_release_focus_window(device->wined3d_device);
        wined3d_device_decref(device->wined3d_device);
3502 3503 3504 3505
        wined3d_mutex_unlock();
        return E_OUTOFMEMORY;
    }

3506 3507
    IDirect3D9Ex_AddRef(&parent->IDirect3D9Ex_iface);
    device->d3d_parent = parent;
3508

3509 3510
    return D3D_OK;
}