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