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