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