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