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