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