Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright 2011 Joakim Sindholt 
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * on the rights to use, copy, modify, merge, publish, distribute, sub
8
 * license, and/or sell copies of the Software, and to permit persons to whom
9
 * the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21
 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
 
23
#include "device9.h"
24
#include "stateblock9.h"
25
#include "surface9.h"
26
#include "swapchain9.h"
27
#include "swapchain9ex.h"
28
#include "indexbuffer9.h"
29
#include "vertexbuffer9.h"
30
#include "vertexdeclaration9.h"
31
#include "vertexshader9.h"
32
#include "pixelshader9.h"
33
#include "query9.h"
34
#include "texture9.h"
35
#include "cubetexture9.h"
36
#include "volumetexture9.h"
37
#include "nine_helpers.h"
38
#include "nine_pipe.h"
39
#include "nine_ff.h"
40
#include "nine_dump.h"
41
 
42
#include "pipe/p_screen.h"
43
#include "pipe/p_context.h"
44
#include "pipe/p_config.h"
45
#include "util/u_math.h"
46
#include "util/u_inlines.h"
47
#include "util/u_hash_table.h"
48
#include "util/u_format.h"
49
#include "util/u_surface.h"
50
#include "util/u_upload_mgr.h"
51
#include "hud/hud_context.h"
52
 
53
#include "cso_cache/cso_context.h"
54
 
55
#define DBG_CHANNEL DBG_DEVICE
56
 
57
#if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))
58
 
59
#include 
60
 
61
static void nine_setup_fpu()
62
{
63
    fpu_control_t c;
64
 
65
    _FPU_GETCW(c);
66
    /* clear the control word */
67
    c &= _FPU_RESERVED;
68
    /* d3d9 doc/wine tests: mask all exceptions, use single-precision
69
     * and round to nearest */
70
    c |= _FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM |
71
         _FPU_MASK_UM | _FPU_MASK_PM | _FPU_SINGLE | _FPU_RC_NEAREST;
72
    _FPU_SETCW(c);
73
}
74
 
75
#else
76
 
77
static void nine_setup_fpu(void)
78
{
79
    WARN_ONCE("FPU setup not supported on non-x86 platforms\n");
80
}
81
 
82
#endif
83
 
84
static void
85
NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
86
{
87
    struct NineSurface9 *refSurf = NULL;
88
 
89
    DBG("This=%p is_reset=%d\n", This, (int) is_reset);
90
 
91
    assert(!This->is_recording);
92
 
93
    nine_state_set_defaults(This, &This->caps, is_reset);
94
 
95
    This->state.viewport.X = 0;
96
    This->state.viewport.Y = 0;
97
    This->state.viewport.Width = 0;
98
    This->state.viewport.Height = 0;
99
 
100
    This->state.scissor.minx = 0;
101
    This->state.scissor.miny = 0;
102
    This->state.scissor.maxx = 0xffff;
103
    This->state.scissor.maxy = 0xffff;
104
 
105
    if (This->nswapchains && This->swapchains[0]->params.BackBufferCount)
106
        refSurf = This->swapchains[0]->buffers[0];
107
 
108
    if (refSurf) {
109
        This->state.viewport.Width = refSurf->desc.Width;
110
        This->state.viewport.Height = refSurf->desc.Height;
111
        This->state.scissor.maxx = refSurf->desc.Width;
112
        This->state.scissor.maxy = refSurf->desc.Height;
113
    }
114
 
115
    if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil)
116
        This->state.rs[D3DRS_ZENABLE] = TRUE;
117
    if (This->state.rs[D3DRS_ZENABLE])
118
        NineDevice9_SetDepthStencilSurface(
119
            This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);
120
}
121
 
122
void
123
NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask )
124
{
125
    struct pipe_context *pipe = This->pipe;
126
 
127
    DBG("This=%p mask=%u\n", This, mask);
128
 
129
    if (mask & 0x1) {
130
        struct pipe_constant_buffer cb;
131
        cb.buffer_offset = 0;
132
 
133
        if (This->prefer_user_constbuf) {
134
            cb.buffer = NULL;
135
            cb.user_buffer = This->state.vs_const_f;
136
        } else {
137
            cb.buffer = This->constbuf_vs;
138
            cb.user_buffer = NULL;
139
        }
140
        cb.buffer_size = This->vs_const_size;
141
        pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
142
 
143
        if (This->prefer_user_constbuf) {
144
            cb.user_buffer = This->state.ps_const_f;
145
        } else {
146
            cb.buffer = This->constbuf_ps;
147
        }
148
        cb.buffer_size = This->ps_const_size;
149
        pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
150
    }
151
 
152
    if (mask & 0x2) {
153
        struct pipe_poly_stipple stipple;
154
        memset(&stipple, ~0, sizeof(stipple));
155
        pipe->set_polygon_stipple(pipe, &stipple);
156
    }
157
 
158
    This->state.changed.group = NINE_STATE_ALL;
159
    This->state.changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
160
    This->state.changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
161
    This->state.changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
162
}
163
 
164
#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
165
HRESULT
166
NineDevice9_ctor( struct NineDevice9 *This,
167
                  struct NineUnknownParams *pParams,
168
                  struct pipe_screen *pScreen,
169
                  D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
170
                  D3DCAPS9 *pCaps,
171
                  D3DPRESENT_PARAMETERS *pPresentationParameters,
172
                  IDirect3D9 *pD3D9,
173
                  ID3DPresentGroup *pPresentationGroup,
174
                  struct d3dadapter9_context *pCTX,
175
                  boolean ex,
176
                  D3DDISPLAYMODEEX *pFullscreenDisplayMode )
177
{
178
    unsigned i;
179
    HRESULT hr = NineUnknown_ctor(&This->base, pParams);
180
 
181
    DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "
182
        "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",
183
        This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9,
184
        pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode);
185
 
186
    if (FAILED(hr)) { return hr; }
187
 
188
    list_inithead(&This->update_textures);
189
 
190
    This->screen = pScreen;
191
    This->caps = *pCaps;
192
    This->d3d9 = pD3D9;
193
    This->params = *pCreationParameters;
194
    This->ex = ex;
195
    This->present = pPresentationGroup;
196
    IDirect3D9_AddRef(This->d3d9);
197
    ID3DPresentGroup_AddRef(This->present);
198
 
199
    if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE))
200
        nine_setup_fpu();
201
 
202
    if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
203
        DBG("Application asked full Software Vertex Processing. Ignoring.\n");
204
    if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING)
205
        DBG("Application asked mixed Software Vertex Processing. Ignoring.\n");
206
 
207
    This->pipe = This->screen->context_create(This->screen, NULL);
208
    if (!This->pipe) { return E_OUTOFMEMORY; } /* guess */
209
 
210
    This->cso = cso_create_context(This->pipe);
211
    if (!This->cso) { return E_OUTOFMEMORY; } /* also a guess */
212
 
213
    /* Create first, it messes up our state. */
214
    This->hud = hud_create(This->pipe, This->cso); /* NULL result is fine */
215
 
216
    /* create implicit swapchains */
217
    This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present);
218
    This->swapchains = CALLOC(This->nswapchains,
219
                              sizeof(struct NineSwapChain9 *));
220
    if (!This->swapchains) { return E_OUTOFMEMORY; }
221
 
222
    for (i = 0; i < This->nswapchains; ++i) {
223
        ID3DPresent *present;
224
 
225
        hr = ID3DPresentGroup_GetPresent(This->present, i, &present);
226
        if (FAILED(hr))
227
            return hr;
228
 
229
        if (ex) {
230
            D3DDISPLAYMODEEX *mode = NULL;
231
            struct NineSwapChain9Ex **ret =
232
                (struct NineSwapChain9Ex **)&This->swapchains[i];
233
 
234
            if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);
235
            /* when this is a Device9Ex, it should create SwapChain9Exs */
236
            hr = NineSwapChain9Ex_new(This, TRUE, present,
237
                                      &pPresentationParameters[i], pCTX,
238
                                      This->params.hFocusWindow, mode, ret);
239
        } else {
240
            hr = NineSwapChain9_new(This, TRUE, present,
241
                                    &pPresentationParameters[i], pCTX,
242
                                    This->params.hFocusWindow,
243
                                    &This->swapchains[i]);
244
        }
245
 
246
        ID3DPresent_Release(present);
247
        if (FAILED(hr))
248
            return hr;
249
        NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i]));
250
 
251
        hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0,
252
                                          D3DBACKBUFFER_TYPE_MONO,
253
                                          (IDirect3DSurface9 **)
254
                                          &This->state.rt[i]);
255
        if (FAILED(hr))
256
            return hr;
257
        NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i]));
258
    }
259
 
260
    /* Initialize a dummy VBO to be used when a a vertex declaration does not
261
     * specify all the inputs needed by vertex shader, on win default behavior
262
     * is to pass 0,0,0,0 to the shader */
263
    {
264
        struct pipe_transfer *transfer;
265
        struct pipe_resource tmpl;
266
        struct pipe_box box;
267
        unsigned char *data;
268
 
269
        tmpl.target = PIPE_BUFFER;
270
        tmpl.format = PIPE_FORMAT_R8_UNORM;
271
        tmpl.width0 = 16; /* 4 floats */
272
        tmpl.height0 = 1;
273
        tmpl.depth0 = 1;
274
        tmpl.array_size = 1;
275
        tmpl.last_level = 0;
276
        tmpl.nr_samples = 0;
277
        tmpl.usage = PIPE_USAGE_DEFAULT;
278
        tmpl.bind = PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_TRANSFER_WRITE;
279
        tmpl.flags = 0;
280
        This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl);
281
 
282
        if (!This->dummy_vbo)
283
            return D3DERR_OUTOFVIDEOMEMORY;
284
 
285
        u_box_1d(0, 16, &box);
286
        data = This->pipe->transfer_map(This->pipe, This->dummy_vbo, 0,
287
                                        PIPE_TRANSFER_WRITE |
288
                                        PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
289
                                        &box, &transfer);
290
        assert(data);
291
        assert(transfer);
292
        memset(data, 0, 16);
293
        This->pipe->transfer_unmap(This->pipe, transfer);
294
    }
295
 
296
    This->cursor.software = FALSE;
297
    This->cursor.hotspot.x = -1;
298
    This->cursor.hotspot.y = -1;
299
    {
300
        struct pipe_resource tmpl;
301
        tmpl.target = PIPE_TEXTURE_2D;
302
        tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM;
303
        tmpl.width0 = 64;
304
        tmpl.height0 = 64;
305
        tmpl.depth0 = 1;
306
        tmpl.array_size = 1;
307
        tmpl.last_level = 0;
308
        tmpl.nr_samples = 0;
309
        tmpl.usage = PIPE_USAGE_DEFAULT;
310
        tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW;
311
        tmpl.flags = 0;
312
 
313
        This->cursor.image = pScreen->resource_create(pScreen, &tmpl);
314
        if (!This->cursor.image)
315
            return D3DERR_OUTOFVIDEOMEMORY;
316
    }
317
 
318
    /* Create constant buffers. */
319
    {
320
        struct pipe_resource tmpl;
321
        unsigned max_const_vs, max_const_ps;
322
 
323
        /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
324
         * we have to take in some more slots for int and bool*/
325
        max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX,
326
                                PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
327
                                sizeof(float[4]),
328
                            NINE_MAX_CONST_ALL);
329
        /* ps 3.0: 224 float constants. All cards supported support at least
330
         * 256 constants for ps */
331
        max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
332
 
333
        This->max_vs_const_f = max_const_vs -
334
                               (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
335
        This->max_ps_const_f = max_const_ps -
336
                               (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
337
 
338
        This->vs_const_size = max_const_vs * sizeof(float[4]);
339
        This->ps_const_size = max_const_ps * sizeof(float[4]);
340
        /* Include space for I,B constants for user constbuf. */
341
        This->state.vs_const_f = CALLOC(This->vs_const_size, 1);
342
        This->state.ps_const_f = CALLOC(This->ps_const_size, 1);
343
        This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1);
344
        if (!This->state.vs_const_f || !This->state.ps_const_f ||
345
            !This->state.vs_lconstf_temp)
346
            return E_OUTOFMEMORY;
347
 
348
        if (strstr(pScreen->get_name(pScreen), "AMD") ||
349
            strstr(pScreen->get_name(pScreen), "ATI")) {
350
            This->prefer_user_constbuf = TRUE;
351
            This->driver_bugs.buggy_barycentrics = TRUE;
352
        }
353
 
354
        tmpl.target = PIPE_BUFFER;
355
        tmpl.format = PIPE_FORMAT_R8_UNORM;
356
        tmpl.height0 = 1;
357
        tmpl.depth0 = 1;
358
        tmpl.array_size = 1;
359
        tmpl.last_level = 0;
360
        tmpl.nr_samples = 0;
361
        tmpl.usage = PIPE_USAGE_DYNAMIC;
362
        tmpl.bind = PIPE_BIND_CONSTANT_BUFFER;
363
        tmpl.flags = 0;
364
 
365
        tmpl.width0 = This->vs_const_size;
366
        This->constbuf_vs = pScreen->resource_create(pScreen, &tmpl);
367
 
368
        tmpl.width0 = This->ps_const_size;
369
        This->constbuf_ps = pScreen->resource_create(pScreen, &tmpl);
370
 
371
        if (!This->constbuf_vs || !This->constbuf_ps)
372
            return E_OUTOFMEMORY;
373
    }
374
 
375
    /* allocate dummy texture/sampler for when there are missing ones bound */
376
    {
377
        struct pipe_resource tmplt;
378
        struct pipe_sampler_view templ;
379
 
380
        tmplt.target = PIPE_TEXTURE_2D;
381
        tmplt.width0 = 1;
382
        tmplt.height0 = 1;
383
        tmplt.depth0 = 1;
384
        tmplt.last_level = 0;
385
        tmplt.array_size = 1;
386
        tmplt.usage = PIPE_USAGE_DEFAULT;
387
        tmplt.flags = 0;
388
        tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM;
389
        tmplt.bind = PIPE_BIND_SAMPLER_VIEW;
390
        tmplt.nr_samples = 0;
391
 
392
        This->dummy_texture = This->screen->resource_create(This->screen, &tmplt);
393
        if (!This->dummy_texture)
394
            return D3DERR_DRIVERINTERNALERROR;
395
 
396
        templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
397
        templ.u.tex.first_layer = 0;
398
        templ.u.tex.last_layer = 0;
399
        templ.u.tex.first_level = 0;
400
        templ.u.tex.last_level = 0;
401
        templ.swizzle_r = PIPE_SWIZZLE_ZERO;
402
        templ.swizzle_g = PIPE_SWIZZLE_ZERO;
403
        templ.swizzle_b = PIPE_SWIZZLE_ZERO;
404
        templ.swizzle_a = PIPE_SWIZZLE_ONE;
405
        templ.target = This->dummy_texture->target;
406
 
407
        This->dummy_sampler = This->pipe->create_sampler_view(This->pipe, This->dummy_texture, &templ);
408
        if (!This->dummy_sampler)
409
            return D3DERR_DRIVERINTERNALERROR;
410
    }
411
 
412
    /* Allocate upload helper for drivers that suck (from st pov ;). */
413
    {
414
        unsigned bind = 0;
415
 
416
        This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS);
417
        This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS);
418
 
419
        if (!This->driver_caps.user_vbufs) bind |= PIPE_BIND_VERTEX_BUFFER;
420
        if (!This->driver_caps.user_ibufs) bind |= PIPE_BIND_INDEX_BUFFER;
421
        if (bind)
422
            This->upload = u_upload_create(This->pipe, 1 << 20, 4, bind);
423
    }
424
 
425
    This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);
426
    This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS);
427
    This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS);
428
 
429
    nine_ff_init(This); /* initialize fixed function code */
430
 
431
    NineDevice9_SetDefaultState(This, FALSE);
432
    NineDevice9_RestoreNonCSOState(This, ~0);
433
 
434
    This->update = &This->state;
435
    nine_update_state(This, ~0);
436
 
437
    ID3DPresentGroup_Release(This->present);
438
 
439
    return D3D_OK;
440
}
441
#undef GET_PCAP
442
 
443
void
444
NineDevice9_dtor( struct NineDevice9 *This )
445
{
446
    unsigned i;
447
 
448
    DBG("This=%p\n", This);
449
 
450
    if (This->pipe && This->cso)
451
        nine_pipe_context_clear(This);
452
    nine_ff_fini(This);
453
    nine_state_clear(&This->state, TRUE);
454
 
455
    if (This->upload)
456
        u_upload_destroy(This->upload);
457
 
458
    nine_bind(&This->record, NULL);
459
 
460
    pipe_sampler_view_reference(&This->dummy_sampler, NULL);
461
    pipe_resource_reference(&This->dummy_texture, NULL);
462
    pipe_resource_reference(&This->constbuf_vs, NULL);
463
    pipe_resource_reference(&This->constbuf_ps, NULL);
464
    pipe_resource_reference(&This->dummy_vbo, NULL);
465
    FREE(This->state.vs_const_f);
466
    FREE(This->state.ps_const_f);
467
    FREE(This->state.vs_lconstf_temp);
468
 
469
    if (This->swapchains) {
470
        for (i = 0; i < This->nswapchains; ++i)
471
            NineUnknown_Unbind(NineUnknown(This->swapchains[i]));
472
        FREE(This->swapchains);
473
    }
474
 
475
    /* state stuff */
476
    if (This->pipe) {
477
        if (This->cso) {
478
            cso_destroy_context(This->cso);
479
        }
480
        if (This->pipe->destroy) { This->pipe->destroy(This->pipe); }
481
    }
482
 
483
    if (This->present) { ID3DPresentGroup_Release(This->present); }
484
    if (This->d3d9) { IDirect3D9_Release(This->d3d9); }
485
 
486
    NineUnknown_dtor(&This->base);
487
}
488
 
489
struct pipe_screen *
490
NineDevice9_GetScreen( struct NineDevice9 *This )
491
{
492
    return This->screen;
493
}
494
 
495
struct pipe_context *
496
NineDevice9_GetPipe( struct NineDevice9 *This )
497
{
498
    return This->pipe;
499
}
500
 
501
struct cso_context *
502
NineDevice9_GetCSO( struct NineDevice9 *This )
503
{
504
    return This->cso;
505
}
506
 
507
const D3DCAPS9 *
508
NineDevice9_GetCaps( struct NineDevice9 *This )
509
{
510
    return &This->caps;
511
}
512
 
513
static INLINE void
514
NineDevice9_PauseRecording( struct NineDevice9 *This )
515
{
516
    if (This->record) {
517
        This->update = &This->state;
518
        This->is_recording = FALSE;
519
    }
520
}
521
 
522
static INLINE void
523
NineDevice9_ResumeRecording( struct NineDevice9 *This )
524
{
525
    if (This->record) {
526
        This->update = &This->record->state;
527
        This->is_recording = TRUE;
528
    }
529
}
530
 
531
HRESULT WINAPI
532
NineDevice9_TestCooperativeLevel( struct NineDevice9 *This )
533
{
534
    return D3D_OK; /* TODO */
535
}
536
 
537
UINT WINAPI
538
NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This )
539
{
540
   const unsigned mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY);
541
   if (mem < 4096)
542
      return mem << 20;
543
   else
544
      return UINT_MAX;
545
}
546
 
547
HRESULT WINAPI
548
NineDevice9_EvictManagedResources( struct NineDevice9 *This )
549
{
550
    /* We don't really need to do anything here, but might want to free up
551
     * the GPU virtual address space by killing pipe_resources.
552
     */
553
    STUB(D3D_OK);
554
}
555
 
556
HRESULT WINAPI
557
NineDevice9_GetDirect3D( struct NineDevice9 *This,
558
                         IDirect3D9 **ppD3D9 )
559
{
560
    user_assert(ppD3D9 != NULL, E_POINTER);
561
    IDirect3D9_AddRef(This->d3d9);
562
    *ppD3D9 = This->d3d9;
563
    return D3D_OK;
564
}
565
 
566
HRESULT WINAPI
567
NineDevice9_GetDeviceCaps( struct NineDevice9 *This,
568
                           D3DCAPS9 *pCaps )
569
{
570
    user_assert(pCaps != NULL, D3DERR_INVALIDCALL);
571
    *pCaps = This->caps;
572
    return D3D_OK;
573
}
574
 
575
HRESULT WINAPI
576
NineDevice9_GetDisplayMode( struct NineDevice9 *This,
577
                            UINT iSwapChain,
578
                            D3DDISPLAYMODE *pMode )
579
{
580
    DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode);
581
 
582
    user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
583
 
584
    return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode);
585
}
586
 
587
HRESULT WINAPI
588
NineDevice9_GetCreationParameters( struct NineDevice9 *This,
589
                                   D3DDEVICE_CREATION_PARAMETERS *pParameters )
590
{
591
    user_assert(pParameters != NULL, D3DERR_INVALIDCALL);
592
    *pParameters = This->params;
593
    return D3D_OK;
594
}
595
 
596
HRESULT WINAPI
597
NineDevice9_SetCursorProperties( struct NineDevice9 *This,
598
                                 UINT XHotSpot,
599
                                 UINT YHotSpot,
600
                                 IDirect3DSurface9 *pCursorBitmap )
601
{
602
    /* TODO: hardware cursor */
603
    struct NineSurface9 *surf = NineSurface9(pCursorBitmap);
604
    struct pipe_context *pipe = This->pipe;
605
    struct pipe_box box;
606
    struct pipe_transfer *transfer;
607
    void *ptr;
608
 
609
    DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u "
610
             "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap);
611
 
612
    user_assert(pCursorBitmap, D3DERR_INVALIDCALL);
613
 
614
    This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);
615
    This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);
616
 
617
    u_box_origin_2d(This->cursor.w, This->cursor.h, &box);
618
 
619
    ptr = pipe->transfer_map(pipe, This->cursor.image, 0,
620
                             PIPE_TRANSFER_WRITE |
621
                             PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
622
                             &box, &transfer);
623
    if (!ptr)
624
        ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR);
625
 
626
    This->cursor.hotspot.x = XHotSpot;
627
    This->cursor.hotspot.y = YHotSpot;
628
 
629
    /* Copy cursor image to internal storage. */
630
    {
631
        D3DLOCKED_RECT lock;
632
        HRESULT hr;
633
        const struct util_format_description *sfmt =
634
            util_format_description(surf->base.info.format);
635
        assert(sfmt);
636
 
637
        hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY);
638
        if (FAILED(hr))
639
            ret_err("Failed to map cursor source image.\n",
640
                    D3DERR_DRIVERINTERNALERROR);
641
 
642
        sfmt->unpack_rgba_8unorm(ptr, transfer->stride,
643
                                 lock.pBits, lock.Pitch,
644
                                 This->cursor.w, This->cursor.h);
645
 
646
        if (!This->cursor.software &&
647
            This->cursor.w == 32 && This->cursor.h == 32)
648
            ID3DPresent_SetCursor(This->swapchains[0]->present,
649
                                  lock.pBits, &This->cursor.hotspot,
650
                                  This->cursor.visible);
651
 
652
        NineSurface9_UnlockRect(surf);
653
    }
654
    pipe->transfer_unmap(pipe, transfer);
655
 
656
    return D3D_OK;
657
}
658
 
659
void WINAPI
660
NineDevice9_SetCursorPosition( struct NineDevice9 *This,
661
                               int X,
662
                               int Y,
663
                               DWORD Flags )
664
{
665
    struct NineSwapChain9 *swap = This->swapchains[0];
666
 
667
    DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags);
668
 
669
    This->cursor.pos.x = X;
670
    This->cursor.pos.y = Y;
671
 
672
    if (!This->cursor.software)
673
        ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos);
674
}
675
 
676
BOOL WINAPI
677
NineDevice9_ShowCursor( struct NineDevice9 *This,
678
                        BOOL bShow )
679
{
680
    BOOL old = This->cursor.visible;
681
 
682
    DBG("This=%p bShow=%d\n", This, (int) bShow);
683
 
684
    This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
685
    if (!This->cursor.software)
686
        ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow);
687
 
688
    return old;
689
}
690
 
691
HRESULT WINAPI
692
NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,
693
                                       D3DPRESENT_PARAMETERS *pPresentationParameters,
694
                                       IDirect3DSwapChain9 **pSwapChain )
695
{
696
    struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0];
697
    ID3DPresent *present;
698
    HRESULT hr;
699
 
700
    DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",
701
        This, pPresentationParameters, pSwapChain);
702
 
703
    user_assert(pPresentationParameters, D3DERR_INVALIDCALL);
704
 
705
    hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present);
706
 
707
    if (FAILED(hr))
708
        return hr;
709
 
710
    hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters,
711
                            tmplt->actx,
712
                            tmplt->params.hDeviceWindow,
713
                            &swapchain);
714
    if (FAILED(hr))
715
        return hr;
716
 
717
    *pSwapChain = (IDirect3DSwapChain9 *)swapchain;
718
    return D3D_OK;
719
}
720
 
721
HRESULT WINAPI
722
NineDevice9_GetSwapChain( struct NineDevice9 *This,
723
                          UINT iSwapChain,
724
                          IDirect3DSwapChain9 **pSwapChain )
725
{
726
    user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL);
727
 
728
    *pSwapChain = NULL;
729
    user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
730
 
731
    NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain]));
732
    *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain];
733
 
734
    return D3D_OK;
735
}
736
 
737
UINT WINAPI
738
NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This )
739
{
740
    return This->nswapchains;
741
}
742
 
743
HRESULT WINAPI
744
NineDevice9_Reset( struct NineDevice9 *This,
745
                   D3DPRESENT_PARAMETERS *pPresentationParameters )
746
{
747
    HRESULT hr = D3D_OK;
748
    unsigned i;
749
 
750
    DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
751
 
752
    for (i = 0; i < This->nswapchains; ++i) {
753
        D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
754
        hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);
755
        if (FAILED(hr))
756
            return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST;
757
    }
758
 
759
    nine_pipe_context_clear(This);
760
    nine_state_clear(&This->state, TRUE);
761
 
762
    NineDevice9_SetDefaultState(This, TRUE);
763
    NineDevice9_SetRenderTarget(
764
        This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]);
765
    /* XXX: better use GetBackBuffer here ? */
766
 
767
    return hr;
768
}
769
 
770
HRESULT WINAPI
771
NineDevice9_Present( struct NineDevice9 *This,
772
                     const RECT *pSourceRect,
773
                     const RECT *pDestRect,
774
                     HWND hDestWindowOverride,
775
                     const RGNDATA *pDirtyRegion )
776
{
777
    unsigned i;
778
    HRESULT hr;
779
 
780
    DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",
781
        This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
782
 
783
    /* XXX is this right? */
784
    for (i = 0; i < This->nswapchains; ++i) {
785
        hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect,
786
                                    hDestWindowOverride, pDirtyRegion, 0);
787
        if (FAILED(hr)) { return hr; }
788
    }
789
 
790
    return D3D_OK;
791
}
792
 
793
HRESULT WINAPI
794
NineDevice9_GetBackBuffer( struct NineDevice9 *This,
795
                           UINT iSwapChain,
796
                           UINT iBackBuffer,
797
                           D3DBACKBUFFER_TYPE Type,
798
                           IDirect3DSurface9 **ppBackBuffer )
799
{
800
    user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL);
801
    user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
802
 
803
    return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain],
804
                                        iBackBuffer, Type, ppBackBuffer);
805
}
806
 
807
HRESULT WINAPI
808
NineDevice9_GetRasterStatus( struct NineDevice9 *This,
809
                             UINT iSwapChain,
810
                             D3DRASTER_STATUS *pRasterStatus )
811
{
812
    user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL);
813
    user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
814
 
815
    return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain],
816
                                          pRasterStatus);
817
}
818
 
819
HRESULT WINAPI
820
NineDevice9_SetDialogBoxMode( struct NineDevice9 *This,
821
                              BOOL bEnableDialogs )
822
{
823
    STUB(D3DERR_INVALIDCALL);
824
}
825
 
826
void WINAPI
827
NineDevice9_SetGammaRamp( struct NineDevice9 *This,
828
                          UINT iSwapChain,
829
                          DWORD Flags,
830
                          const D3DGAMMARAMP *pRamp )
831
{
832
    DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This,
833
        iSwapChain, Flags, pRamp);
834
 
835
    user_warn(iSwapChain >= This->nswapchains);
836
    user_warn(!pRamp);
837
 
838
    if (pRamp && (iSwapChain < This->nswapchains)) {
839
        struct NineSwapChain9 *swap = This->swapchains[iSwapChain];
840
        swap->gamma = *pRamp;
841
        ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow);
842
    }
843
}
844
 
845
void WINAPI
846
NineDevice9_GetGammaRamp( struct NineDevice9 *This,
847
                          UINT iSwapChain,
848
                          D3DGAMMARAMP *pRamp )
849
{
850
    DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp);
851
 
852
    user_warn(iSwapChain >= This->nswapchains);
853
    user_warn(!pRamp);
854
 
855
    if (pRamp && (iSwapChain < This->nswapchains))
856
        *pRamp = This->swapchains[iSwapChain]->gamma;
857
}
858
 
859
HRESULT WINAPI
860
NineDevice9_CreateTexture( struct NineDevice9 *This,
861
                           UINT Width,
862
                           UINT Height,
863
                           UINT Levels,
864
                           DWORD Usage,
865
                           D3DFORMAT Format,
866
                           D3DPOOL Pool,
867
                           IDirect3DTexture9 **ppTexture,
868
                           HANDLE *pSharedHandle )
869
{
870
    struct NineTexture9 *tex;
871
    HRESULT hr;
872
 
873
    DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
874
        "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels,
875
        nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
876
        nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle);
877
 
878
    Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP |
879
             D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
880
             D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI;
881
 
882
    *ppTexture = NULL;
883
    user_assert(Width && Height, D3DERR_INVALIDCALL);
884
    user_assert(!pSharedHandle || This->ex, D3DERR_INVALIDCALL);
885
    /* When is used shared handle, Pool must be
886
     * SYSTEMMEM with Levels 1 or DEFAULT with any Levels */
887
    user_assert(!pSharedHandle || Pool != D3DPOOL_SYSTEMMEM || Levels == 1,
888
                D3DERR_INVALIDCALL);
889
    user_assert(!pSharedHandle || Pool == D3DPOOL_SYSTEMMEM || Pool == D3DPOOL_DEFAULT,
890
                D3DERR_INVALIDCALL);
891
    user_assert((Usage != D3DUSAGE_AUTOGENMIPMAP || Levels <= 1), D3DERR_INVALIDCALL);
892
 
893
    hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool,
894
                          &tex, pSharedHandle);
895
    if (SUCCEEDED(hr))
896
        *ppTexture = (IDirect3DTexture9 *)tex;
897
 
898
    return hr;
899
}
900
 
901
HRESULT WINAPI
902
NineDevice9_CreateVolumeTexture( struct NineDevice9 *This,
903
                                 UINT Width,
904
                                 UINT Height,
905
                                 UINT Depth,
906
                                 UINT Levels,
907
                                 DWORD Usage,
908
                                 D3DFORMAT Format,
909
                                 D3DPOOL Pool,
910
                                 IDirect3DVolumeTexture9 **ppVolumeTexture,
911
                                 HANDLE *pSharedHandle )
912
{
913
    struct NineVolumeTexture9 *tex;
914
    HRESULT hr;
915
 
916
    DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
917
        "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels,
918
        nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
919
        nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle);
920
 
921
    Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
922
             D3DUSAGE_SOFTWAREPROCESSING;
923
 
924
    *ppVolumeTexture = NULL;
925
    user_assert(Width && Height && Depth, D3DERR_INVALIDCALL);
926
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
927
 
928
    hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels,
929
                                Usage, Format, Pool, &tex, pSharedHandle);
930
    if (SUCCEEDED(hr))
931
        *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex;
932
 
933
    return hr;
934
}
935
 
936
HRESULT WINAPI
937
NineDevice9_CreateCubeTexture( struct NineDevice9 *This,
938
                               UINT EdgeLength,
939
                               UINT Levels,
940
                               DWORD Usage,
941
                               D3DFORMAT Format,
942
                               D3DPOOL Pool,
943
                               IDirect3DCubeTexture9 **ppCubeTexture,
944
                               HANDLE *pSharedHandle )
945
{
946
    struct NineCubeTexture9 *tex;
947
    HRESULT hr;
948
 
949
    DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
950
        "pSharedHandle=%p\n", This, EdgeLength, Levels,
951
        nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
952
        nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle);
953
 
954
    Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC |
955
             D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
956
             D3DUSAGE_SOFTWAREPROCESSING;
957
 
958
    *ppCubeTexture = NULL;
959
    user_assert(EdgeLength, D3DERR_INVALIDCALL);
960
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
961
 
962
    hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool,
963
                              &tex, pSharedHandle);
964
    if (SUCCEEDED(hr))
965
        *ppCubeTexture = (IDirect3DCubeTexture9 *)tex;
966
 
967
    return hr;
968
}
969
 
970
HRESULT WINAPI
971
NineDevice9_CreateVertexBuffer( struct NineDevice9 *This,
972
                                UINT Length,
973
                                DWORD Usage,
974
                                DWORD FVF,
975
                                D3DPOOL Pool,
976
                                IDirect3DVertexBuffer9 **ppVertexBuffer,
977
                                HANDLE *pSharedHandle )
978
{
979
    struct NineVertexBuffer9 *buf;
980
    HRESULT hr;
981
    D3DVERTEXBUFFER_DESC desc;
982
 
983
    DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
984
        This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
985
 
986
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
987
 
988
    desc.Format = D3DFMT_VERTEXDATA;
989
    desc.Type = D3DRTYPE_VERTEXBUFFER;
990
    desc.Usage = Usage &
991
        (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
992
         D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
993
         D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI |
994
         D3DUSAGE_WRITEONLY);
995
    desc.Pool = Pool;
996
    desc.Size = Length;
997
    desc.FVF = FVF;
998
 
999
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1000
    user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
1001
 
1002
    hr = NineVertexBuffer9_new(This, &desc, &buf);
1003
    if (SUCCEEDED(hr))
1004
        *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf;
1005
    return hr;
1006
}
1007
 
1008
HRESULT WINAPI
1009
NineDevice9_CreateIndexBuffer( struct NineDevice9 *This,
1010
                               UINT Length,
1011
                               DWORD Usage,
1012
                               D3DFORMAT Format,
1013
                               D3DPOOL Pool,
1014
                               IDirect3DIndexBuffer9 **ppIndexBuffer,
1015
                               HANDLE *pSharedHandle )
1016
{
1017
    struct NineIndexBuffer9 *buf;
1018
    HRESULT hr;
1019
    D3DINDEXBUFFER_DESC desc;
1020
 
1021
    DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
1022
        "pSharedHandle=%p\n", This, Length, Usage,
1023
        d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle);
1024
 
1025
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
1026
 
1027
    desc.Format = Format;
1028
    desc.Type = D3DRTYPE_INDEXBUFFER;
1029
    desc.Usage = Usage &
1030
        (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
1031
         D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
1032
         D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY);
1033
    desc.Pool = Pool;
1034
    desc.Size = Length;
1035
 
1036
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1037
    user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
1038
 
1039
    hr = NineIndexBuffer9_new(This, &desc, &buf);
1040
    if (SUCCEEDED(hr))
1041
        *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf;
1042
    return hr;
1043
}
1044
 
1045
static HRESULT
1046
create_zs_or_rt_surface(struct NineDevice9 *This,
1047
                        unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */
1048
                        D3DPOOL Pool,
1049
                        UINT Width, UINT Height,
1050
                        D3DFORMAT Format,
1051
                        D3DMULTISAMPLE_TYPE MultiSample,
1052
                        DWORD MultisampleQuality,
1053
                        BOOL Discard_or_Lockable,
1054
                        IDirect3DSurface9 **ppSurface,
1055
                        HANDLE *pSharedHandle)
1056
{
1057
    struct NineSurface9 *surface;
1058
    struct pipe_screen *screen = This->screen;
1059
    struct pipe_resource *resource = NULL;
1060
    HRESULT hr;
1061
    D3DSURFACE_DESC desc;
1062
    struct pipe_resource templ;
1063
 
1064
    DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
1065
        "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
1066
        This, type, nine_D3DPOOL_to_str(Pool), Width, Height,
1067
        d3dformat_to_string(Format), MultiSample, MultisampleQuality,
1068
        Discard_or_Lockable, ppSurface, pSharedHandle);
1069
 
1070
    if (pSharedHandle)
1071
      DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
1072
 
1073
    user_assert(Width && Height, D3DERR_INVALIDCALL);
1074
    user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
1075
 
1076
    templ.target = PIPE_TEXTURE_2D;
1077
    templ.width0 = Width;
1078
    templ.height0 = Height;
1079
    templ.depth0 = 1;
1080
    templ.array_size = 1;
1081
    templ.last_level = 0;
1082
    templ.nr_samples = (unsigned)MultiSample;
1083
    templ.usage = PIPE_USAGE_DEFAULT;
1084
    templ.flags = 0;
1085
    templ.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
1086
    switch (type) {
1087
    case 0: templ.bind |= PIPE_BIND_RENDER_TARGET; break;
1088
    case 1: templ.bind = d3d9_get_pipe_depth_format_bindings(Format); break;
1089
    default:
1090
        assert(type == 2);
1091
        break;
1092
    }
1093
    templ.format = d3d9_to_pipe_format_checked(screen, Format, templ.target,
1094
                                               templ.nr_samples, templ.bind,
1095
                                               FALSE);
1096
 
1097
    desc.Format = Format;
1098
    desc.Type = D3DRTYPE_SURFACE;
1099
    desc.Usage = 0;
1100
    desc.Pool = Pool;
1101
    desc.MultiSampleType = MultiSample;
1102
    desc.MultiSampleQuality = MultisampleQuality;
1103
    desc.Width = Width;
1104
    desc.Height = Height;
1105
    switch (type) {
1106
    case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break;
1107
    case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break;
1108
    default: break;
1109
    }
1110
 
1111
    if (Pool == D3DPOOL_DEFAULT && Format != D3DFMT_NULL) {
1112
        /* resource_create doesn't return an error code, so check format here */
1113
        user_assert(templ.format != PIPE_FORMAT_NONE, D3DERR_INVALIDCALL);
1114
        resource = screen->resource_create(screen, &templ);
1115
        user_assert(resource, D3DERR_OUTOFVIDEOMEMORY);
1116
        if (Discard_or_Lockable && (desc.Usage & D3DUSAGE_RENDERTARGET))
1117
            resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
1118
    } else {
1119
        resource = NULL;
1120
    }
1121
    hr = NineSurface9_new(This, NULL, resource, NULL, 0, 0, 0, &desc, &surface);
1122
    pipe_resource_reference(&resource, NULL);
1123
 
1124
    if (SUCCEEDED(hr))
1125
        *ppSurface = (IDirect3DSurface9 *)surface;
1126
    return hr;
1127
}
1128
 
1129
HRESULT WINAPI
1130
NineDevice9_CreateRenderTarget( struct NineDevice9 *This,
1131
                                UINT Width,
1132
                                UINT Height,
1133
                                D3DFORMAT Format,
1134
                                D3DMULTISAMPLE_TYPE MultiSample,
1135
                                DWORD MultisampleQuality,
1136
                                BOOL Lockable,
1137
                                IDirect3DSurface9 **ppSurface,
1138
                                HANDLE *pSharedHandle )
1139
{
1140
    *ppSurface = NULL;
1141
    return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT,
1142
                                   Width, Height, Format,
1143
                                   MultiSample, MultisampleQuality,
1144
                                   Lockable, ppSurface, pSharedHandle);
1145
}
1146
 
1147
HRESULT WINAPI
1148
NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,
1149
                                       UINT Width,
1150
                                       UINT Height,
1151
                                       D3DFORMAT Format,
1152
                                       D3DMULTISAMPLE_TYPE MultiSample,
1153
                                       DWORD MultisampleQuality,
1154
                                       BOOL Discard,
1155
                                       IDirect3DSurface9 **ppSurface,
1156
                                       HANDLE *pSharedHandle )
1157
{
1158
    *ppSurface = NULL;
1159
    if (!depth_stencil_format(Format))
1160
        return D3DERR_NOTAVAILABLE;
1161
    return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT,
1162
                                   Width, Height, Format,
1163
                                   MultiSample, MultisampleQuality,
1164
                                   Discard, ppSurface, pSharedHandle);
1165
}
1166
 
1167
HRESULT WINAPI
1168
NineDevice9_UpdateSurface( struct NineDevice9 *This,
1169
                           IDirect3DSurface9 *pSourceSurface,
1170
                           const RECT *pSourceRect,
1171
                           IDirect3DSurface9 *pDestinationSurface,
1172
                           const POINT *pDestPoint )
1173
{
1174
    struct NineSurface9 *dst = NineSurface9(pDestinationSurface);
1175
    struct NineSurface9 *src = NineSurface9(pSourceSurface);
1176
 
1177
    DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
1178
        "pSourceRect=%p pDestPoint=%p\n", This,
1179
        pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint);
1180
    if (pSourceRect)
1181
        DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
1182
            pSourceRect->left, pSourceRect->top,
1183
            pSourceRect->right, pSourceRect->bottom);
1184
    if (pDestPoint)
1185
        DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);
1186
 
1187
    user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1188
    user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1189
 
1190
    user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
1191
    user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
1192
 
1193
    return NineSurface9_CopySurface(dst, src, pDestPoint, pSourceRect);
1194
}
1195
 
1196
HRESULT WINAPI
1197
NineDevice9_UpdateTexture( struct NineDevice9 *This,
1198
                           IDirect3DBaseTexture9 *pSourceTexture,
1199
                           IDirect3DBaseTexture9 *pDestinationTexture )
1200
{
1201
    struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture);
1202
    struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);
1203
    unsigned l, m;
1204
    unsigned last_level = dstb->base.info.last_level;
1205
 
1206
    DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,
1207
        pSourceTexture, pDestinationTexture);
1208
 
1209
    user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL);
1210
 
1211
    user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1212
    user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1213
 
1214
    if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {
1215
        /* Only the first level is updated, the others regenerated. */
1216
        last_level = 0;
1217
        /* if the source has D3DUSAGE_AUTOGENMIPMAP, we have to ignore
1218
         * the sublevels, thus level 0 has to match */
1219
        user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ||
1220
                    (srcb->base.info.width0 == dstb->base.info.width0 &&
1221
                     srcb->base.info.height0 == dstb->base.info.height0 &&
1222
                     srcb->base.info.depth0 == dstb->base.info.depth0),
1223
                    D3DERR_INVALIDCALL);
1224
    } else {
1225
        user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL);
1226
    }
1227
 
1228
    user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);
1229
 
1230
    /* TODO: We can restrict the update to the dirty portions of the source.
1231
     * Yes, this seems silly, but it's what MSDN says ...
1232
     */
1233
 
1234
    /* Find src level that matches dst level 0: */
1235
    user_assert(srcb->base.info.width0 >= dstb->base.info.width0 &&
1236
                srcb->base.info.height0 >= dstb->base.info.height0 &&
1237
                srcb->base.info.depth0 >= dstb->base.info.depth0,
1238
                D3DERR_INVALIDCALL);
1239
    for (m = 0; m <= srcb->base.info.last_level; ++m) {
1240
        unsigned w = u_minify(srcb->base.info.width0, m);
1241
        unsigned h = u_minify(srcb->base.info.height0, m);
1242
        unsigned d = u_minify(srcb->base.info.depth0, m);
1243
 
1244
        if (w == dstb->base.info.width0 &&
1245
            h == dstb->base.info.height0 &&
1246
            d == dstb->base.info.depth0)
1247
            break;
1248
    }
1249
    user_assert(m <= srcb->base.info.last_level, D3DERR_INVALIDCALL);
1250
 
1251
    last_level = MIN2(last_level, srcb->base.info.last_level - m);
1252
 
1253
    if (dstb->base.type == D3DRTYPE_TEXTURE) {
1254
        struct NineTexture9 *dst = NineTexture9(dstb);
1255
        struct NineTexture9 *src = NineTexture9(srcb);
1256
 
1257
        for (l = 0; l <= last_level; ++l, ++m)
1258
            NineSurface9_CopySurface(dst->surfaces[l],
1259
                                     src->surfaces[m], NULL, NULL);
1260
    } else
1261
    if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {
1262
        struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);
1263
        struct NineCubeTexture9 *src = NineCubeTexture9(srcb);
1264
        unsigned z;
1265
 
1266
        /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
1267
        for (z = 0; z < 6; ++z) {
1268
            for (l = 0; l <= last_level; ++l, ++m) {
1269
                NineSurface9_CopySurface(dst->surfaces[l * 6 + z],
1270
                                         src->surfaces[m * 6 + z], NULL, NULL);
1271
            }
1272
            m -= l;
1273
        }
1274
    } else
1275
    if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) {
1276
        struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb);
1277
        struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb);
1278
 
1279
        for (l = 0; l <= last_level; ++l, ++m)
1280
            NineVolume9_CopyVolume(dst->volumes[l],
1281
                                   src->volumes[m], 0, 0, 0, NULL);
1282
    } else{
1283
        assert(!"invalid texture type");
1284
    }
1285
 
1286
    if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {
1287
        dstb->dirty_mip = TRUE;
1288
        NineBaseTexture9_GenerateMipSubLevels(dstb);
1289
    }
1290
 
1291
    return D3D_OK;
1292
}
1293
 
1294
HRESULT WINAPI
1295
NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
1296
                                 IDirect3DSurface9 *pRenderTarget,
1297
                                 IDirect3DSurface9 *pDestSurface )
1298
{
1299
    struct NineSurface9 *dst = NineSurface9(pDestSurface);
1300
    struct NineSurface9 *src = NineSurface9(pRenderTarget);
1301
 
1302
    DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
1303
        This, pRenderTarget, pDestSurface);
1304
 
1305
    user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1306
    user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1307
 
1308
    user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
1309
    user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
1310
 
1311
    return NineSurface9_CopySurface(dst, src, NULL, NULL);
1312
}
1313
 
1314
HRESULT WINAPI
1315
NineDevice9_GetFrontBufferData( struct NineDevice9 *This,
1316
                                UINT iSwapChain,
1317
                                IDirect3DSurface9 *pDestSurface )
1318
{
1319
    DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This,
1320
        iSwapChain, pDestSurface);
1321
 
1322
    user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL);
1323
    user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
1324
 
1325
    return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain],
1326
                                             pDestSurface);
1327
}
1328
 
1329
HRESULT WINAPI
1330
NineDevice9_StretchRect( struct NineDevice9 *This,
1331
                         IDirect3DSurface9 *pSourceSurface,
1332
                         const RECT *pSourceRect,
1333
                         IDirect3DSurface9 *pDestSurface,
1334
                         const RECT *pDestRect,
1335
                         D3DTEXTUREFILTERTYPE Filter )
1336
{
1337
    struct pipe_screen *screen = This->screen;
1338
    struct pipe_context *pipe = This->pipe;
1339
    struct NineSurface9 *dst = NineSurface9(pDestSurface);
1340
    struct NineSurface9 *src = NineSurface9(pSourceSurface);
1341
    struct pipe_resource *dst_res = NineSurface9_GetResource(dst);
1342
    struct pipe_resource *src_res = NineSurface9_GetResource(src);
1343
    const boolean zs = util_format_is_depth_or_stencil(dst_res->format);
1344
    struct pipe_blit_info blit;
1345
    boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE;
1346
 
1347
    DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
1348
        "pDestRect=%p Filter=%u\n",
1349
        This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
1350
    if (pSourceRect)
1351
        DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
1352
            pSourceRect->left, pSourceRect->top,
1353
            pSourceRect->right, pSourceRect->bottom);
1354
    if (pDestRect)
1355
        DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top,
1356
            pDestRect->right, pDestRect->bottom);
1357
 
1358
    user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL);
1359
    user_assert(!zs || !pSourceRect ||
1360
                (pSourceRect->left == 0 &&
1361
                 pSourceRect->top == 0 &&
1362
                 pSourceRect->right == src->desc.Width &&
1363
                 pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL);
1364
    user_assert(!zs || !pDestRect ||
1365
                (pDestRect->left == 0 &&
1366
                 pDestRect->top == 0 &&
1367
                 pDestRect->right == dst->desc.Width &&
1368
                 pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL);
1369
    user_assert(!zs ||
1370
                (dst->desc.Width == src->desc.Width &&
1371
                 dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL);
1372
    user_assert(zs || !util_format_is_depth_or_stencil(src_res->format),
1373
                D3DERR_INVALIDCALL);
1374
    user_assert(!zs || dst->desc.Format == src->desc.Format,
1375
                D3DERR_INVALIDCALL);
1376
    user_assert(screen->is_format_supported(screen, src_res->format,
1377
                                            src_res->target,
1378
                                            src_res->nr_samples,
1379
                                            PIPE_BIND_SAMPLER_VIEW),
1380
                D3DERR_INVALIDCALL);
1381
    user_assert(dst->base.pool == D3DPOOL_DEFAULT &&
1382
                src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1383
 
1384
    /* We might want to permit these, but wine thinks we shouldn't. */
1385
    user_assert(!pDestRect ||
1386
                (pDestRect->left <= pDestRect->right &&
1387
                 pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL);
1388
    user_assert(!pSourceRect ||
1389
                (pSourceRect->left <= pSourceRect->right &&
1390
                 pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL);
1391
 
1392
    memset(&blit, 0, sizeof(blit));
1393
    blit.dst.resource = dst_res;
1394
    blit.dst.level = dst->level;
1395
    blit.dst.box.z = dst->layer;
1396
    blit.dst.box.depth = 1;
1397
    blit.dst.format = dst_res->format;
1398
    if (pDestRect) {
1399
        flip_x = pDestRect->left > pDestRect->right;
1400
        if (flip_x) {
1401
            blit.dst.box.x = pDestRect->right;
1402
            blit.dst.box.width = pDestRect->left - pDestRect->right;
1403
        } else {
1404
            blit.dst.box.x = pDestRect->left;
1405
            blit.dst.box.width = pDestRect->right - pDestRect->left;
1406
        }
1407
        flip_y = pDestRect->top > pDestRect->bottom;
1408
        if (flip_y) {
1409
            blit.dst.box.y = pDestRect->bottom;
1410
            blit.dst.box.height = pDestRect->top - pDestRect->bottom;
1411
        } else {
1412
            blit.dst.box.y = pDestRect->top;
1413
            blit.dst.box.height = pDestRect->bottom - pDestRect->top;
1414
        }
1415
    } else {
1416
        blit.dst.box.x = 0;
1417
        blit.dst.box.y = 0;
1418
        blit.dst.box.width = dst->desc.Width;
1419
        blit.dst.box.height = dst->desc.Height;
1420
    }
1421
    blit.src.resource = src_res;
1422
    blit.src.level = src->level;
1423
    blit.src.box.z = src->layer;
1424
    blit.src.box.depth = 1;
1425
    blit.src.format = src_res->format;
1426
    if (pSourceRect) {
1427
        if (flip_x ^ (pSourceRect->left > pSourceRect->right)) {
1428
            blit.src.box.x = pSourceRect->right;
1429
            blit.src.box.width = pSourceRect->left - pSourceRect->right;
1430
        } else {
1431
            blit.src.box.x = pSourceRect->left;
1432
            blit.src.box.width = pSourceRect->right - pSourceRect->left;
1433
        }
1434
        if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) {
1435
            blit.src.box.y = pSourceRect->bottom;
1436
            blit.src.box.height = pSourceRect->top - pSourceRect->bottom;
1437
        } else {
1438
            blit.src.box.y = pSourceRect->top;
1439
            blit.src.box.height = pSourceRect->bottom - pSourceRect->top;
1440
        }
1441
    } else {
1442
        blit.src.box.x = flip_x ? src->desc.Width : 0;
1443
        blit.src.box.y = flip_y ? src->desc.Height : 0;
1444
        blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width;
1445
        blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height;
1446
    }
1447
    blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA;
1448
    blit.filter = Filter == D3DTEXF_LINEAR ?
1449
       PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
1450
    blit.scissor_enable = FALSE;
1451
 
1452
    /* If both of a src and dst dimension are negative, flip them. */
1453
    if (blit.dst.box.width < 0 && blit.src.box.width < 0) {
1454
        blit.dst.box.width = -blit.dst.box.width;
1455
        blit.src.box.width = -blit.src.box.width;
1456
    }
1457
    if (blit.dst.box.height < 0 && blit.src.box.height < 0) {
1458
        blit.dst.box.height = -blit.dst.box.height;
1459
        blit.src.box.height = -blit.src.box.height;
1460
    }
1461
    scaled =
1462
        blit.dst.box.width != blit.src.box.width ||
1463
        blit.dst.box.height != blit.src.box.height;
1464
 
1465
    user_assert(!scaled || dst != src, D3DERR_INVALIDCALL);
1466
    user_assert(!scaled ||
1467
                !NineSurface9_IsOffscreenPlain(dst) ||
1468
                NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL);
1469
    user_assert(!scaled ||
1470
                (!util_format_is_compressed(dst->base.info.format) &&
1471
                 !util_format_is_compressed(src->base.info.format)),
1472
                D3DERR_INVALIDCALL);
1473
 
1474
    user_warn(src == dst &&
1475
              u_box_test_intersection_2d(&blit.src.box, &blit.dst.box));
1476
 
1477
    /* Check for clipping/clamping: */
1478
    {
1479
        struct pipe_box box;
1480
        int xy;
1481
 
1482
        xy = u_box_clip_2d(&box, &blit.dst.box,
1483
                           dst->desc.Width, dst->desc.Height);
1484
        if (xy < 0)
1485
            return D3D_OK;
1486
        if (xy == 0)
1487
            xy = u_box_clip_2d(&box, &blit.src.box,
1488
                               src->desc.Width, src->desc.Height);
1489
        clamped = !!xy;
1490
    }
1491
 
1492
    ms = (dst->desc.MultiSampleType | 1) != (src->desc.MultiSampleType | 1);
1493
 
1494
    if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) {
1495
        DBG("using pipe->blit()\n");
1496
        /* TODO: software scaling */
1497
        user_assert(screen->is_format_supported(screen, dst_res->format,
1498
                                                dst_res->target,
1499
                                                dst_res->nr_samples,
1500
                                                zs ? PIPE_BIND_DEPTH_STENCIL :
1501
                                                PIPE_BIND_RENDER_TARGET),
1502
                    D3DERR_INVALIDCALL);
1503
 
1504
        pipe->blit(pipe, &blit);
1505
    } else {
1506
        assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 &&
1507
               blit.src.box.x >= 0 && blit.src.box.y >= 0 &&
1508
               blit.dst.box.x + blit.dst.box.width <= dst->desc.Width &&
1509
               blit.src.box.x + blit.src.box.width <= src->desc.Width &&
1510
               blit.dst.box.y + blit.dst.box.height <= dst->desc.Height &&
1511
               blit.src.box.y + blit.src.box.height <= src->desc.Height);
1512
        /* Or drivers might crash ... */
1513
        DBG("Using resource_copy_region.\n");
1514
        pipe->resource_copy_region(pipe,
1515
            blit.dst.resource, blit.dst.level,
1516
            blit.dst.box.x, blit.dst.box.y, blit.dst.box.z,
1517
            blit.src.resource, blit.src.level,
1518
            &blit.src.box);
1519
    }
1520
 
1521
    /* Communicate the container it needs to update sublevels - if apply */
1522
    NineSurface9_MarkContainerDirty(dst);
1523
 
1524
    return D3D_OK;
1525
}
1526
 
1527
HRESULT WINAPI
1528
NineDevice9_ColorFill( struct NineDevice9 *This,
1529
                       IDirect3DSurface9 *pSurface,
1530
                       const RECT *pRect,
1531
                       D3DCOLOR color )
1532
{
1533
    struct pipe_context *pipe = This->pipe;
1534
    struct NineSurface9 *surf = NineSurface9(pSurface);
1535
    struct pipe_surface *psurf;
1536
    unsigned x, y, w, h;
1537
    union pipe_color_union rgba;
1538
    boolean fallback;
1539
 
1540
    DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This,
1541
        pSurface, pRect, color);
1542
    if (pRect)
1543
        DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top,
1544
            pRect->right, pRect->bottom);
1545
 
1546
    user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1547
 
1548
    user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) ||
1549
                NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL);
1550
 
1551
    if (pRect) {
1552
        x = pRect->left;
1553
        y = pRect->top;
1554
        w = pRect->right - pRect->left;
1555
        h = pRect->bottom - pRect->top;
1556
    } else{
1557
        x = 0;
1558
        y = 0;
1559
        w = surf->desc.Width;
1560
        h = surf->desc.Height;
1561
    }
1562
    d3dcolor_to_pipe_color_union(&rgba, color);
1563
 
1564
    fallback =
1565
        !This->screen->is_format_supported(This->screen, surf->base.info.format,
1566
                                           surf->base.info.target,
1567
                                           surf->base.info.nr_samples,
1568
                                           PIPE_BIND_RENDER_TARGET);
1569
    if (!fallback) {
1570
        psurf = NineSurface9_GetSurface(surf, 0);
1571
        if (!psurf)
1572
            fallback = TRUE;
1573
    }
1574
 
1575
    if (!fallback) {
1576
        pipe->clear_render_target(pipe, psurf, &rgba, x, y, w, h);
1577
    } else {
1578
        D3DLOCKED_RECT lock;
1579
        union util_color uc;
1580
        HRESULT hr;
1581
        /* XXX: lock pRect and fix util_fill_rect */
1582
        hr = NineSurface9_LockRect(surf, &lock, NULL, 0);
1583
        if (FAILED(hr))
1584
            return hr;
1585
        util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24,
1586
                           surf->base.info.format, &uc);
1587
        util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch,
1588
                       x, y, w, h, &uc);
1589
        NineSurface9_UnlockRect(surf);
1590
    }
1591
 
1592
    return D3D_OK;
1593
}
1594
 
1595
HRESULT WINAPI
1596
NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,
1597
                                         UINT Width,
1598
                                         UINT Height,
1599
                                         D3DFORMAT Format,
1600
                                         D3DPOOL Pool,
1601
                                         IDirect3DSurface9 **ppSurface,
1602
                                         HANDLE *pSharedHandle )
1603
{
1604
    HRESULT hr;
1605
 
1606
    DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
1607
        "ppSurface=%p pSharedHandle=%p\n", This,
1608
        Width, Height, d3dformat_to_string(Format), Format, Pool,
1609
        ppSurface, pSharedHandle);
1610
 
1611
    *ppSurface = NULL;
1612
    user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT
1613
                               || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1614
    user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
1615
 
1616
    /* Can be used with StretchRect and ColorFill. It's also always lockable.
1617
     */
1618
    hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height,
1619
                                 Format,
1620
                                 D3DMULTISAMPLE_NONE, 0,
1621
                                 TRUE,
1622
                                 ppSurface, pSharedHandle);
1623
    if (FAILED(hr))
1624
        DBG("Failed to create surface.\n");
1625
    return hr;
1626
}
1627
 
1628
HRESULT WINAPI
1629
NineDevice9_SetRenderTarget( struct NineDevice9 *This,
1630
                             DWORD RenderTargetIndex,
1631
                             IDirect3DSurface9 *pRenderTarget )
1632
{
1633
    struct NineSurface9 *rt = NineSurface9(pRenderTarget);
1634
    const unsigned i = RenderTargetIndex;
1635
 
1636
    DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This,
1637
        RenderTargetIndex, pRenderTarget);
1638
 
1639
    user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
1640
    user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL);
1641
    user_assert(!pRenderTarget ||
1642
                rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL);
1643
 
1644
    if (i == 0) {
1645
        This->state.viewport.X = 0;
1646
        This->state.viewport.Y = 0;
1647
        This->state.viewport.Width = rt->desc.Width;
1648
        This->state.viewport.Height = rt->desc.Height;
1649
        This->state.viewport.MinZ = 0.0f;
1650
        This->state.viewport.MaxZ = 1.0f;
1651
 
1652
        This->state.scissor.minx = 0;
1653
        This->state.scissor.miny = 0;
1654
        This->state.scissor.maxx = rt->desc.Width;
1655
        This->state.scissor.maxy = rt->desc.Height;
1656
 
1657
        This->state.changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR;
1658
    }
1659
 
1660
    if (This->state.rt[i] != NineSurface9(pRenderTarget)) {
1661
       nine_bind(&This->state.rt[i], pRenderTarget);
1662
       This->state.changed.group |= NINE_STATE_FB;
1663
    }
1664
    return D3D_OK;
1665
}
1666
 
1667
HRESULT WINAPI
1668
NineDevice9_GetRenderTarget( struct NineDevice9 *This,
1669
                             DWORD RenderTargetIndex,
1670
                             IDirect3DSurface9 **ppRenderTarget )
1671
{
1672
    const unsigned i = RenderTargetIndex;
1673
 
1674
    user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
1675
    user_assert(ppRenderTarget, D3DERR_INVALIDCALL);
1676
 
1677
    *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i];
1678
    if (!This->state.rt[i])
1679
        return D3DERR_NOTFOUND;
1680
 
1681
    NineUnknown_AddRef(NineUnknown(This->state.rt[i]));
1682
    return D3D_OK;
1683
}
1684
 
1685
HRESULT WINAPI
1686
NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This,
1687
                                    IDirect3DSurface9 *pNewZStencil )
1688
{
1689
    DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil);
1690
 
1691
    if (This->state.ds != NineSurface9(pNewZStencil)) {
1692
        nine_bind(&This->state.ds, pNewZStencil);
1693
        This->state.changed.group |= NINE_STATE_FB;
1694
    }
1695
    return D3D_OK;
1696
}
1697
 
1698
HRESULT WINAPI
1699
NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This,
1700
                                    IDirect3DSurface9 **ppZStencilSurface )
1701
{
1702
    user_assert(ppZStencilSurface, D3DERR_INVALIDCALL);
1703
 
1704
    *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds;
1705
    if (!This->state.ds)
1706
        return D3DERR_NOTFOUND;
1707
 
1708
    NineUnknown_AddRef(NineUnknown(This->state.ds));
1709
    return D3D_OK;
1710
}
1711
 
1712
HRESULT WINAPI
1713
NineDevice9_BeginScene( struct NineDevice9 *This )
1714
{
1715
    DBG("This=%p\n", This);
1716
    user_assert(!This->in_scene, D3DERR_INVALIDCALL);
1717
    This->in_scene = TRUE;
1718
    /* Do we want to do anything else here ? */
1719
    return D3D_OK;
1720
}
1721
 
1722
HRESULT WINAPI
1723
NineDevice9_EndScene( struct NineDevice9 *This )
1724
{
1725
    DBG("This=%p\n", This);
1726
    user_assert(This->in_scene, D3DERR_INVALIDCALL);
1727
    This->in_scene = FALSE;
1728
    return D3D_OK;
1729
}
1730
 
1731
HRESULT WINAPI
1732
NineDevice9_Clear( struct NineDevice9 *This,
1733
                   DWORD Count,
1734
                   const D3DRECT *pRects,
1735
                   DWORD Flags,
1736
                   D3DCOLOR Color,
1737
                   float Z,
1738
                   DWORD Stencil )
1739
{
1740
    const int sRGB = This->state.rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
1741
    struct pipe_surface *cbuf, *zsbuf;
1742
    struct pipe_context *pipe = This->pipe;
1743
    struct NineSurface9 *zsbuf_surf = This->state.ds;
1744
    struct NineSurface9 *rt;
1745
    unsigned bufs = 0;
1746
    unsigned r, i;
1747
    union pipe_color_union rgba;
1748
    unsigned rt_mask = 0;
1749
    D3DRECT rect;
1750
 
1751
    DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
1752
        This, Count, pRects, Flags, Color, Z, Stencil);
1753
 
1754
    user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL),
1755
                D3DERR_INVALIDCALL);
1756
    user_assert(!(Flags & D3DCLEAR_STENCIL) ||
1757
                (zsbuf_surf &&
1758
                 util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)),
1759
                D3DERR_INVALIDCALL);
1760
#ifdef NINE_STRICT
1761
    user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL);
1762
#else
1763
    user_warn((pRects && !Count) || (!pRects && Count));
1764
    if (pRects && !Count)
1765
        return D3D_OK;
1766
    if (!pRects)
1767
        Count = 0;
1768
#endif
1769
 
1770
    if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR;
1771
    if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH;
1772
    if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL;
1773
    if (!bufs)
1774
        return D3D_OK;
1775
    d3dcolor_to_pipe_color_union(&rgba, Color);
1776
 
1777
    nine_update_state(This, NINE_STATE_FB);
1778
 
1779
    rect.x1 = This->state.viewport.X;
1780
    rect.y1 = This->state.viewport.Y;
1781
    rect.x2 = This->state.viewport.Width + rect.x1;
1782
    rect.y2 = This->state.viewport.Height + rect.y1;
1783
 
1784
    /* Both rectangles apply, which is weird, but that's D3D9. */
1785
    if (This->state.rs[D3DRS_SCISSORTESTENABLE]) {
1786
        rect.x1 = MAX2(rect.x1, This->state.scissor.minx);
1787
        rect.y1 = MAX2(rect.y1, This->state.scissor.miny);
1788
        rect.x2 = MIN2(rect.x2, This->state.scissor.maxx);
1789
        rect.y2 = MIN2(rect.y2, This->state.scissor.maxy);
1790
    }
1791
 
1792
    if (Count) {
1793
        /* Maybe apps like to specify a large rect ? */
1794
        if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 &&
1795
            pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) {
1796
            DBG("First rect covers viewport.\n");
1797
            Count = 0;
1798
            pRects = NULL;
1799
        }
1800
    }
1801
 
1802
    if (rect.x1 >= This->state.fb.width || rect.y1 >= This->state.fb.height)
1803
        return D3D_OK;
1804
 
1805
    for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
1806
        if (This->state.rt[i] && This->state.rt[i]->desc.Format != D3DFMT_NULL)
1807
            rt_mask |= 1 << i;
1808
    }
1809
 
1810
    /* fast path, clears everything at once */
1811
    if (!Count &&
1812
        (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == This->state.rt_mask)) &&
1813
        rect.x1 == 0 && rect.y1 == 0 &&
1814
        /* Case we clear only render target. Check clear region vs rt. */
1815
        ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
1816
         rect.x2 >= This->state.fb.width &&
1817
         rect.y2 >= This->state.fb.height) ||
1818
        /* Case we clear depth buffer (and eventually rt too).
1819
         * depth buffer size is always >= rt size. Compare to clear region */
1820
        ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
1821
         This->state.fb.zsbuf != NULL &&
1822
         rect.x2 >= zsbuf_surf->desc.Width &&
1823
         rect.y2 >= zsbuf_surf->desc.Height))) {
1824
        DBG("Clear fast path\n");
1825
        pipe->clear(pipe, bufs, &rgba, Z, Stencil);
1826
        return D3D_OK;
1827
    }
1828
 
1829
    if (!Count) {
1830
        Count = 1;
1831
        pRects = ▭
1832
    }
1833
 
1834
    for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
1835
        rt = This->state.rt[i];
1836
        if (!rt || rt->desc.Format == D3DFMT_NULL ||
1837
            !(Flags & D3DCLEAR_TARGET))
1838
            continue; /* save space, compiler should hoist this */
1839
        cbuf = NineSurface9_GetSurface(rt, sRGB);
1840
        for (r = 0; r < Count; ++r) {
1841
            /* Don't trust users to pass these in the right order. */
1842
            unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
1843
            unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
1844
            unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
1845
            unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
1846
#ifndef NINE_LAX
1847
            /* Drop negative rectangles (like wine expects). */
1848
            if (pRects[r].x1 > pRects[r].x2) continue;
1849
            if (pRects[r].y1 > pRects[r].y2) continue;
1850
#endif
1851
 
1852
            x1 = MAX2(x1, rect.x1);
1853
            y1 = MAX2(y1, rect.y1);
1854
            x2 = MIN3(x2, rect.x2, rt->desc.Width);
1855
            y2 = MIN3(y2, rect.y2, rt->desc.Height);
1856
 
1857
            DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2);
1858
            pipe->clear_render_target(pipe, cbuf, &rgba,
1859
                                      x1, y1, x2 - x1, y2 - y1);
1860
        }
1861
    }
1862
    if (!(Flags & NINED3DCLEAR_DEPTHSTENCIL))
1863
        return D3D_OK;
1864
 
1865
    bufs &= PIPE_CLEAR_DEPTHSTENCIL;
1866
 
1867
    for (r = 0; r < Count; ++r) {
1868
        unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
1869
        unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
1870
        unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
1871
        unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
1872
#ifndef NINE_LAX
1873
        /* Drop negative rectangles. */
1874
        if (pRects[r].x1 > pRects[r].x2) continue;
1875
        if (pRects[r].y1 > pRects[r].y2) continue;
1876
#endif
1877
 
1878
        x1 = MIN2(x1, rect.x1);
1879
        y1 = MIN2(y1, rect.y1);
1880
        x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width);
1881
        y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height);
1882
 
1883
        zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0);
1884
        assert(zsbuf);
1885
        pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil,
1886
                                  x1, y1, x2 - x1, y2 - y1);
1887
    }
1888
    return D3D_OK;
1889
}
1890
 
1891
HRESULT WINAPI
1892
NineDevice9_SetTransform( struct NineDevice9 *This,
1893
                          D3DTRANSFORMSTATETYPE State,
1894
                          const D3DMATRIX *pMatrix )
1895
{
1896
    struct nine_state *state = This->update;
1897
    D3DMATRIX *M = nine_state_access_transform(state, State, TRUE);
1898
 
1899
    DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix);
1900
 
1901
    user_assert(M, D3DERR_INVALIDCALL);
1902
 
1903
    *M = *pMatrix;
1904
    state->ff.changed.transform[State / 32] |= 1 << (State % 32);
1905
    state->changed.group |= NINE_STATE_FF;
1906
 
1907
    return D3D_OK;
1908
}
1909
 
1910
HRESULT WINAPI
1911
NineDevice9_GetTransform( struct NineDevice9 *This,
1912
                          D3DTRANSFORMSTATETYPE State,
1913
                          D3DMATRIX *pMatrix )
1914
{
1915
    D3DMATRIX *M = nine_state_access_transform(&This->state, State, FALSE);
1916
    user_assert(M, D3DERR_INVALIDCALL);
1917
    *pMatrix = *M;
1918
    return D3D_OK;
1919
}
1920
 
1921
HRESULT WINAPI
1922
NineDevice9_MultiplyTransform( struct NineDevice9 *This,
1923
                               D3DTRANSFORMSTATETYPE State,
1924
                               const D3DMATRIX *pMatrix )
1925
{
1926
    struct nine_state *state = This->update;
1927
    D3DMATRIX T;
1928
    D3DMATRIX *M = nine_state_access_transform(state, State, TRUE);
1929
 
1930
    DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix);
1931
 
1932
    user_assert(M, D3DERR_INVALIDCALL);
1933
 
1934
    nine_d3d_matrix_matrix_mul(&T, pMatrix, M);
1935
    return NineDevice9_SetTransform(This, State, &T);
1936
}
1937
 
1938
HRESULT WINAPI
1939
NineDevice9_SetViewport( struct NineDevice9 *This,
1940
                         const D3DVIEWPORT9 *pViewport )
1941
{
1942
    struct nine_state *state = This->update;
1943
 
1944
    DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
1945
        pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height,
1946
        pViewport->MinZ, pViewport->MaxZ);
1947
 
1948
    state->viewport = *pViewport;
1949
    state->changed.group |= NINE_STATE_VIEWPORT;
1950
 
1951
    return D3D_OK;
1952
}
1953
 
1954
HRESULT WINAPI
1955
NineDevice9_GetViewport( struct NineDevice9 *This,
1956
                         D3DVIEWPORT9 *pViewport )
1957
{
1958
    *pViewport = This->state.viewport;
1959
    return D3D_OK;
1960
}
1961
 
1962
HRESULT WINAPI
1963
NineDevice9_SetMaterial( struct NineDevice9 *This,
1964
                         const D3DMATERIAL9 *pMaterial )
1965
{
1966
    struct nine_state *state = This->update;
1967
 
1968
    DBG("This=%p pMaterial=%p\n", This, pMaterial);
1969
    if (pMaterial)
1970
        nine_dump_D3DMATERIAL9(DBG_FF, pMaterial);
1971
 
1972
    user_assert(pMaterial, E_POINTER);
1973
 
1974
    state->ff.material = *pMaterial;
1975
    state->changed.group |= NINE_STATE_FF_MATERIAL;
1976
 
1977
    return D3D_OK;
1978
}
1979
 
1980
HRESULT WINAPI
1981
NineDevice9_GetMaterial( struct NineDevice9 *This,
1982
                         D3DMATERIAL9 *pMaterial )
1983
{
1984
    user_assert(pMaterial, E_POINTER);
1985
    *pMaterial = This->state.ff.material;
1986
    return D3D_OK;
1987
}
1988
 
1989
HRESULT WINAPI
1990
NineDevice9_SetLight( struct NineDevice9 *This,
1991
                      DWORD Index,
1992
                      const D3DLIGHT9 *pLight )
1993
{
1994
    struct nine_state *state = This->update;
1995
 
1996
    DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight);
1997
    if (pLight)
1998
        nine_dump_D3DLIGHT9(DBG_FF, pLight);
1999
 
2000
    user_assert(pLight, D3DERR_INVALIDCALL);
2001
    user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL);
2002
 
2003
    user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */
2004
 
2005
    if (Index >= state->ff.num_lights) {
2006
        unsigned n = state->ff.num_lights;
2007
        unsigned N = Index + 1;
2008
 
2009
        state->ff.light = REALLOC(state->ff.light, n * sizeof(D3DLIGHT9),
2010
                                                   N * sizeof(D3DLIGHT9));
2011
        if (!state->ff.light)
2012
            return E_OUTOFMEMORY;
2013
        state->ff.num_lights = N;
2014
 
2015
        for (; n < Index; ++n)
2016
            state->ff.light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID;
2017
    }
2018
    state->ff.light[Index] = *pLight;
2019
 
2020
    if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) {
2021
        DBG("Warning: clamping D3DLIGHT9.Theta\n");
2022
        state->ff.light[Index].Theta = state->ff.light[Index].Phi;
2023
    }
2024
    if (pLight->Type != D3DLIGHT_DIRECTIONAL &&
2025
        pLight->Attenuation0 == 0.0f &&
2026
        pLight->Attenuation1 == 0.0f &&
2027
        pLight->Attenuation2 == 0.0f) {
2028
        DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
2029
    }
2030
 
2031
    state->changed.group |= NINE_STATE_FF_LIGHTING;
2032
 
2033
    return D3D_OK;
2034
}
2035
 
2036
HRESULT WINAPI
2037
NineDevice9_GetLight( struct NineDevice9 *This,
2038
                      DWORD Index,
2039
                      D3DLIGHT9 *pLight )
2040
{
2041
    const struct nine_state *state = &This->state;
2042
 
2043
    user_assert(pLight, D3DERR_INVALIDCALL);
2044
    user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
2045
    user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
2046
                D3DERR_INVALIDCALL);
2047
 
2048
    *pLight = state->ff.light[Index];
2049
 
2050
    return D3D_OK;
2051
}
2052
 
2053
HRESULT WINAPI
2054
NineDevice9_LightEnable( struct NineDevice9 *This,
2055
                         DWORD Index,
2056
                         BOOL Enable )
2057
{
2058
    struct nine_state *state = This->update;
2059
    unsigned i;
2060
 
2061
    DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable);
2062
 
2063
    if (Index >= state->ff.num_lights ||
2064
        state->ff.light[Index].Type == NINED3DLIGHT_INVALID) {
2065
        /* This should create a default light. */
2066
        D3DLIGHT9 light;
2067
        memset(&light, 0, sizeof(light));
2068
        light.Type = D3DLIGHT_DIRECTIONAL;
2069
        light.Diffuse.r = 1.0f;
2070
        light.Diffuse.g = 1.0f;
2071
        light.Diffuse.b = 1.0f;
2072
        light.Direction.z = 1.0f;
2073
        NineDevice9_SetLight(This, Index, &light);
2074
    }
2075
    user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
2076
 
2077
    for (i = 0; i < state->ff.num_lights_active; ++i) {
2078
        if (state->ff.active_light[i] == Index)
2079
            break;
2080
    }
2081
 
2082
    if (Enable) {
2083
        if (i < state->ff.num_lights_active)
2084
            return D3D_OK;
2085
        /* XXX wine thinks this should still succeed:
2086
         */
2087
        user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL);
2088
 
2089
        state->ff.active_light[i] = Index;
2090
        state->ff.num_lights_active++;
2091
    } else {
2092
        if (i == state->ff.num_lights_active)
2093
            return D3D_OK;
2094
        --state->ff.num_lights_active;
2095
        for (; i < state->ff.num_lights_active; ++i)
2096
            state->ff.active_light[i] = state->ff.active_light[i + 1];
2097
    }
2098
    state->changed.group |= NINE_STATE_FF_LIGHTING;
2099
 
2100
    return D3D_OK;
2101
}
2102
 
2103
HRESULT WINAPI
2104
NineDevice9_GetLightEnable( struct NineDevice9 *This,
2105
                            DWORD Index,
2106
                            BOOL *pEnable )
2107
{
2108
    const struct nine_state *state = &This->state;
2109
    unsigned i;
2110
 
2111
    user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
2112
    user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
2113
                D3DERR_INVALIDCALL);
2114
 
2115
    for (i = 0; i < state->ff.num_lights_active; ++i)
2116
        if (state->ff.active_light[i] == Index)
2117
            break;
2118
 
2119
    *pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine
2120
 
2121
    return D3D_OK;
2122
}
2123
 
2124
HRESULT WINAPI
2125
NineDevice9_SetClipPlane( struct NineDevice9 *This,
2126
                          DWORD Index,
2127
                          const float *pPlane )
2128
{
2129
    struct nine_state *state = This->update;
2130
 
2131
    user_assert(pPlane, D3DERR_INVALIDCALL);
2132
 
2133
    DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index,
2134
        pPlane[0], pPlane[1],
2135
        pPlane[2], pPlane[3]);
2136
 
2137
    user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
2138
 
2139
    memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0]));
2140
    state->changed.ucp |= 1 << Index;
2141
 
2142
    return D3D_OK;
2143
}
2144
 
2145
HRESULT WINAPI
2146
NineDevice9_GetClipPlane( struct NineDevice9 *This,
2147
                          DWORD Index,
2148
                          float *pPlane )
2149
{
2150
    const struct nine_state *state = &This->state;
2151
 
2152
    user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
2153
 
2154
    memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0]));
2155
    return D3D_OK;
2156
}
2157
 
2158
#define RESZ_CODE 0x7fa05000
2159
 
2160
static HRESULT
2161
NineDevice9_ResolveZ( struct NineDevice9 *This )
2162
{
2163
    struct nine_state *state = &This->state;
2164
    const struct util_format_description *desc;
2165
    struct NineSurface9 *source = state->ds;
2166
    struct NineBaseTexture9 *destination = state->texture[0];
2167
    struct pipe_resource *src, *dst;
2168
    struct pipe_blit_info blit;
2169
 
2170
    DBG("RESZ resolve\n");
2171
 
2172
    user_assert(source && destination &&
2173
                destination->base.type == D3DRTYPE_TEXTURE, D3DERR_INVALIDCALL);
2174
 
2175
    src = source->base.resource;
2176
    dst = destination->base.resource;
2177
 
2178
    user_assert(src && dst, D3DERR_INVALIDCALL);
2179
 
2180
    /* check dst is depth format. we know already for src */
2181
    desc = util_format_description(dst->format);
2182
    user_assert(desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS, D3DERR_INVALIDCALL);
2183
 
2184
    memset(&blit, 0, sizeof(blit));
2185
    blit.src.resource = src;
2186
    blit.src.level = 0;
2187
    blit.src.format = src->format;
2188
    blit.src.box.z = 0;
2189
    blit.src.box.depth = 1;
2190
    blit.src.box.x = 0;
2191
    blit.src.box.y = 0;
2192
    blit.src.box.width = src->width0;
2193
    blit.src.box.height = src->height0;
2194
 
2195
    blit.dst.resource = dst;
2196
    blit.dst.level = 0;
2197
    blit.dst.format = dst->format;
2198
    blit.dst.box.z = 0;
2199
    blit.dst.box.depth = 1;
2200
    blit.dst.box.x = 0;
2201
    blit.dst.box.y = 0;
2202
    blit.dst.box.width = dst->width0;
2203
    blit.dst.box.height = dst->height0;
2204
 
2205
    blit.mask = PIPE_MASK_ZS;
2206
    blit.filter = PIPE_TEX_FILTER_NEAREST;
2207
    blit.scissor_enable = FALSE;
2208
 
2209
    This->pipe->blit(This->pipe, &blit);
2210
    return D3D_OK;
2211
}
2212
 
2213
#define ALPHA_TO_COVERAGE_ENABLE   MAKEFOURCC('A', '2', 'M', '1')
2214
#define ALPHA_TO_COVERAGE_DISABLE  MAKEFOURCC('A', '2', 'M', '0')
2215
 
2216
HRESULT WINAPI
2217
NineDevice9_SetRenderState( struct NineDevice9 *This,
2218
                            D3DRENDERSTATETYPE State,
2219
                            DWORD Value )
2220
{
2221
    struct nine_state *state = This->update;
2222
 
2223
    DBG("This=%p State=%u(%s) Value=%08x\n", This,
2224
        State, nine_d3drs_to_string(State), Value);
2225
 
2226
    /* Amd hacks (equivalent to GL extensions) */
2227
    if (State == D3DRS_POINTSIZE) {
2228
        if (Value == RESZ_CODE)
2229
            return NineDevice9_ResolveZ(This);
2230
 
2231
        if (Value == ALPHA_TO_COVERAGE_ENABLE ||
2232
            Value == ALPHA_TO_COVERAGE_DISABLE) {
2233
            state->rs[NINED3DRS_ALPHACOVERAGE] = (Value == ALPHA_TO_COVERAGE_ENABLE);
2234
            state->changed.group |= NINE_STATE_BLEND;
2235
            return D3D_OK;
2236
        }
2237
    }
2238
 
2239
    /* NV hack */
2240
    if (State == D3DRS_ADAPTIVETESS_Y &&
2241
        (Value == D3DFMT_ATOC || (Value == D3DFMT_UNKNOWN && state->rs[NINED3DRS_ALPHACOVERAGE]))) {
2242
            state->rs[NINED3DRS_ALPHACOVERAGE] = (Value == D3DFMT_ATOC);
2243
            state->changed.group |= NINE_STATE_BLEND;
2244
            return D3D_OK;
2245
    }
2246
 
2247
    user_assert(State < Elements(state->rs), D3DERR_INVALIDCALL);
2248
 
2249
    if (likely(state->rs[State] != Value) || unlikely(This->is_recording)) {
2250
        state->rs[State] = Value;
2251
        state->changed.rs[State / 32] |= 1 << (State % 32);
2252
        state->changed.group |= nine_render_state_group[State];
2253
    }
2254
 
2255
    return D3D_OK;
2256
}
2257
 
2258
HRESULT WINAPI
2259
NineDevice9_GetRenderState( struct NineDevice9 *This,
2260
                            D3DRENDERSTATETYPE State,
2261
                            DWORD *pValue )
2262
{
2263
    user_assert(State < Elements(This->state.rs), D3DERR_INVALIDCALL);
2264
 
2265
    *pValue = This->state.rs[State];
2266
    return D3D_OK;
2267
}
2268
 
2269
HRESULT WINAPI
2270
NineDevice9_CreateStateBlock( struct NineDevice9 *This,
2271
                              D3DSTATEBLOCKTYPE Type,
2272
                              IDirect3DStateBlock9 **ppSB )
2273
{
2274
    struct NineStateBlock9 *nsb;
2275
    struct nine_state *dst;
2276
    HRESULT hr;
2277
    enum nine_stateblock_type type;
2278
    unsigned s;
2279
 
2280
    DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB);
2281
 
2282
    user_assert(Type == D3DSBT_ALL ||
2283
                Type == D3DSBT_VERTEXSTATE ||
2284
                Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL);
2285
 
2286
    switch (Type) {
2287
    case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break;
2288
    case D3DSBT_PIXELSTATE:  type = NINESBT_PIXELSTATE; break;
2289
    default:
2290
       type = NINESBT_ALL;
2291
       break;
2292
    }
2293
 
2294
    hr = NineStateBlock9_new(This, &nsb, type);
2295
    if (FAILED(hr))
2296
       return hr;
2297
    *ppSB = (IDirect3DStateBlock9 *)nsb;
2298
    dst = &nsb->state;
2299
 
2300
    dst->changed.group =
2301
       NINE_STATE_TEXTURE |
2302
       NINE_STATE_SAMPLER;
2303
 
2304
    if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) {
2305
       dst->changed.group |=
2306
           NINE_STATE_FF_LIGHTING |
2307
           NINE_STATE_VS | NINE_STATE_VS_CONST |
2308
           NINE_STATE_VDECL;
2309
       /* TODO: texture/sampler state */
2310
       memcpy(dst->changed.rs,
2311
              nine_render_states_vertex, sizeof(dst->changed.rs));
2312
       nine_ranges_insert(&dst->changed.vs_const_f, 0, This->max_vs_const_f,
2313
                          &This->range_pool);
2314
       dst->changed.vs_const_i = 0xffff;
2315
       dst->changed.vs_const_b = 0xffff;
2316
       for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
2317
           dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET;
2318
       if (This->state.ff.num_lights) {
2319
           dst->ff.num_lights = This->state.ff.num_lights;
2320
           /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
2321
            * all currently existing lights will be captured
2322
            */
2323
           dst->ff.light = CALLOC(This->state.ff.num_lights,
2324
                                  sizeof(D3DLIGHT9));
2325
           if (!dst->ff.light) {
2326
               nine_bind(ppSB, NULL);
2327
               return E_OUTOFMEMORY;
2328
           }
2329
       }
2330
    }
2331
    if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) {
2332
       dst->changed.group |=
2333
          NINE_STATE_PS | NINE_STATE_PS_CONST;
2334
       /* TODO: texture/sampler state */
2335
       memcpy(dst->changed.rs,
2336
              nine_render_states_pixel, sizeof(dst->changed.rs));
2337
       nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f,
2338
                          &This->range_pool);
2339
       dst->changed.ps_const_i = 0xffff;
2340
       dst->changed.ps_const_b = 0xffff;
2341
       for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
2342
           dst->changed.sampler[s] |= 0x1ffe;
2343
    }
2344
    if (Type == D3DSBT_ALL) {
2345
       dst->changed.group |=
2346
          NINE_STATE_VIEWPORT |
2347
          NINE_STATE_SCISSOR |
2348
          NINE_STATE_RASTERIZER |
2349
          NINE_STATE_BLEND |
2350
          NINE_STATE_DSA |
2351
          NINE_STATE_IDXBUF |
2352
          NINE_STATE_MATERIAL |
2353
          NINE_STATE_BLEND_COLOR |
2354
          NINE_STATE_SAMPLE_MASK;
2355
       memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t));
2356
       dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1;
2357
       dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
2358
       dst->changed.stream_freq = dst->changed.vtxbuf;
2359
       dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
2360
       dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1;
2361
    }
2362
    NineStateBlock9_Capture(NineStateBlock9(*ppSB));
2363
 
2364
    /* TODO: fixed function state */
2365
 
2366
    return D3D_OK;
2367
}
2368
 
2369
HRESULT WINAPI
2370
NineDevice9_BeginStateBlock( struct NineDevice9 *This )
2371
{
2372
    HRESULT hr;
2373
 
2374
    DBG("This=%p\n", This);
2375
 
2376
    user_assert(!This->record, D3DERR_INVALIDCALL);
2377
 
2378
    hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM);
2379
    if (FAILED(hr))
2380
        return hr;
2381
    NineUnknown_ConvertRefToBind(NineUnknown(This->record));
2382
 
2383
    This->update = &This->record->state;
2384
    This->is_recording = TRUE;
2385
 
2386
    return D3D_OK;
2387
}
2388
 
2389
HRESULT WINAPI
2390
NineDevice9_EndStateBlock( struct NineDevice9 *This,
2391
                           IDirect3DStateBlock9 **ppSB )
2392
{
2393
    DBG("This=%p ppSB=%p\n", This, ppSB);
2394
 
2395
    user_assert(This->record, D3DERR_INVALIDCALL);
2396
 
2397
    This->update = &This->state;
2398
    This->is_recording = FALSE;
2399
 
2400
    NineUnknown_AddRef(NineUnknown(This->record));
2401
    *ppSB = (IDirect3DStateBlock9 *)This->record;
2402
    NineUnknown_Unbind(NineUnknown(This->record));
2403
    This->record = NULL;
2404
 
2405
    return D3D_OK;
2406
}
2407
 
2408
HRESULT WINAPI
2409
NineDevice9_SetClipStatus( struct NineDevice9 *This,
2410
                           const D3DCLIPSTATUS9 *pClipStatus )
2411
{
2412
    STUB(D3DERR_INVALIDCALL);
2413
}
2414
 
2415
HRESULT WINAPI
2416
NineDevice9_GetClipStatus( struct NineDevice9 *This,
2417
                           D3DCLIPSTATUS9 *pClipStatus )
2418
{
2419
    STUB(D3DERR_INVALIDCALL);
2420
}
2421
 
2422
HRESULT WINAPI
2423
NineDevice9_GetTexture( struct NineDevice9 *This,
2424
                        DWORD Stage,
2425
                        IDirect3DBaseTexture9 **ppTexture )
2426
{
2427
    user_assert(Stage < This->caps.MaxSimultaneousTextures ||
2428
                Stage == D3DDMAPSAMPLER ||
2429
                (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
2430
                 Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2431
    user_assert(ppTexture, D3DERR_INVALIDCALL);
2432
 
2433
    if (Stage >= D3DDMAPSAMPLER)
2434
        Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2435
 
2436
    *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage];
2437
 
2438
    if (This->state.texture[Stage])
2439
        NineUnknown_AddRef(NineUnknown(This->state.texture[Stage]));
2440
    return D3D_OK;
2441
}
2442
 
2443
HRESULT WINAPI
2444
NineDevice9_SetTexture( struct NineDevice9 *This,
2445
                        DWORD Stage,
2446
                        IDirect3DBaseTexture9 *pTexture )
2447
{
2448
    struct nine_state *state = This->update;
2449
    struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture);
2450
 
2451
    DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture);
2452
 
2453
    user_assert(Stage < This->caps.MaxSimultaneousTextures ||
2454
                Stage == D3DDMAPSAMPLER ||
2455
                (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
2456
                 Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2457
    user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH &&
2458
                tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL);
2459
 
2460
    if (Stage >= D3DDMAPSAMPLER)
2461
        Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2462
 
2463
    if (!This->is_recording) {
2464
        struct NineBaseTexture9 *old = state->texture[Stage];
2465
        if (old == tex)
2466
            return D3D_OK;
2467
 
2468
        state->samplers_shadow &= ~(1 << Stage);
2469
        if (tex) {
2470
            state->samplers_shadow |= tex->shadow << Stage;
2471
 
2472
            if ((tex->managed.dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list))
2473
                list_add(&tex->list, &This->update_textures);
2474
 
2475
            tex->bind_count++;
2476
        }
2477
        if (old)
2478
            old->bind_count--;
2479
    }
2480
    nine_bind(&state->texture[Stage], pTexture);
2481
 
2482
    state->changed.texture |= 1 << Stage;
2483
    state->changed.group |= NINE_STATE_TEXTURE;
2484
 
2485
    return D3D_OK;
2486
}
2487
 
2488
HRESULT WINAPI
2489
NineDevice9_GetTextureStageState( struct NineDevice9 *This,
2490
                                  DWORD Stage,
2491
                                  D3DTEXTURESTAGESTATETYPE Type,
2492
                                  DWORD *pValue )
2493
{
2494
    const struct nine_state *state = &This->state;
2495
 
2496
    user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
2497
    user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
2498
 
2499
    *pValue = state->ff.tex_stage[Stage][Type];
2500
 
2501
    return D3D_OK;
2502
}
2503
 
2504
HRESULT WINAPI
2505
NineDevice9_SetTextureStageState( struct NineDevice9 *This,
2506
                                  DWORD Stage,
2507
                                  D3DTEXTURESTAGESTATETYPE Type,
2508
                                  DWORD Value )
2509
{
2510
    struct nine_state *state = This->update;
2511
 
2512
    DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);
2513
    nine_dump_D3DTSS_value(DBG_FF, Type, Value);
2514
 
2515
    user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
2516
    user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
2517
 
2518
    state->ff.tex_stage[Stage][Type] = Value;
2519
 
2520
    state->changed.group |= NINE_STATE_FF_PSSTAGES;
2521
    state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32);
2522
 
2523
    return D3D_OK;
2524
}
2525
 
2526
HRESULT WINAPI
2527
NineDevice9_GetSamplerState( struct NineDevice9 *This,
2528
                             DWORD Sampler,
2529
                             D3DSAMPLERSTATETYPE Type,
2530
                             DWORD *pValue )
2531
{
2532
    user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
2533
                Sampler == D3DDMAPSAMPLER ||
2534
                (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
2535
                 Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2536
 
2537
    if (Sampler >= D3DDMAPSAMPLER)
2538
        Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2539
 
2540
    *pValue = This->state.samp[Sampler][Type];
2541
    return D3D_OK;
2542
}
2543
 
2544
HRESULT WINAPI
2545
NineDevice9_SetSamplerState( struct NineDevice9 *This,
2546
                             DWORD Sampler,
2547
                             D3DSAMPLERSTATETYPE Type,
2548
                             DWORD Value )
2549
{
2550
    struct nine_state *state = This->update;
2551
 
2552
    DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This,
2553
        Sampler, nine_D3DSAMP_to_str(Type), Value);
2554
 
2555
    user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
2556
                Sampler == D3DDMAPSAMPLER ||
2557
                (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
2558
                 Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2559
 
2560
    if (Sampler >= D3DDMAPSAMPLER)
2561
        Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2562
 
2563
    state->samp[Sampler][Type] = Value;
2564
    state->changed.group |= NINE_STATE_SAMPLER;
2565
    state->changed.sampler[Sampler] |= 1 << Type;
2566
 
2567
    if (Type == D3DSAMP_SRGBTEXTURE)
2568
        state->changed.srgb = TRUE;
2569
 
2570
    return D3D_OK;
2571
}
2572
 
2573
HRESULT WINAPI
2574
NineDevice9_ValidateDevice( struct NineDevice9 *This,
2575
                            DWORD *pNumPasses )
2576
{
2577
    const struct nine_state *state = &This->state;
2578
    unsigned i;
2579
    unsigned w = 0, h = 0;
2580
 
2581
    DBG("This=%p pNumPasses=%p\n", This, pNumPasses);
2582
 
2583
    for (i = 0; i < Elements(state->samp); ++i) {
2584
        if (state->samp[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE ||
2585
            state->samp[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE)
2586
            return D3DERR_UNSUPPORTEDTEXTUREFILTER;
2587
    }
2588
 
2589
    for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
2590
        if (!state->rt[i])
2591
            continue;
2592
        if (w == 0) {
2593
            w = state->rt[i]->desc.Width;
2594
            h = state->rt[i]->desc.Height;
2595
        } else
2596
        if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) {
2597
            return D3DERR_CONFLICTINGRENDERSTATE;
2598
        }
2599
    }
2600
    if (state->ds &&
2601
        (state->rs[D3DRS_ZENABLE] || state->rs[D3DRS_STENCILENABLE])) {
2602
        if (w != 0 &&
2603
            (state->ds->desc.Width != w || state->ds->desc.Height != h))
2604
            return D3DERR_CONFLICTINGRENDERSTATE;
2605
    }
2606
 
2607
    if (pNumPasses)
2608
        *pNumPasses = 1;
2609
 
2610
    return D3D_OK;
2611
}
2612
 
2613
HRESULT WINAPI
2614
NineDevice9_SetPaletteEntries( struct NineDevice9 *This,
2615
                               UINT PaletteNumber,
2616
                               const PALETTEENTRY *pEntries )
2617
{
2618
    STUB(D3D_OK); /* like wine */
2619
}
2620
 
2621
HRESULT WINAPI
2622
NineDevice9_GetPaletteEntries( struct NineDevice9 *This,
2623
                               UINT PaletteNumber,
2624
                               PALETTEENTRY *pEntries )
2625
{
2626
    STUB(D3DERR_INVALIDCALL);
2627
}
2628
 
2629
HRESULT WINAPI
2630
NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,
2631
                                      UINT PaletteNumber )
2632
{
2633
    STUB(D3D_OK); /* like wine */
2634
}
2635
 
2636
HRESULT WINAPI
2637
NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,
2638
                                      UINT *PaletteNumber )
2639
{
2640
    STUB(D3DERR_INVALIDCALL);
2641
}
2642
 
2643
HRESULT WINAPI
2644
NineDevice9_SetScissorRect( struct NineDevice9 *This,
2645
                            const RECT *pRect )
2646
{
2647
    struct nine_state *state = This->update;
2648
 
2649
    DBG("x=(%u..%u) y=(%u..%u)\n",
2650
        pRect->left, pRect->top, pRect->right, pRect->bottom);
2651
 
2652
    state->scissor.minx = pRect->left;
2653
    state->scissor.miny = pRect->top;
2654
    state->scissor.maxx = pRect->right;
2655
    state->scissor.maxy = pRect->bottom;
2656
 
2657
    state->changed.group |= NINE_STATE_SCISSOR;
2658
 
2659
    return D3D_OK;
2660
}
2661
 
2662
HRESULT WINAPI
2663
NineDevice9_GetScissorRect( struct NineDevice9 *This,
2664
                            RECT *pRect )
2665
{
2666
    pRect->left   = This->state.scissor.minx;
2667
    pRect->top    = This->state.scissor.miny;
2668
    pRect->right  = This->state.scissor.maxx;
2669
    pRect->bottom = This->state.scissor.maxy;
2670
 
2671
    return D3D_OK;
2672
}
2673
 
2674
HRESULT WINAPI
2675
NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,
2676
                                         BOOL bSoftware )
2677
{
2678
    STUB(D3DERR_INVALIDCALL);
2679
}
2680
 
2681
BOOL WINAPI
2682
NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This )
2683
{
2684
    return !!(This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING);
2685
}
2686
 
2687
HRESULT WINAPI
2688
NineDevice9_SetNPatchMode( struct NineDevice9 *This,
2689
                           float nSegments )
2690
{
2691
    STUB(D3DERR_INVALIDCALL);
2692
}
2693
 
2694
float WINAPI
2695
NineDevice9_GetNPatchMode( struct NineDevice9 *This )
2696
{
2697
    STUB(0);
2698
}
2699
 
2700
static INLINE void
2701
init_draw_info(struct pipe_draw_info *info,
2702
               struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count)
2703
{
2704
    info->mode = d3dprimitivetype_to_pipe_prim(type);
2705
    info->count = prim_count_to_vertex_count(type, count);
2706
    info->start_instance = 0;
2707
    info->instance_count = 1;
2708
    if (dev->state.stream_instancedata_mask & dev->state.stream_usage_mask)
2709
        info->instance_count = MAX2(dev->state.stream_freq[0] & 0x7FFFFF, 1);
2710
    info->primitive_restart = FALSE;
2711
    info->restart_index = 0;
2712
    info->count_from_stream_output = NULL;
2713
    info->indirect = NULL;
2714
}
2715
 
2716
HRESULT WINAPI
2717
NineDevice9_DrawPrimitive( struct NineDevice9 *This,
2718
                           D3DPRIMITIVETYPE PrimitiveType,
2719
                           UINT StartVertex,
2720
                           UINT PrimitiveCount )
2721
{
2722
    struct pipe_draw_info info;
2723
 
2724
    DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
2725
        This, PrimitiveType, StartVertex, PrimitiveCount);
2726
 
2727
    nine_update_state(This, ~0);
2728
 
2729
    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2730
    info.indexed = FALSE;
2731
    info.start = StartVertex;
2732
    info.index_bias = 0;
2733
    info.min_index = info.start;
2734
    info.max_index = info.count - 1;
2735
 
2736
    This->pipe->draw_vbo(This->pipe, &info);
2737
 
2738
    return D3D_OK;
2739
}
2740
 
2741
HRESULT WINAPI
2742
NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
2743
                                  D3DPRIMITIVETYPE PrimitiveType,
2744
                                  INT BaseVertexIndex,
2745
                                  UINT MinVertexIndex,
2746
                                  UINT NumVertices,
2747
                                  UINT StartIndex,
2748
                                  UINT PrimitiveCount )
2749
{
2750
    struct pipe_draw_info info;
2751
 
2752
    DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
2753
        "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
2754
        This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices,
2755
        StartIndex, PrimitiveCount);
2756
 
2757
    user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);
2758
    user_assert(This->state.vdecl, D3DERR_INVALIDCALL);
2759
 
2760
    nine_update_state(This, ~0);
2761
 
2762
    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2763
    info.indexed = TRUE;
2764
    info.start = StartIndex;
2765
    info.index_bias = BaseVertexIndex;
2766
    /* These don't include index bias: */
2767
    info.min_index = MinVertexIndex;
2768
    info.max_index = MinVertexIndex + NumVertices - 1;
2769
 
2770
    This->pipe->draw_vbo(This->pipe, &info);
2771
 
2772
    return D3D_OK;
2773
}
2774
 
2775
HRESULT WINAPI
2776
NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
2777
                             D3DPRIMITIVETYPE PrimitiveType,
2778
                             UINT PrimitiveCount,
2779
                             const void *pVertexStreamZeroData,
2780
                             UINT VertexStreamZeroStride )
2781
{
2782
    struct pipe_vertex_buffer vtxbuf;
2783
    struct pipe_draw_info info;
2784
 
2785
    DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
2786
        This, PrimitiveType, PrimitiveCount,
2787
        pVertexStreamZeroData, VertexStreamZeroStride);
2788
 
2789
    user_assert(pVertexStreamZeroData && VertexStreamZeroStride,
2790
                D3DERR_INVALIDCALL);
2791
 
2792
    nine_update_state(This, ~0);
2793
 
2794
    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2795
    info.indexed = FALSE;
2796
    info.start = 0;
2797
    info.index_bias = 0;
2798
    info.min_index = 0;
2799
    info.max_index = info.count - 1;
2800
 
2801
    vtxbuf.stride = VertexStreamZeroStride;
2802
    vtxbuf.buffer_offset = 0;
2803
    vtxbuf.buffer = NULL;
2804
    vtxbuf.user_buffer = pVertexStreamZeroData;
2805
 
2806
    if (!This->driver_caps.user_vbufs)
2807
        u_upload_data(This->upload,
2808
                      0,
2809
                      (info.max_index + 1) * VertexStreamZeroStride, /* XXX */
2810
                      vtxbuf.user_buffer,
2811
                      &vtxbuf.buffer_offset,
2812
                      &vtxbuf.buffer);
2813
 
2814
    This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vtxbuf);
2815
 
2816
    This->pipe->draw_vbo(This->pipe, &info);
2817
 
2818
    NineDevice9_PauseRecording(This);
2819
    NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
2820
    NineDevice9_ResumeRecording(This);
2821
 
2822
    pipe_resource_reference(&vtxbuf.buffer, NULL);
2823
 
2824
    return D3D_OK;
2825
}
2826
 
2827
HRESULT WINAPI
2828
NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
2829
                                    D3DPRIMITIVETYPE PrimitiveType,
2830
                                    UINT MinVertexIndex,
2831
                                    UINT NumVertices,
2832
                                    UINT PrimitiveCount,
2833
                                    const void *pIndexData,
2834
                                    D3DFORMAT IndexDataFormat,
2835
                                    const void *pVertexStreamZeroData,
2836
                                    UINT VertexStreamZeroStride )
2837
{
2838
    struct pipe_draw_info info;
2839
    struct pipe_vertex_buffer vbuf;
2840
    struct pipe_index_buffer ibuf;
2841
 
2842
    DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
2843
        "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
2844
        "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
2845
        This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount,
2846
        pIndexData, IndexDataFormat,
2847
        pVertexStreamZeroData, VertexStreamZeroStride);
2848
 
2849
    user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL);
2850
    user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL);
2851
    user_assert(IndexDataFormat == D3DFMT_INDEX16 ||
2852
                IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2853
 
2854
    nine_update_state(This, ~0);
2855
 
2856
    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2857
    info.indexed = TRUE;
2858
    info.start = 0;
2859
    info.index_bias = 0;
2860
    info.min_index = MinVertexIndex;
2861
    info.max_index = MinVertexIndex + NumVertices - 1;
2862
 
2863
    vbuf.stride = VertexStreamZeroStride;
2864
    vbuf.buffer_offset = 0;
2865
    vbuf.buffer = NULL;
2866
    vbuf.user_buffer = pVertexStreamZeroData;
2867
 
2868
    ibuf.index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;
2869
    ibuf.offset = 0;
2870
    ibuf.buffer = NULL;
2871
    ibuf.user_buffer = pIndexData;
2872
 
2873
    if (!This->driver_caps.user_vbufs) {
2874
        const unsigned base = info.min_index * VertexStreamZeroStride;
2875
        u_upload_data(This->upload,
2876
                      base,
2877
                      (info.max_index -
2878
                       info.min_index + 1) * VertexStreamZeroStride, /* XXX */
2879
                      (const uint8_t *)vbuf.user_buffer + base,
2880
                      &vbuf.buffer_offset,
2881
                      &vbuf.buffer);
2882
        /* Won't be used: */
2883
        vbuf.buffer_offset -= base;
2884
    }
2885
    if (!This->driver_caps.user_ibufs)
2886
        u_upload_data(This->upload,
2887
                      0,
2888
                      info.count * ibuf.index_size,
2889
                      ibuf.user_buffer,
2890
                      &ibuf.offset,
2891
                      &ibuf.buffer);
2892
 
2893
    This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vbuf);
2894
    This->pipe->set_index_buffer(This->pipe, &ibuf);
2895
 
2896
    This->pipe->draw_vbo(This->pipe, &info);
2897
 
2898
    pipe_resource_reference(&vbuf.buffer, NULL);
2899
    pipe_resource_reference(&ibuf.buffer, NULL);
2900
 
2901
    NineDevice9_PauseRecording(This);
2902
    NineDevice9_SetIndices(This, NULL);
2903
    NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
2904
    NineDevice9_ResumeRecording(This);
2905
 
2906
    return D3D_OK;
2907
}
2908
 
2909
/* TODO: Write to pDestBuffer directly if vertex declaration contains
2910
 * only f32 formats.
2911
 */
2912
HRESULT WINAPI
2913
NineDevice9_ProcessVertices( struct NineDevice9 *This,
2914
                             UINT SrcStartIndex,
2915
                             UINT DestIndex,
2916
                             UINT VertexCount,
2917
                             IDirect3DVertexBuffer9 *pDestBuffer,
2918
                             IDirect3DVertexDeclaration9 *pVertexDecl,
2919
                             DWORD Flags )
2920
{
2921
    struct pipe_screen *screen = This->screen;
2922
    struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl);
2923
    struct NineVertexShader9 *vs;
2924
    struct pipe_resource *resource;
2925
    struct pipe_stream_output_target *target;
2926
    struct pipe_draw_info draw;
2927
    HRESULT hr;
2928
    unsigned buffer_offset, buffer_size;
2929
 
2930
    DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
2931
        "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
2932
        This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer,
2933
        pVertexDecl, Flags);
2934
 
2935
    if (!screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS))
2936
        STUB(D3DERR_INVALIDCALL);
2937
 
2938
    nine_update_state(This, ~0);
2939
 
2940
    /* TODO: Create shader with stream output. */
2941
    STUB(D3DERR_INVALIDCALL);
2942
    struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);
2943
 
2944
    vs = This->state.vs ? This->state.vs : This->ff.vs;
2945
 
2946
    buffer_size = VertexCount * vs->so->stride[0];
2947
    if (1) {
2948
        struct pipe_resource templ;
2949
 
2950
        templ.target = PIPE_BUFFER;
2951
        templ.format = PIPE_FORMAT_R8_UNORM;
2952
        templ.width0 = buffer_size;
2953
        templ.flags = 0;
2954
        templ.bind = PIPE_BIND_STREAM_OUTPUT;
2955
        templ.usage = PIPE_USAGE_STREAM;
2956
        templ.height0 = templ.depth0 = templ.array_size = 1;
2957
        templ.last_level = templ.nr_samples = 0;
2958
 
2959
        resource = This->screen->resource_create(This->screen, &templ);
2960
        if (!resource)
2961
            return E_OUTOFMEMORY;
2962
        buffer_offset = 0;
2963
    } else {
2964
        /* SO matches vertex declaration */
2965
        resource = dst->base.resource;
2966
        buffer_offset = DestIndex * vs->so->stride[0];
2967
    }
2968
    target = This->pipe->create_stream_output_target(This->pipe, resource,
2969
                                                     buffer_offset,
2970
                                                     buffer_size);
2971
    if (!target) {
2972
        pipe_resource_reference(&resource, NULL);
2973
        return D3DERR_DRIVERINTERNALERROR;
2974
    }
2975
 
2976
    if (!vdecl) {
2977
        hr = NineVertexDeclaration9_new_from_fvf(This, dst->desc.FVF, &vdecl);
2978
        if (FAILED(hr))
2979
            goto out;
2980
    }
2981
 
2982
    init_draw_info(&draw, This, D3DPT_POINTLIST, VertexCount);
2983
    draw.instance_count = 1;
2984
    draw.indexed = FALSE;
2985
    draw.start = SrcStartIndex;
2986
    draw.index_bias = 0;
2987
    draw.min_index = SrcStartIndex;
2988
    draw.max_index = SrcStartIndex + VertexCount - 1;
2989
 
2990
    This->pipe->set_stream_output_targets(This->pipe, 1, &target, 0);
2991
    This->pipe->draw_vbo(This->pipe, &draw);
2992
    This->pipe->set_stream_output_targets(This->pipe, 0, NULL, 0);
2993
    This->pipe->stream_output_target_destroy(This->pipe, target);
2994
 
2995
    hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl,
2996
                                                    dst, DestIndex, VertexCount,
2997
                                                    resource, vs->so);
2998
out:
2999
    pipe_resource_reference(&resource, NULL);
3000
    if (!pVertexDecl)
3001
        NineUnknown_Release(NineUnknown(vdecl));
3002
    return hr;
3003
}
3004
 
3005
HRESULT WINAPI
3006
NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This,
3007
                                     const D3DVERTEXELEMENT9 *pVertexElements,
3008
                                     IDirect3DVertexDeclaration9 **ppDecl )
3009
{
3010
    struct NineVertexDeclaration9 *vdecl;
3011
 
3012
    DBG("This=%p pVertexElements=%p ppDecl=%p\n",
3013
        This, pVertexElements, ppDecl);
3014
 
3015
    HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl);
3016
    if (SUCCEEDED(hr))
3017
        *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl;
3018
 
3019
    return hr;
3020
}
3021
 
3022
HRESULT WINAPI
3023
NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,
3024
                                  IDirect3DVertexDeclaration9 *pDecl )
3025
{
3026
    struct nine_state *state = This->update;
3027
 
3028
    DBG("This=%p pDecl=%p\n", This, pDecl);
3029
 
3030
    if (likely(!This->is_recording) && state->vdecl == NineVertexDeclaration9(pDecl))
3031
        return D3D_OK;
3032
    nine_bind(&state->vdecl, pDecl);
3033
 
3034
    state->changed.group |= NINE_STATE_VDECL;
3035
 
3036
    return D3D_OK;
3037
}
3038
 
3039
HRESULT WINAPI
3040
NineDevice9_GetVertexDeclaration( struct NineDevice9 *This,
3041
                                  IDirect3DVertexDeclaration9 **ppDecl )
3042
{
3043
    user_assert(ppDecl, D3DERR_INVALIDCALL);
3044
 
3045
    *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl;
3046
    if (*ppDecl)
3047
        NineUnknown_AddRef(NineUnknown(*ppDecl));
3048
    return D3D_OK;
3049
}
3050
 
3051
HRESULT WINAPI
3052
NineDevice9_SetFVF( struct NineDevice9 *This,
3053
                    DWORD FVF )
3054
{
3055
    struct NineVertexDeclaration9 *vdecl;
3056
    HRESULT hr;
3057
 
3058
    DBG("FVF = %08x\n", FVF);
3059
    if (!FVF)
3060
        return D3D_OK; /* like wine */
3061
 
3062
    vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);
3063
    if (!vdecl) {
3064
        hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);
3065
        if (FAILED(hr))
3066
            return hr;
3067
        vdecl->fvf = FVF;
3068
        util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl);
3069
        NineUnknown_ConvertRefToBind(NineUnknown(vdecl));
3070
    }
3071
    return NineDevice9_SetVertexDeclaration(
3072
        This, (IDirect3DVertexDeclaration9 *)vdecl);
3073
}
3074
 
3075
HRESULT WINAPI
3076
NineDevice9_GetFVF( struct NineDevice9 *This,
3077
                    DWORD *pFVF )
3078
{
3079
    *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0;
3080
    return D3D_OK;
3081
}
3082
 
3083
HRESULT WINAPI
3084
NineDevice9_CreateVertexShader( struct NineDevice9 *This,
3085
                                const DWORD *pFunction,
3086
                                IDirect3DVertexShader9 **ppShader )
3087
{
3088
    struct NineVertexShader9 *vs;
3089
    HRESULT hr;
3090
 
3091
    DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader);
3092
 
3093
    hr = NineVertexShader9_new(This, &vs, pFunction, NULL);
3094
    if (FAILED(hr))
3095
        return hr;
3096
    *ppShader = (IDirect3DVertexShader9 *)vs;
3097
    return D3D_OK;
3098
}
3099
 
3100
HRESULT WINAPI
3101
NineDevice9_SetVertexShader( struct NineDevice9 *This,
3102
                             IDirect3DVertexShader9 *pShader )
3103
{
3104
    struct nine_state *state = This->update;
3105
 
3106
    DBG("This=%p pShader=%p\n", This, pShader);
3107
 
3108
    nine_bind(&state->vs, pShader);
3109
 
3110
    state->changed.group |= NINE_STATE_VS;
3111
 
3112
    return D3D_OK;
3113
}
3114
 
3115
HRESULT WINAPI
3116
NineDevice9_GetVertexShader( struct NineDevice9 *This,
3117
                             IDirect3DVertexShader9 **ppShader )
3118
{
3119
    user_assert(ppShader, D3DERR_INVALIDCALL);
3120
    nine_reference_set(ppShader, This->state.vs);
3121
    return D3D_OK;
3122
}
3123
 
3124
HRESULT WINAPI
3125
NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
3126
                                      UINT StartRegister,
3127
                                      const float *pConstantData,
3128
                                      UINT Vector4fCount )
3129
{
3130
    struct nine_state *state = This->update;
3131
 
3132
    DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3133
        This, StartRegister, pConstantData, Vector4fCount);
3134
 
3135
    user_assert(StartRegister                  < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
3136
    user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
3137
 
3138
    if (!Vector4fCount)
3139
       return D3D_OK;
3140
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3141
 
3142
    memcpy(&state->vs_const_f[StartRegister * 4],
3143
           pConstantData,
3144
           Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
3145
 
3146
    nine_ranges_insert(&state->changed.vs_const_f,
3147
                       StartRegister, StartRegister + Vector4fCount,
3148
                       &This->range_pool);
3149
 
3150
    state->changed.group |= NINE_STATE_VS_CONST;
3151
 
3152
    return D3D_OK;
3153
}
3154
 
3155
HRESULT WINAPI
3156
NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,
3157
                                      UINT StartRegister,
3158
                                      float *pConstantData,
3159
                                      UINT Vector4fCount )
3160
{
3161
    const struct nine_state *state = &This->state;
3162
 
3163
    user_assert(StartRegister                  < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
3164
    user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
3165
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3166
 
3167
    memcpy(pConstantData,
3168
           &state->vs_const_f[StartRegister * 4],
3169
           Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
3170
 
3171
    return D3D_OK;
3172
}
3173
 
3174
HRESULT WINAPI
3175
NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
3176
                                      UINT StartRegister,
3177
                                      const int *pConstantData,
3178
                                      UINT Vector4iCount )
3179
{
3180
    struct nine_state *state = This->update;
3181
    int i;
3182
 
3183
    DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3184
        This, StartRegister, pConstantData, Vector4iCount);
3185
 
3186
    user_assert(StartRegister                  < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3187
    user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3188
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3189
 
3190
    if (This->driver_caps.vs_integer) {
3191
        memcpy(&state->vs_const_i[StartRegister][0],
3192
               pConstantData,
3193
               Vector4iCount * sizeof(state->vs_const_i[0]));
3194
    } else {
3195
        for (i = 0; i < Vector4iCount; i++) {
3196
            state->vs_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i]));
3197
            state->vs_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1]));
3198
            state->vs_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2]));
3199
            state->vs_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3]));
3200
        }
3201
    }
3202
 
3203
    state->changed.vs_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
3204
    state->changed.group |= NINE_STATE_VS_CONST;
3205
 
3206
    return D3D_OK;
3207
}
3208
 
3209
HRESULT WINAPI
3210
NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,
3211
                                      UINT StartRegister,
3212
                                      int *pConstantData,
3213
                                      UINT Vector4iCount )
3214
{
3215
    const struct nine_state *state = &This->state;
3216
    int i;
3217
 
3218
    user_assert(StartRegister                  < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3219
    user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3220
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3221
 
3222
    if (This->driver_caps.vs_integer) {
3223
        memcpy(pConstantData,
3224
               &state->vs_const_i[StartRegister][0],
3225
               Vector4iCount * sizeof(state->vs_const_i[0]));
3226
    } else {
3227
        for (i = 0; i < Vector4iCount; i++) {
3228
            pConstantData[4*i] = (int32_t) uif(state->vs_const_i[StartRegister+i][0]);
3229
            pConstantData[4*i+1] = (int32_t) uif(state->vs_const_i[StartRegister+i][1]);
3230
            pConstantData[4*i+2] = (int32_t) uif(state->vs_const_i[StartRegister+i][2]);
3231
            pConstantData[4*i+3] = (int32_t) uif(state->vs_const_i[StartRegister+i][3]);
3232
        }
3233
    }
3234
 
3235
    return D3D_OK;
3236
}
3237
 
3238
HRESULT WINAPI
3239
NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
3240
                                      UINT StartRegister,
3241
                                      const BOOL *pConstantData,
3242
                                      UINT BoolCount )
3243
{
3244
    struct nine_state *state = This->update;
3245
    int i;
3246
    uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f);
3247
 
3248
    DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3249
        This, StartRegister, pConstantData, BoolCount);
3250
 
3251
    user_assert(StartRegister              < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3252
    user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3253
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3254
 
3255
    for (i = 0; i < BoolCount; i++)
3256
        state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;
3257
 
3258
    state->changed.vs_const_b |= ((1 << BoolCount) - 1) << StartRegister;
3259
    state->changed.group |= NINE_STATE_VS_CONST;
3260
 
3261
    return D3D_OK;
3262
}
3263
 
3264
HRESULT WINAPI
3265
NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,
3266
                                      UINT StartRegister,
3267
                                      BOOL *pConstantData,
3268
                                      UINT BoolCount )
3269
{
3270
    const struct nine_state *state = &This->state;
3271
    int i;
3272
 
3273
    user_assert(StartRegister              < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3274
    user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3275
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3276
 
3277
    for (i = 0; i < BoolCount; i++)
3278
        pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE;
3279
 
3280
    return D3D_OK;
3281
}
3282
 
3283
HRESULT WINAPI
3284
NineDevice9_SetStreamSource( struct NineDevice9 *This,
3285
                             UINT StreamNumber,
3286
                             IDirect3DVertexBuffer9 *pStreamData,
3287
                             UINT OffsetInBytes,
3288
                             UINT Stride )
3289
{
3290
    struct nine_state *state = This->update;
3291
    struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData);
3292
    const unsigned i = StreamNumber;
3293
 
3294
    DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",
3295
        This, StreamNumber, pStreamData, OffsetInBytes, Stride);
3296
 
3297
    user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3298
    user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL);
3299
 
3300
    if (likely(!This->is_recording)) {
3301
        if (state->stream[i] == NineVertexBuffer9(pStreamData) &&
3302
            state->vtxbuf[i].stride == Stride &&
3303
            state->vtxbuf[i].buffer_offset == OffsetInBytes)
3304
            return D3D_OK;
3305
    }
3306
    nine_bind(&state->stream[i], pStreamData);
3307
 
3308
    state->changed.vtxbuf |= 1 << StreamNumber;
3309
 
3310
    if (pStreamData) {
3311
        state->vtxbuf[i].stride = Stride;
3312
        state->vtxbuf[i].buffer_offset = OffsetInBytes;
3313
    }
3314
    state->vtxbuf[i].buffer = pStreamData ? pVBuf9->base.resource : NULL;
3315
 
3316
    return D3D_OK;
3317
}
3318
 
3319
HRESULT WINAPI
3320
NineDevice9_GetStreamSource( struct NineDevice9 *This,
3321
                             UINT StreamNumber,
3322
                             IDirect3DVertexBuffer9 **ppStreamData,
3323
                             UINT *pOffsetInBytes,
3324
                             UINT *pStride )
3325
{
3326
    const struct nine_state *state = &This->state;
3327
    const unsigned i = StreamNumber;
3328
 
3329
    user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3330
    user_assert(ppStreamData, D3DERR_INVALIDCALL);
3331
 
3332
    nine_reference_set(ppStreamData, state->stream[i]);
3333
    *pStride = state->vtxbuf[i].stride;
3334
    *pOffsetInBytes = state->vtxbuf[i].buffer_offset;
3335
 
3336
    return D3D_OK;
3337
}
3338
 
3339
HRESULT WINAPI
3340
NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This,
3341
                                 UINT StreamNumber,
3342
                                 UINT Setting )
3343
{
3344
    struct nine_state *state = This->update;
3345
    /* const UINT freq = Setting & 0x7FFFFF; */
3346
 
3347
    DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This,
3348
        StreamNumber, Setting);
3349
 
3350
    user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3351
    user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA),
3352
                D3DERR_INVALIDCALL);
3353
    user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) &&
3354
                  (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL);
3355
    user_assert(Setting, D3DERR_INVALIDCALL);
3356
 
3357
    state->stream_freq[StreamNumber] = Setting;
3358
 
3359
    if (Setting & D3DSTREAMSOURCE_INSTANCEDATA)
3360
        state->stream_instancedata_mask |= 1 << StreamNumber;
3361
    else
3362
        state->stream_instancedata_mask &= ~(1 << StreamNumber);
3363
 
3364
    state->changed.stream_freq |= 1 << StreamNumber;
3365
    return D3D_OK;
3366
}
3367
 
3368
HRESULT WINAPI
3369
NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This,
3370
                                 UINT StreamNumber,
3371
                                 UINT *pSetting )
3372
{
3373
    user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3374
    *pSetting = This->state.stream_freq[StreamNumber];
3375
    return D3D_OK;
3376
}
3377
 
3378
HRESULT WINAPI
3379
NineDevice9_SetIndices( struct NineDevice9 *This,
3380
                        IDirect3DIndexBuffer9 *pIndexData )
3381
{
3382
    struct nine_state *state = This->update;
3383
 
3384
    DBG("This=%p pIndexData=%p\n", This, pIndexData);
3385
 
3386
    if (likely(!This->is_recording))
3387
        if (state->idxbuf == NineIndexBuffer9(pIndexData))
3388
            return D3D_OK;
3389
    nine_bind(&state->idxbuf, pIndexData);
3390
 
3391
    state->changed.group |= NINE_STATE_IDXBUF;
3392
 
3393
    return D3D_OK;
3394
}
3395
 
3396
/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
3397
 * here because it's an argument passed to the Draw calls.
3398
 */
3399
HRESULT WINAPI
3400
NineDevice9_GetIndices( struct NineDevice9 *This,
3401
                        IDirect3DIndexBuffer9 **ppIndexData /*,
3402
                        UINT *pBaseVertexIndex */ )
3403
{
3404
    user_assert(ppIndexData, D3DERR_INVALIDCALL);
3405
    nine_reference_set(ppIndexData, This->state.idxbuf);
3406
    return D3D_OK;
3407
}
3408
 
3409
HRESULT WINAPI
3410
NineDevice9_CreatePixelShader( struct NineDevice9 *This,
3411
                               const DWORD *pFunction,
3412
                               IDirect3DPixelShader9 **ppShader )
3413
{
3414
    struct NinePixelShader9 *ps;
3415
    HRESULT hr;
3416
 
3417
    DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader);
3418
 
3419
    hr = NinePixelShader9_new(This, &ps, pFunction, NULL);
3420
    if (FAILED(hr))
3421
        return hr;
3422
    *ppShader = (IDirect3DPixelShader9 *)ps;
3423
    return D3D_OK;
3424
}
3425
 
3426
HRESULT WINAPI
3427
NineDevice9_SetPixelShader( struct NineDevice9 *This,
3428
                            IDirect3DPixelShader9 *pShader )
3429
{
3430
    struct nine_state *state = This->update;
3431
    unsigned old_mask = state->ps ? state->ps->rt_mask : 1;
3432
    unsigned mask;
3433
 
3434
    DBG("This=%p pShader=%p\n", This, pShader);
3435
 
3436
    nine_bind(&state->ps, pShader);
3437
 
3438
    state->changed.group |= NINE_STATE_PS;
3439
 
3440
    mask = state->ps ? state->ps->rt_mask : 1;
3441
    /* We need to update cbufs if the pixel shader would
3442
     * write to different render targets */
3443
    if (mask != old_mask)
3444
        state->changed.group |= NINE_STATE_FB;
3445
 
3446
    return D3D_OK;
3447
}
3448
 
3449
HRESULT WINAPI
3450
NineDevice9_GetPixelShader( struct NineDevice9 *This,
3451
                            IDirect3DPixelShader9 **ppShader )
3452
{
3453
    user_assert(ppShader, D3DERR_INVALIDCALL);
3454
    nine_reference_set(ppShader, This->state.ps);
3455
    return D3D_OK;
3456
}
3457
 
3458
HRESULT WINAPI
3459
NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
3460
                                     UINT StartRegister,
3461
                                     const float *pConstantData,
3462
                                     UINT Vector4fCount )
3463
{
3464
    struct nine_state *state = This->update;
3465
 
3466
    DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3467
        This, StartRegister, pConstantData, Vector4fCount);
3468
 
3469
    user_assert(StartRegister                  < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
3470
    user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
3471
 
3472
    if (!Vector4fCount)
3473
       return D3D_OK;
3474
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3475
 
3476
    memcpy(&state->ps_const_f[StartRegister * 4],
3477
           pConstantData,
3478
           Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
3479
 
3480
    nine_ranges_insert(&state->changed.ps_const_f,
3481
                       StartRegister, StartRegister + Vector4fCount,
3482
                       &This->range_pool);
3483
 
3484
    state->changed.group |= NINE_STATE_PS_CONST;
3485
 
3486
    return D3D_OK;
3487
}
3488
 
3489
HRESULT WINAPI
3490
NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,
3491
                                     UINT StartRegister,
3492
                                     float *pConstantData,
3493
                                     UINT Vector4fCount )
3494
{
3495
    const struct nine_state *state = &This->state;
3496
 
3497
    user_assert(StartRegister                  < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
3498
    user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
3499
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3500
 
3501
    memcpy(pConstantData,
3502
           &state->ps_const_f[StartRegister * 4],
3503
           Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
3504
 
3505
    return D3D_OK;
3506
}
3507
 
3508
HRESULT WINAPI
3509
NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
3510
                                     UINT StartRegister,
3511
                                     const int *pConstantData,
3512
                                     UINT Vector4iCount )
3513
{
3514
    struct nine_state *state = This->update;
3515
    int i;
3516
 
3517
    DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3518
        This, StartRegister, pConstantData, Vector4iCount);
3519
 
3520
    user_assert(StartRegister                  < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3521
    user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3522
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3523
 
3524
    if (This->driver_caps.ps_integer) {
3525
        memcpy(&state->ps_const_i[StartRegister][0],
3526
               pConstantData,
3527
               Vector4iCount * sizeof(state->ps_const_i[0]));
3528
    } else {
3529
        for (i = 0; i < Vector4iCount; i++) {
3530
            state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i]));
3531
            state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1]));
3532
            state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2]));
3533
            state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3]));
3534
        }
3535
    }
3536
    state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
3537
    state->changed.group |= NINE_STATE_PS_CONST;
3538
 
3539
    return D3D_OK;
3540
}
3541
 
3542
HRESULT WINAPI
3543
NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,
3544
                                     UINT StartRegister,
3545
                                     int *pConstantData,
3546
                                     UINT Vector4iCount )
3547
{
3548
    const struct nine_state *state = &This->state;
3549
    int i;
3550
 
3551
    user_assert(StartRegister                  < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3552
    user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3553
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3554
 
3555
    if (This->driver_caps.ps_integer) {
3556
        memcpy(pConstantData,
3557
               &state->ps_const_i[StartRegister][0],
3558
               Vector4iCount * sizeof(state->ps_const_i[0]));
3559
    } else {
3560
        for (i = 0; i < Vector4iCount; i++) {
3561
            pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]);
3562
            pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]);
3563
            pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]);
3564
            pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]);
3565
        }
3566
    }
3567
 
3568
    return D3D_OK;
3569
}
3570
 
3571
HRESULT WINAPI
3572
NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
3573
                                     UINT StartRegister,
3574
                                     const BOOL *pConstantData,
3575
                                     UINT BoolCount )
3576
{
3577
    struct nine_state *state = This->update;
3578
    int i;
3579
    uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f);
3580
 
3581
    DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3582
        This, StartRegister, pConstantData, BoolCount);
3583
 
3584
    user_assert(StartRegister              < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3585
    user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3586
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3587
 
3588
    for (i = 0; i < BoolCount; i++)
3589
        state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;
3590
 
3591
    state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister;
3592
    state->changed.group |= NINE_STATE_PS_CONST;
3593
 
3594
    return D3D_OK;
3595
}
3596
 
3597
HRESULT WINAPI
3598
NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,
3599
                                     UINT StartRegister,
3600
                                     BOOL *pConstantData,
3601
                                     UINT BoolCount )
3602
{
3603
    const struct nine_state *state = &This->state;
3604
    int i;
3605
 
3606
    user_assert(StartRegister              < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3607
    user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3608
    user_assert(pConstantData, D3DERR_INVALIDCALL);
3609
 
3610
    for (i = 0; i < BoolCount; i++)
3611
        pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE;
3612
 
3613
    return D3D_OK;
3614
}
3615
 
3616
HRESULT WINAPI
3617
NineDevice9_DrawRectPatch( struct NineDevice9 *This,
3618
                           UINT Handle,
3619
                           const float *pNumSegs,
3620
                           const D3DRECTPATCH_INFO *pRectPatchInfo )
3621
{
3622
    STUB(D3DERR_INVALIDCALL);
3623
}
3624
 
3625
HRESULT WINAPI
3626
NineDevice9_DrawTriPatch( struct NineDevice9 *This,
3627
                          UINT Handle,
3628
                          const float *pNumSegs,
3629
                          const D3DTRIPATCH_INFO *pTriPatchInfo )
3630
{
3631
    STUB(D3DERR_INVALIDCALL);
3632
}
3633
 
3634
HRESULT WINAPI
3635
NineDevice9_DeletePatch( struct NineDevice9 *This,
3636
                         UINT Handle )
3637
{
3638
    STUB(D3DERR_INVALIDCALL);
3639
}
3640
 
3641
HRESULT WINAPI
3642
NineDevice9_CreateQuery( struct NineDevice9 *This,
3643
                         D3DQUERYTYPE Type,
3644
                         IDirect3DQuery9 **ppQuery )
3645
{
3646
    struct NineQuery9 *query;
3647
    HRESULT hr;
3648
 
3649
    DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery);
3650
 
3651
    hr = nine_is_query_supported(This->screen, Type);
3652
    if (!ppQuery || hr != D3D_OK)
3653
        return hr;
3654
 
3655
    hr = NineQuery9_new(This, &query, Type);
3656
    if (FAILED(hr))
3657
        return hr;
3658
    *ppQuery = (IDirect3DQuery9 *)query;
3659
    return D3D_OK;
3660
}
3661
 
3662
IDirect3DDevice9Vtbl NineDevice9_vtable = {
3663
    (void *)NineUnknown_QueryInterface,
3664
    (void *)NineUnknown_AddRef,
3665
    (void *)NineUnknown_Release,
3666
    (void *)NineDevice9_TestCooperativeLevel,
3667
    (void *)NineDevice9_GetAvailableTextureMem,
3668
    (void *)NineDevice9_EvictManagedResources,
3669
    (void *)NineDevice9_GetDirect3D,
3670
    (void *)NineDevice9_GetDeviceCaps,
3671
    (void *)NineDevice9_GetDisplayMode,
3672
    (void *)NineDevice9_GetCreationParameters,
3673
    (void *)NineDevice9_SetCursorProperties,
3674
    (void *)NineDevice9_SetCursorPosition,
3675
    (void *)NineDevice9_ShowCursor,
3676
    (void *)NineDevice9_CreateAdditionalSwapChain,
3677
    (void *)NineDevice9_GetSwapChain,
3678
    (void *)NineDevice9_GetNumberOfSwapChains,
3679
    (void *)NineDevice9_Reset,
3680
    (void *)NineDevice9_Present,
3681
    (void *)NineDevice9_GetBackBuffer,
3682
    (void *)NineDevice9_GetRasterStatus,
3683
    (void *)NineDevice9_SetDialogBoxMode,
3684
    (void *)NineDevice9_SetGammaRamp,
3685
    (void *)NineDevice9_GetGammaRamp,
3686
    (void *)NineDevice9_CreateTexture,
3687
    (void *)NineDevice9_CreateVolumeTexture,
3688
    (void *)NineDevice9_CreateCubeTexture,
3689
    (void *)NineDevice9_CreateVertexBuffer,
3690
    (void *)NineDevice9_CreateIndexBuffer,
3691
    (void *)NineDevice9_CreateRenderTarget,
3692
    (void *)NineDevice9_CreateDepthStencilSurface,
3693
    (void *)NineDevice9_UpdateSurface,
3694
    (void *)NineDevice9_UpdateTexture,
3695
    (void *)NineDevice9_GetRenderTargetData,
3696
    (void *)NineDevice9_GetFrontBufferData,
3697
    (void *)NineDevice9_StretchRect,
3698
    (void *)NineDevice9_ColorFill,
3699
    (void *)NineDevice9_CreateOffscreenPlainSurface,
3700
    (void *)NineDevice9_SetRenderTarget,
3701
    (void *)NineDevice9_GetRenderTarget,
3702
    (void *)NineDevice9_SetDepthStencilSurface,
3703
    (void *)NineDevice9_GetDepthStencilSurface,
3704
    (void *)NineDevice9_BeginScene,
3705
    (void *)NineDevice9_EndScene,
3706
    (void *)NineDevice9_Clear,
3707
    (void *)NineDevice9_SetTransform,
3708
    (void *)NineDevice9_GetTransform,
3709
    (void *)NineDevice9_MultiplyTransform,
3710
    (void *)NineDevice9_SetViewport,
3711
    (void *)NineDevice9_GetViewport,
3712
    (void *)NineDevice9_SetMaterial,
3713
    (void *)NineDevice9_GetMaterial,
3714
    (void *)NineDevice9_SetLight,
3715
    (void *)NineDevice9_GetLight,
3716
    (void *)NineDevice9_LightEnable,
3717
    (void *)NineDevice9_GetLightEnable,
3718
    (void *)NineDevice9_SetClipPlane,
3719
    (void *)NineDevice9_GetClipPlane,
3720
    (void *)NineDevice9_SetRenderState,
3721
    (void *)NineDevice9_GetRenderState,
3722
    (void *)NineDevice9_CreateStateBlock,
3723
    (void *)NineDevice9_BeginStateBlock,
3724
    (void *)NineDevice9_EndStateBlock,
3725
    (void *)NineDevice9_SetClipStatus,
3726
    (void *)NineDevice9_GetClipStatus,
3727
    (void *)NineDevice9_GetTexture,
3728
    (void *)NineDevice9_SetTexture,
3729
    (void *)NineDevice9_GetTextureStageState,
3730
    (void *)NineDevice9_SetTextureStageState,
3731
    (void *)NineDevice9_GetSamplerState,
3732
    (void *)NineDevice9_SetSamplerState,
3733
    (void *)NineDevice9_ValidateDevice,
3734
    (void *)NineDevice9_SetPaletteEntries,
3735
    (void *)NineDevice9_GetPaletteEntries,
3736
    (void *)NineDevice9_SetCurrentTexturePalette,
3737
    (void *)NineDevice9_GetCurrentTexturePalette,
3738
    (void *)NineDevice9_SetScissorRect,
3739
    (void *)NineDevice9_GetScissorRect,
3740
    (void *)NineDevice9_SetSoftwareVertexProcessing,
3741
    (void *)NineDevice9_GetSoftwareVertexProcessing,
3742
    (void *)NineDevice9_SetNPatchMode,
3743
    (void *)NineDevice9_GetNPatchMode,
3744
    (void *)NineDevice9_DrawPrimitive,
3745
    (void *)NineDevice9_DrawIndexedPrimitive,
3746
    (void *)NineDevice9_DrawPrimitiveUP,
3747
    (void *)NineDevice9_DrawIndexedPrimitiveUP,
3748
    (void *)NineDevice9_ProcessVertices,
3749
    (void *)NineDevice9_CreateVertexDeclaration,
3750
    (void *)NineDevice9_SetVertexDeclaration,
3751
    (void *)NineDevice9_GetVertexDeclaration,
3752
    (void *)NineDevice9_SetFVF,
3753
    (void *)NineDevice9_GetFVF,
3754
    (void *)NineDevice9_CreateVertexShader,
3755
    (void *)NineDevice9_SetVertexShader,
3756
    (void *)NineDevice9_GetVertexShader,
3757
    (void *)NineDevice9_SetVertexShaderConstantF,
3758
    (void *)NineDevice9_GetVertexShaderConstantF,
3759
    (void *)NineDevice9_SetVertexShaderConstantI,
3760
    (void *)NineDevice9_GetVertexShaderConstantI,
3761
    (void *)NineDevice9_SetVertexShaderConstantB,
3762
    (void *)NineDevice9_GetVertexShaderConstantB,
3763
    (void *)NineDevice9_SetStreamSource,
3764
    (void *)NineDevice9_GetStreamSource,
3765
    (void *)NineDevice9_SetStreamSourceFreq,
3766
    (void *)NineDevice9_GetStreamSourceFreq,
3767
    (void *)NineDevice9_SetIndices,
3768
    (void *)NineDevice9_GetIndices,
3769
    (void *)NineDevice9_CreatePixelShader,
3770
    (void *)NineDevice9_SetPixelShader,
3771
    (void *)NineDevice9_GetPixelShader,
3772
    (void *)NineDevice9_SetPixelShaderConstantF,
3773
    (void *)NineDevice9_GetPixelShaderConstantF,
3774
    (void *)NineDevice9_SetPixelShaderConstantI,
3775
    (void *)NineDevice9_GetPixelShaderConstantI,
3776
    (void *)NineDevice9_SetPixelShaderConstantB,
3777
    (void *)NineDevice9_GetPixelShaderConstantB,
3778
    (void *)NineDevice9_DrawRectPatch,
3779
    (void *)NineDevice9_DrawTriPatch,
3780
    (void *)NineDevice9_DeletePatch,
3781
    (void *)NineDevice9_CreateQuery
3782
};
3783
 
3784
static const GUID *NineDevice9_IIDs[] = {
3785
    &IID_IDirect3DDevice9,
3786
    &IID_IUnknown,
3787
    NULL
3788
};
3789
 
3790
HRESULT
3791
NineDevice9_new( struct pipe_screen *pScreen,
3792
                 D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
3793
                 D3DCAPS9 *pCaps,
3794
                 D3DPRESENT_PARAMETERS *pPresentationParameters,
3795
                 IDirect3D9 *pD3D9,
3796
                 ID3DPresentGroup *pPresentationGroup,
3797
                 struct d3dadapter9_context *pCTX,
3798
                 boolean ex,
3799
                 D3DDISPLAYMODEEX *pFullscreenDisplayMode,
3800
                 struct NineDevice9 **ppOut )
3801
{
3802
    BOOL lock;
3803
    lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);
3804
 
3805
    NINE_NEW(Device9, ppOut, lock, /* args */
3806
             pScreen, pCreationParameters, pCaps,
3807
             pPresentationParameters, pD3D9, pPresentationGroup, pCTX,
3808
             ex, pFullscreenDisplayMode);
3809
}