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