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