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