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