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