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