2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
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:
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
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. */
24 #include "stateblock9.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"
35 #include "cubetexture9.h"
36 #include "volumetexture9.h"
37 #include "nine_buffer_upload.h"
38 #include "nine_helpers.h"
39 #include "nine_pipe.h"
41 #include "nine_dump.h"
42 #include "nine_limits.h"
44 #include "pipe/p_screen.h"
45 #include "pipe/p_context.h"
46 #include "pipe/p_config.h"
47 #include "util/u_math.h"
48 #include "util/u_inlines.h"
49 #include "util/u_hash_table.h"
50 #include "util/format/u_format.h"
51 #include "util/u_surface.h"
52 #include "util/u_upload_mgr.h"
53 #include "hud/hud_context.h"
54 #include "compiler/glsl_types.h"
56 #include "cso_cache/cso_context.h"
58 #define DBG_CHANNEL DBG_DEVICE
60 #if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))
62 static void nine_setup_fpu()
66 __asm__
__volatile__ ("fnstcw %0" : "=m" (*&c
));
68 /* clear the control word */
70 /* d3d9 doc/wine tests: mask all exceptions, use single-precision
71 * and round to nearest */
74 __asm__
__volatile__ ("fldcw %0" : : "m" (*&c
));
79 static void nine_setup_fpu(void)
81 WARN_ONCE("FPU setup not supported on non-x86 platforms\n");
86 struct pipe_resource
*
87 nine_resource_create_with_retry( struct NineDevice9
*This
,
88 struct pipe_screen
*screen
,
89 const struct pipe_resource
*templat
)
91 struct pipe_resource
*res
;
92 res
= screen
->resource_create(screen
, templat
);
95 /* Allocation failed, retry after freeing some resources
96 * Note: Shouldn't be called from the worker thread */
99 /* Evict resources we can evict */
100 NineDevice9_EvictManagedResourcesInternal(This
);
101 /* Execute anything pending, such that some
102 * deleted resources can be actually freed */
103 nine_csmt_process(This
);
104 /* We could also finish the context, if needed */
105 return screen
->resource_create(screen
, templat
);
109 NineDevice9_SetDefaultState( struct NineDevice9
*This
, boolean is_reset
)
111 struct NineSurface9
*refSurf
= NULL
;
113 DBG("This=%p is_reset=%d\n", This
, (int) is_reset
);
115 assert(!This
->is_recording
);
117 nine_state_set_defaults(This
, &This
->caps
, is_reset
);
119 refSurf
= This
->swapchains
[0]->buffers
[0];
122 This
->state
.viewport
.X
= 0;
123 This
->state
.viewport
.Y
= 0;
124 This
->state
.viewport
.Width
= refSurf
->desc
.Width
;
125 This
->state
.viewport
.Height
= refSurf
->desc
.Height
;
127 nine_context_set_viewport(This
, &This
->state
.viewport
);
129 This
->state
.scissor
.minx
= 0;
130 This
->state
.scissor
.miny
= 0;
131 This
->state
.scissor
.maxx
= refSurf
->desc
.Width
;
132 This
->state
.scissor
.maxy
= refSurf
->desc
.Height
;
134 nine_context_set_scissor(This
, &This
->state
.scissor
);
136 if (This
->nswapchains
&& This
->swapchains
[0]->params
.EnableAutoDepthStencil
) {
137 nine_context_set_render_state(This
, D3DRS_ZENABLE
, TRUE
);
138 This
->state
.rs_advertised
[D3DRS_ZENABLE
] = TRUE
;
140 if (This
->state
.rs_advertised
[D3DRS_ZENABLE
])
141 NineDevice9_SetDepthStencilSurface(
142 This
, (IDirect3DSurface9
*)This
->swapchains
[0]->zsbuf
);
145 #define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
147 NineDevice9_ctor( struct NineDevice9
*This
,
148 struct NineUnknownParams
*pParams
,
149 struct pipe_screen
*pScreen
,
150 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
152 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
154 ID3DPresentGroup
*pPresentationGroup
,
155 struct d3dadapter9_context
*pCTX
,
157 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
158 int minorVersionNum
)
161 HRESULT hr
= NineUnknown_ctor(&This
->base
, pParams
);
163 DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "
164 "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",
165 This
, pParams
, pScreen
, pCreationParameters
, pCaps
, pPresentationParameters
, pD3D9
,
166 pPresentationGroup
, pCTX
, (int) ex
, pFullscreenDisplayMode
);
168 if (FAILED(hr
)) { return hr
; }
170 /* NIR shaders need to use GLSL types so let's initialize them here */
171 glsl_type_singleton_init_or_ref();
173 list_inithead(&This
->update_buffers
);
174 list_inithead(&This
->update_textures
);
175 list_inithead(&This
->managed_buffers
);
176 list_inithead(&This
->managed_textures
);
178 This
->screen
= pScreen
;
179 This
->screen_sw
= pCTX
->ref
;
182 This
->params
= *pCreationParameters
;
184 This
->present
= pPresentationGroup
;
185 This
->minor_version_num
= minorVersionNum
;
187 IDirect3D9_AddRef(This
->d3d9
);
188 ID3DPresentGroup_AddRef(This
->present
);
190 if (!(This
->params
.BehaviorFlags
& D3DCREATE_FPU_PRESERVE
))
193 if (This
->params
.BehaviorFlags
& D3DCREATE_SOFTWARE_VERTEXPROCESSING
) {
194 DBG("Application asked full Software Vertex Processing.\n");
196 This
->may_swvp
= true;
199 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
) {
200 DBG("Application asked mixed Software Vertex Processing.\n");
201 This
->may_swvp
= true;
203 This
->context
.swvp
= This
->swvp
;
204 /* TODO: check if swvp is resetted by device Resets */
206 if (This
->may_swvp
&&
207 (This
->screen
->get_shader_param(This
->screen
, PIPE_SHADER_VERTEX
,
208 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
)
209 < (NINE_MAX_CONST_F_SWVP
/2) * sizeof(float[4]) ||
210 This
->screen
->get_shader_param(This
->screen
, PIPE_SHADER_VERTEX
,
211 PIPE_SHADER_CAP_MAX_CONST_BUFFERS
) < 5)) {
212 /* Note: We just go on, some apps never use the abilities of
213 * swvp, and just set more constants than allowed at init.
214 * Only cards we support that are affected are the r500 */
215 WARN("Card unable to handle Software Vertex Processing. Game may fail\n");
218 /* When may_swvp, SetConstant* limits are different */
220 This
->caps
.MaxVertexShaderConst
= NINE_MAX_CONST_F_SWVP
;
222 This
->pure
= !!(This
->params
.BehaviorFlags
& D3DCREATE_PUREDEVICE
);
224 This
->context
.pipe
= This
->screen
->context_create(This
->screen
, NULL
, 0);
225 This
->pipe_secondary
= This
->screen
->context_create(This
->screen
, NULL
, 0);
226 if (!This
->context
.pipe
|| !This
->pipe_secondary
) { return E_OUTOFMEMORY
; } /* guess */
227 This
->pipe_sw
= This
->screen_sw
->context_create(This
->screen_sw
, NULL
, 0);
228 if (!This
->pipe_sw
) { return E_OUTOFMEMORY
; }
230 This
->context
.cso
= cso_create_context(This
->context
.pipe
, 0);
231 if (!This
->context
.cso
) { return E_OUTOFMEMORY
; } /* also a guess */
232 This
->cso_sw
= cso_create_context(This
->pipe_sw
, 0);
233 if (!This
->cso_sw
) { return E_OUTOFMEMORY
; }
235 /* Create first, it messes up our state. */
236 This
->hud
= hud_create(This
->context
.cso
, NULL
); /* NULL result is fine */
238 /* Available memory counter. Updated only for allocations with this device
239 * instance. This is the Win 7 behavior.
240 * Win XP shares this counter across multiple devices. */
241 This
->available_texture_mem
= This
->screen
->get_param(This
->screen
, PIPE_CAP_VIDEO_MEMORY
);
242 This
->available_texture_mem
<<= 20;
244 /* To prevent overflows for 32bits apps - Not sure about this one */
245 This
->available_texture_limit
= MAX2(This
->available_texture_limit
, UINT_MAX
- (64 << 20));
247 /* We cap texture memory usage to 95% of what is reported free initially
248 * This helps get closer Win behaviour. For example VertexBuffer allocation
249 * still succeeds when texture allocation fails. */
250 This
->available_texture_limit
= This
->available_texture_mem
* 5LL / 100LL;
252 /* create implicit swapchains */
253 This
->nswapchains
= ID3DPresentGroup_GetMultiheadCount(This
->present
);
254 This
->swapchains
= CALLOC(This
->nswapchains
,
255 sizeof(struct NineSwapChain9
*));
256 if (!This
->swapchains
) { return E_OUTOFMEMORY
; }
258 for (i
= 0; i
< This
->nswapchains
; ++i
) {
259 ID3DPresent
*present
;
261 hr
= ID3DPresentGroup_GetPresent(This
->present
, i
, &present
);
266 D3DDISPLAYMODEEX
*mode
= NULL
;
267 struct NineSwapChain9Ex
**ret
=
268 (struct NineSwapChain9Ex
**)&This
->swapchains
[i
];
270 if (pFullscreenDisplayMode
) mode
= &(pFullscreenDisplayMode
[i
]);
271 /* when this is a Device9Ex, it should create SwapChain9Exs */
272 hr
= NineSwapChain9Ex_new(This
, TRUE
, present
,
273 &pPresentationParameters
[i
], pCTX
,
274 This
->params
.hFocusWindow
, mode
, ret
);
276 hr
= NineSwapChain9_new(This
, TRUE
, present
,
277 &pPresentationParameters
[i
], pCTX
,
278 This
->params
.hFocusWindow
,
279 &This
->swapchains
[i
]);
282 ID3DPresent_Release(present
);
285 NineUnknown_ConvertRefToBind(NineUnknown(This
->swapchains
[i
]));
287 hr
= NineSwapChain9_GetBackBuffer(This
->swapchains
[i
], 0,
288 D3DBACKBUFFER_TYPE_MONO
,
289 (IDirect3DSurface9
**)
293 NineUnknown_ConvertRefToBind(NineUnknown(This
->state
.rt
[i
]));
294 nine_bind(&This
->context
.rt
[i
], This
->state
.rt
[i
]);
297 /* Initialize CSMT */
298 /* r600, radeonsi and iris are thread safe. */
299 if (pCTX
->csmt_force
== 1)
300 This
->csmt_active
= true;
301 else if (pCTX
->csmt_force
== 0)
302 This
->csmt_active
= false;
303 else if (strstr(pScreen
->get_name(pScreen
), "AMD") != NULL
)
304 This
->csmt_active
= true;
305 else if (strstr(pScreen
->get_name(pScreen
), "Intel") != NULL
)
306 This
->csmt_active
= true;
308 /* We rely on u_upload_mgr using persistent coherent buffers (which don't
309 * require flush to work in multi-pipe_context scenario) for vertex and
311 if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT
))
312 This
->csmt_active
= false;
314 if (This
->csmt_active
) {
315 This
->csmt_ctx
= nine_csmt_create(This
);
317 return E_OUTOFMEMORY
;
320 if (This
->csmt_active
)
321 DBG("\033[1;32mCSMT is active\033[0m\n");
323 This
->workarounds
.dynamic_texture_workaround
= pCTX
->dynamic_texture_workaround
;
325 This
->buffer_upload
= nine_upload_create(This
->pipe_secondary
, 4 * 1024 * 1024, 4);
327 /* Initialize a dummy VBO to be used when a vertex declaration does not
328 * specify all the inputs needed by vertex shader, on win default behavior
329 * is to pass 0,0,0,0 to the shader */
331 struct pipe_transfer
*transfer
;
332 struct pipe_resource tmpl
;
336 memset(&tmpl
, 0, sizeof(tmpl
));
337 tmpl
.target
= PIPE_BUFFER
;
338 tmpl
.format
= PIPE_FORMAT_R8_UNORM
;
339 tmpl
.width0
= 16; /* 4 floats */
345 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
346 tmpl
.bind
= PIPE_BIND_VERTEX_BUFFER
;
348 This
->dummy_vbo
= pScreen
->resource_create(pScreen
, &tmpl
);
350 if (!This
->dummy_vbo
)
351 return D3DERR_OUTOFVIDEOMEMORY
;
353 u_box_1d(0, 16, &box
);
354 data
= This
->context
.pipe
->transfer_map(This
->context
.pipe
, This
->dummy_vbo
, 0,
355 PIPE_TRANSFER_WRITE
|
356 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
361 This
->context
.pipe
->transfer_unmap(This
->context
.pipe
, transfer
);
364 This
->cursor
.software
= FALSE
;
365 This
->cursor
.hotspot
.x
= -1;
366 This
->cursor
.hotspot
.y
= -1;
367 This
->cursor
.w
= This
->cursor
.h
= 0;
368 This
->cursor
.visible
= FALSE
;
369 if (ID3DPresent_GetCursorPos(This
->swapchains
[0]->present
, &This
->cursor
.pos
) != S_OK
) {
370 This
->cursor
.pos
.x
= 0;
371 This
->cursor
.pos
.y
= 0;
375 struct pipe_resource tmpl
;
376 memset(&tmpl
, 0, sizeof(tmpl
));
377 tmpl
.target
= PIPE_TEXTURE_2D
;
378 tmpl
.format
= PIPE_FORMAT_R8G8B8A8_UNORM
;
385 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
386 tmpl
.bind
= PIPE_BIND_CURSOR
| PIPE_BIND_SAMPLER_VIEW
;
389 This
->cursor
.image
= pScreen
->resource_create(pScreen
, &tmpl
);
390 if (!This
->cursor
.image
)
391 return D3DERR_OUTOFVIDEOMEMORY
;
393 /* For uploading 32x32 (argb) cursor */
394 This
->cursor
.hw_upload_temp
= MALLOC(32 * 4 * 32);
395 if (!This
->cursor
.hw_upload_temp
)
396 return D3DERR_OUTOFVIDEOMEMORY
;
399 /* Create constant buffers. */
401 unsigned max_const_vs
, max_const_ps
;
403 /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
404 * we have to take in some more slots for int and bool*/
405 max_const_vs
= _min(pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
,
406 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
) /
409 /* ps 3.0: 224 float constants. All cards supported support at least
410 * 256 constants for ps */
411 max_const_ps
= NINE_MAX_CONST_F_PS3
+ (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
413 This
->max_vs_const_f
= max_const_vs
-
414 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
415 This
->max_ps_const_f
= max_const_ps
-
416 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
418 This
->vs_const_size
= max_const_vs
* sizeof(float[4]);
419 This
->ps_const_size
= max_const_ps
* sizeof(float[4]);
420 /* Include space for I,B constants for user constbuf. */
421 if (This
->may_swvp
) {
422 This
->state
.vs_const_f
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
423 This
->context
.vs_const_f_swvp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
424 if (!This
->context
.vs_const_f_swvp
)
425 return E_OUTOFMEMORY
;
426 This
->state
.vs_lconstf_temp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
427 This
->context
.vs_lconstf_temp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
428 This
->state
.vs_const_i
= CALLOC(NINE_MAX_CONST_I_SWVP
* sizeof(int[4]), 1);
429 This
->context
.vs_const_i
= CALLOC(NINE_MAX_CONST_I_SWVP
* sizeof(int[4]), 1);
430 This
->state
.vs_const_b
= CALLOC(NINE_MAX_CONST_B_SWVP
* sizeof(BOOL
), 1);
431 This
->context
.vs_const_b
= CALLOC(NINE_MAX_CONST_B_SWVP
* sizeof(BOOL
), 1);
433 This
->state
.vs_const_f
= CALLOC(NINE_MAX_CONST_F
* sizeof(float[4]), 1);
434 This
->context
.vs_const_f_swvp
= NULL
;
435 This
->state
.vs_lconstf_temp
= CALLOC(This
->vs_const_size
,1);
436 This
->context
.vs_lconstf_temp
= CALLOC(This
->vs_const_size
,1);
437 This
->state
.vs_const_i
= CALLOC(NINE_MAX_CONST_I
* sizeof(int[4]), 1);
438 This
->context
.vs_const_i
= CALLOC(NINE_MAX_CONST_I
* sizeof(int[4]), 1);
439 This
->state
.vs_const_b
= CALLOC(NINE_MAX_CONST_B
* sizeof(BOOL
), 1);
440 This
->context
.vs_const_b
= CALLOC(NINE_MAX_CONST_B
* sizeof(BOOL
), 1);
442 This
->context
.vs_const_f
= CALLOC(This
->vs_const_size
, 1);
443 This
->state
.ps_const_f
= CALLOC(This
->ps_const_size
, 1);
444 This
->context
.ps_const_f
= CALLOC(This
->ps_const_size
, 1);
445 This
->context
.ps_lconstf_temp
= CALLOC(This
->ps_const_size
,1);
446 if (!This
->state
.vs_const_f
|| !This
->context
.vs_const_f
||
447 !This
->state
.ps_const_f
|| !This
->context
.ps_const_f
||
448 !This
->state
.vs_lconstf_temp
|| !This
->context
.vs_lconstf_temp
||
449 !This
->context
.ps_lconstf_temp
||
450 !This
->state
.vs_const_i
|| !This
->context
.vs_const_i
||
451 !This
->state
.vs_const_b
|| !This
->context
.vs_const_b
)
452 return E_OUTOFMEMORY
;
454 if (strstr(pScreen
->get_name(pScreen
), "AMD") ||
455 strstr(pScreen
->get_name(pScreen
), "ATI")) {
456 This
->driver_bugs
.buggy_barycentrics
= TRUE
;
460 /* allocate dummy texture/sampler for when there are missing ones bound */
462 struct pipe_resource tmplt
;
463 struct pipe_sampler_view templ
;
464 struct pipe_sampler_state samp
;
465 memset(&tmplt
, 0, sizeof(tmplt
));
466 memset(&samp
, 0, sizeof(samp
));
468 tmplt
.target
= PIPE_TEXTURE_2D
;
472 tmplt
.last_level
= 0;
473 tmplt
.array_size
= 1;
474 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
476 tmplt
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
477 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
;
478 tmplt
.nr_samples
= 0;
480 This
->dummy_texture
= This
->screen
->resource_create(This
->screen
, &tmplt
);
481 if (!This
->dummy_texture
)
482 return D3DERR_DRIVERINTERNALERROR
;
484 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
485 templ
.u
.tex
.first_layer
= 0;
486 templ
.u
.tex
.last_layer
= 0;
487 templ
.u
.tex
.first_level
= 0;
488 templ
.u
.tex
.last_level
= 0;
489 templ
.swizzle_r
= PIPE_SWIZZLE_0
;
490 templ
.swizzle_g
= PIPE_SWIZZLE_0
;
491 templ
.swizzle_b
= PIPE_SWIZZLE_0
;
492 templ
.swizzle_a
= PIPE_SWIZZLE_1
;
493 templ
.target
= This
->dummy_texture
->target
;
495 This
->dummy_sampler_view
= This
->context
.pipe
->create_sampler_view(This
->context
.pipe
, This
->dummy_texture
, &templ
);
496 if (!This
->dummy_sampler_view
)
497 return D3DERR_DRIVERINTERNALERROR
;
499 samp
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
500 samp
.max_lod
= 15.0f
;
501 samp
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
502 samp
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
503 samp
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
504 samp
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
505 samp
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
506 samp
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
507 samp
.compare_func
= PIPE_FUNC_LEQUAL
;
508 samp
.normalized_coords
= 1;
509 samp
.seamless_cube_map
= 0;
510 This
->dummy_sampler_state
= samp
;
513 /* Allocate upload helper for drivers that suck (from st pov ;). */
515 This
->driver_caps
.user_vbufs
= GET_PCAP(USER_VERTEX_BUFFERS
) && !This
->csmt_active
;
516 This
->driver_caps
.user_sw_vbufs
= This
->screen_sw
->get_param(This
->screen_sw
, PIPE_CAP_USER_VERTEX_BUFFERS
);
517 This
->vertex_uploader
= This
->csmt_active
? This
->pipe_secondary
->stream_uploader
: This
->context
.pipe
->stream_uploader
;
518 This
->driver_caps
.window_space_position_support
= GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION
);
519 This
->driver_caps
.vs_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
, PIPE_SHADER_CAP_INTEGERS
);
520 This
->driver_caps
.ps_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_INTEGERS
);
521 This
->driver_caps
.offset_units_unscaled
= GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED
);
523 This
->context
.inline_constants
= pCTX
->shader_inline_constants
;
524 /* Code would be needed when integers are not available to correctly
525 * handle the conversion of integer constants */
526 This
->context
.inline_constants
&= This
->driver_caps
.vs_integer
&& This
->driver_caps
.ps_integer
;
528 nine_ff_init(This
); /* initialize fixed function code */
530 NineDevice9_SetDefaultState(This
, FALSE
);
533 struct pipe_poly_stipple stipple
;
534 memset(&stipple
, ~0, sizeof(stipple
));
535 This
->context
.pipe
->set_polygon_stipple(This
->context
.pipe
, &stipple
);
538 This
->update
= &This
->state
;
540 nine_state_init_sw(This
);
542 ID3DPresentGroup_Release(This
->present
);
543 nine_context_update_state(This
); /* Some drivers needs states to be initialized */
544 nine_csmt_process(This
);
551 NineDevice9_dtor( struct NineDevice9
*This
)
555 DBG("This=%p\n", This
);
557 /* Flush all pending commands to get refcount right,
558 * and properly release bound objects. It is ok to still
559 * execute commands while we are in device dtor, because
560 * we haven't released anything yet. Note that no pending
561 * command can increase the device refcount. */
562 if (This
->csmt_active
&& This
->csmt_ctx
) {
563 nine_csmt_process(This
);
564 nine_csmt_destroy(This
, This
->csmt_ctx
);
565 This
->csmt_active
= FALSE
;
566 This
->csmt_ctx
= NULL
;
570 nine_state_destroy_sw(This
);
571 nine_device_state_clear(This
);
572 nine_context_clear(This
);
574 nine_bind(&This
->record
, NULL
);
576 pipe_sampler_view_reference(&This
->dummy_sampler_view
, NULL
);
577 pipe_resource_reference(&This
->dummy_texture
, NULL
);
578 pipe_resource_reference(&This
->dummy_vbo
, NULL
);
579 FREE(This
->state
.vs_const_f
);
580 FREE(This
->context
.vs_const_f
);
581 FREE(This
->state
.ps_const_f
);
582 FREE(This
->context
.ps_const_f
);
583 FREE(This
->state
.vs_lconstf_temp
);
584 FREE(This
->context
.vs_lconstf_temp
);
585 FREE(This
->context
.ps_lconstf_temp
);
586 FREE(This
->state
.vs_const_i
);
587 FREE(This
->context
.vs_const_i
);
588 FREE(This
->state
.vs_const_b
);
589 FREE(This
->context
.vs_const_b
);
590 FREE(This
->context
.vs_const_f_swvp
);
592 pipe_resource_reference(&This
->cursor
.image
, NULL
);
593 FREE(This
->cursor
.hw_upload_temp
);
595 if (This
->swapchains
) {
596 for (i
= 0; i
< This
->nswapchains
; ++i
)
597 if (This
->swapchains
[i
])
598 NineUnknown_Unbind(NineUnknown(This
->swapchains
[i
]));
599 FREE(This
->swapchains
);
602 if (This
->buffer_upload
)
603 nine_upload_destroy(This
->buffer_upload
);
605 /* Destroy cso first */
606 if (This
->context
.cso
) { cso_destroy_context(This
->context
.cso
); }
607 if (This
->cso_sw
) { cso_destroy_context(This
->cso_sw
); }
608 if (This
->context
.pipe
&& This
->context
.pipe
->destroy
) { This
->context
.pipe
->destroy(This
->context
.pipe
); }
609 if (This
->pipe_secondary
&& This
->pipe_secondary
->destroy
) { This
->pipe_secondary
->destroy(This
->pipe_secondary
); }
610 if (This
->pipe_sw
&& This
->pipe_sw
->destroy
) { This
->pipe_sw
->destroy(This
->pipe_sw
); }
612 if (This
->present
) { ID3DPresentGroup_Release(This
->present
); }
613 if (This
->d3d9
) { IDirect3D9_Release(This
->d3d9
); }
615 NineUnknown_dtor(&This
->base
);
616 glsl_type_singleton_decref();
620 NineDevice9_GetScreen( struct NineDevice9
*This
)
625 struct pipe_context
*
626 NineDevice9_GetPipe( struct NineDevice9
*This
)
628 return nine_context_get_pipe(This
);
632 NineDevice9_GetCaps( struct NineDevice9
*This
)
638 NineDevice9_PauseRecording( struct NineDevice9
*This
)
641 This
->update
= &This
->state
;
642 This
->is_recording
= FALSE
;
647 NineDevice9_ResumeRecording( struct NineDevice9
*This
)
650 This
->update
= &This
->record
->state
;
651 This
->is_recording
= TRUE
;
656 NineDevice9_TestCooperativeLevel( struct NineDevice9
*This
)
658 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
659 This
->device_needs_reset
= TRUE
;
660 return D3DERR_DEVICELOST
;
661 } else if (NineSwapChain9_ResolutionMismatch(This
->swapchains
[0])) {
662 This
->device_needs_reset
= TRUE
;
663 return D3DERR_DEVICENOTRESET
;
664 } else if (This
->device_needs_reset
) {
665 return D3DERR_DEVICENOTRESET
;
672 NineDevice9_GetAvailableTextureMem( struct NineDevice9
*This
)
674 return This
->available_texture_mem
;
678 NineDevice9_EvictManagedResourcesInternal( struct NineDevice9
*This
)
680 struct NineBaseTexture9
*tex
;
682 DBG("This=%p\n", This
);
684 /* This function is called internally when an allocation fails.
685 * We are supposed to release old unused managed textures/buffers,
686 * until we have enough space for the allocation.
687 * For now just release everything, except the bound textures,
688 * as this function can be called when uploading bound textures.
690 LIST_FOR_EACH_ENTRY(tex
, &This
->managed_textures
, list2
) {
691 if (!tex
->bind_count
)
692 NineBaseTexture9_UnLoad(tex
);
697 NineDevice9_EvictManagedResources( struct NineDevice9
*This
)
699 struct NineBaseTexture9
*tex
;
700 struct NineBuffer9
*buf
;
702 DBG("This=%p\n", This
);
703 LIST_FOR_EACH_ENTRY(tex
, &This
->managed_textures
, list2
) {
704 NineBaseTexture9_UnLoad(tex
);
706 /* Vertex/index buffers don't take a lot of space and aren't accounted
707 * for d3d memory usage. Instead of actually freeing from memory,
708 * just mark the buffer dirty to trigger a re-upload later. We
709 * could just ignore, but some bad behaving apps could rely on it (if
710 * they write outside the locked regions typically). */
711 LIST_FOR_EACH_ENTRY(buf
, &This
->managed_buffers
, managed
.list2
) {
712 NineBuffer9_SetDirty(buf
);
719 NineDevice9_GetDirect3D( struct NineDevice9
*This
,
720 IDirect3D9
**ppD3D9
)
722 user_assert(ppD3D9
!= NULL
, E_POINTER
);
723 IDirect3D9_AddRef(This
->d3d9
);
724 *ppD3D9
= This
->d3d9
;
729 NineDevice9_GetDeviceCaps( struct NineDevice9
*This
,
732 user_assert(pCaps
!= NULL
, D3DERR_INVALIDCALL
);
738 NineDevice9_GetDisplayMode( struct NineDevice9
*This
,
740 D3DDISPLAYMODE
*pMode
)
742 DBG("This=%p iSwapChain=%u pMode=%p\n", This
, iSwapChain
, pMode
);
744 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
746 return NineSwapChain9_GetDisplayMode(This
->swapchains
[iSwapChain
], pMode
);
750 NineDevice9_GetCreationParameters( struct NineDevice9
*This
,
751 D3DDEVICE_CREATION_PARAMETERS
*pParameters
)
753 user_assert(pParameters
!= NULL
, D3DERR_INVALIDCALL
);
754 *pParameters
= This
->params
;
759 NineDevice9_SetCursorProperties( struct NineDevice9
*This
,
762 IDirect3DSurface9
*pCursorBitmap
)
764 struct NineSurface9
*surf
= NineSurface9(pCursorBitmap
);
765 struct pipe_context
*pipe
= NineDevice9_GetPipe(This
);
767 struct pipe_transfer
*transfer
;
771 DBG_FLAG(DBG_SWAPCHAIN
, "This=%p XHotSpot=%u YHotSpot=%u "
772 "pCursorBitmap=%p\n", This
, XHotSpot
, YHotSpot
, pCursorBitmap
);
774 user_assert(pCursorBitmap
, D3DERR_INVALIDCALL
);
775 user_assert(surf
->desc
.Format
== D3DFMT_A8R8G8B8
, D3DERR_INVALIDCALL
);
777 if (This
->swapchains
[0]->params
.Windowed
) {
778 This
->cursor
.w
= MIN2(surf
->desc
.Width
, 32);
779 This
->cursor
.h
= MIN2(surf
->desc
.Height
, 32);
780 hw_cursor
= 1; /* always use hw cursor for windowed mode */
782 This
->cursor
.w
= MIN2(surf
->desc
.Width
, This
->cursor
.image
->width0
);
783 This
->cursor
.h
= MIN2(surf
->desc
.Height
, This
->cursor
.image
->height0
);
784 hw_cursor
= This
->cursor
.w
== 32 && This
->cursor
.h
== 32;
787 u_box_origin_2d(This
->cursor
.w
, This
->cursor
.h
, &box
);
789 ptr
= pipe
->transfer_map(pipe
, This
->cursor
.image
, 0,
790 PIPE_TRANSFER_WRITE
|
791 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
794 ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR
);
796 This
->cursor
.hotspot
.x
= XHotSpot
;
797 This
->cursor
.hotspot
.y
= YHotSpot
;
799 /* Copy cursor image to internal storage. */
803 const struct util_format_description
*sfmt
=
804 util_format_description(surf
->base
.info
.format
);
807 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, D3DLOCK_READONLY
);
809 ret_err("Failed to map cursor source image.\n",
810 D3DERR_DRIVERINTERNALERROR
);
812 sfmt
->unpack_rgba_8unorm(ptr
, transfer
->stride
,
813 lock
.pBits
, lock
.Pitch
,
814 This
->cursor
.w
, This
->cursor
.h
);
817 void *data
= lock
.pBits
;
818 /* SetCursor assumes 32x32 argb with pitch 128 */
819 if (lock
.Pitch
!= 128) {
820 sfmt
->unpack_rgba_8unorm(This
->cursor
.hw_upload_temp
, 128,
821 lock
.pBits
, lock
.Pitch
,
823 data
= This
->cursor
.hw_upload_temp
;
825 hw_cursor
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
,
827 &This
->cursor
.hotspot
,
828 This
->cursor
.visible
) == D3D_OK
;
831 NineSurface9_UnlockRect(surf
);
833 pipe
->transfer_unmap(pipe
, transfer
);
835 /* hide cursor if we emulate it */
837 ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, FALSE
);
838 This
->cursor
.software
= !hw_cursor
;
844 NineDevice9_SetCursorPosition( struct NineDevice9
*This
,
849 struct NineSwapChain9
*swap
= This
->swapchains
[0];
851 DBG("This=%p X=%d Y=%d Flags=%d\n", This
, X
, Y
, Flags
);
853 /* present >= v1.4 handles this itself */
854 if (This
->minor_version_num
< 4) {
855 if (This
->cursor
.pos
.x
== X
&& This
->cursor
.pos
.y
== Y
)
859 This
->cursor
.pos
.x
= X
;
860 This
->cursor
.pos
.y
= Y
;
862 if (!This
->cursor
.software
)
863 This
->cursor
.software
= ID3DPresent_SetCursorPos(swap
->present
, &This
->cursor
.pos
) != D3D_OK
;
867 NineDevice9_ShowCursor( struct NineDevice9
*This
,
870 BOOL old
= This
->cursor
.visible
;
872 DBG("This=%p bShow=%d\n", This
, (int) bShow
);
874 /* No-op until a cursor is set in d3d */
875 if (This
->cursor
.hotspot
.x
== -1)
878 This
->cursor
.visible
= bShow
;
879 /* Note: Don't optimize by avoiding the call if This->cursor.visible
880 * hasn't changed. One has to keep in mind the app may do SetCursor
881 * calls outside d3d, thus such an optimization affects behaviour. */
882 if (!This
->cursor
.software
)
883 This
->cursor
.software
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, bShow
) != D3D_OK
;
889 NineDevice9_CreateAdditionalSwapChain( struct NineDevice9
*This
,
890 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
891 IDirect3DSwapChain9
**pSwapChain
)
893 struct NineSwapChain9
*swapchain
, *tmplt
= This
->swapchains
[0];
894 ID3DPresent
*present
;
897 DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",
898 This
, pPresentationParameters
, pSwapChain
);
900 user_assert(pPresentationParameters
, D3DERR_INVALIDCALL
);
901 user_assert(pSwapChain
!= NULL
, D3DERR_INVALIDCALL
);
902 user_assert(tmplt
->params
.Windowed
&& pPresentationParameters
->Windowed
, D3DERR_INVALIDCALL
);
904 /* TODO: this deserves more tests */
905 if (!pPresentationParameters
->hDeviceWindow
)
906 pPresentationParameters
->hDeviceWindow
= This
->params
.hFocusWindow
;
908 hr
= ID3DPresentGroup_CreateAdditionalPresent(This
->present
, pPresentationParameters
, &present
);
913 hr
= NineSwapChain9_new(This
, FALSE
, present
, pPresentationParameters
,
915 tmplt
->params
.hDeviceWindow
,
920 *pSwapChain
= (IDirect3DSwapChain9
*)swapchain
;
925 NineDevice9_GetSwapChain( struct NineDevice9
*This
,
927 IDirect3DSwapChain9
**pSwapChain
)
929 user_assert(pSwapChain
!= NULL
, D3DERR_INVALIDCALL
);
932 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
934 NineUnknown_AddRef(NineUnknown(This
->swapchains
[iSwapChain
]));
935 *pSwapChain
= (IDirect3DSwapChain9
*)This
->swapchains
[iSwapChain
];
941 NineDevice9_GetNumberOfSwapChains( struct NineDevice9
*This
)
943 return This
->nswapchains
;
947 NineDevice9_Reset( struct NineDevice9
*This
,
948 D3DPRESENT_PARAMETERS
*pPresentationParameters
)
953 DBG("This=%p pPresentationParameters=%p\n", This
, pPresentationParameters
);
955 user_assert(pPresentationParameters
!= NULL
, D3DERR_INVALIDCALL
);
957 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
958 This
->device_needs_reset
= TRUE
;
959 return D3DERR_DEVICELOST
;
962 for (i
= 0; i
< This
->nswapchains
; ++i
) {
963 D3DPRESENT_PARAMETERS
*params
= &pPresentationParameters
[i
];
964 hr
= NineSwapChain9_Resize(This
->swapchains
[i
], params
, NULL
);
969 nine_csmt_process(This
);
970 nine_device_state_clear(This
);
971 nine_context_clear(This
);
973 NineDevice9_SetDefaultState(This
, TRUE
);
974 NineDevice9_SetRenderTarget(
975 This
, 0, (IDirect3DSurface9
*)This
->swapchains
[0]->buffers
[0]);
976 /* XXX: better use GetBackBuffer here ? */
978 This
->device_needs_reset
= (hr
!= D3D_OK
);
983 NineDevice9_Present( struct NineDevice9
*This
,
984 const RECT
*pSourceRect
,
985 const RECT
*pDestRect
,
986 HWND hDestWindowOverride
,
987 const RGNDATA
*pDirtyRegion
)
992 DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",
993 This
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
);
995 /* XXX is this right? */
996 for (i
= 0; i
< This
->nswapchains
; ++i
) {
997 hr
= NineSwapChain9_Present(This
->swapchains
[i
], pSourceRect
, pDestRect
,
998 hDestWindowOverride
, pDirtyRegion
, 0);
999 if (FAILED(hr
)) { return hr
; }
1006 NineDevice9_GetBackBuffer( struct NineDevice9
*This
,
1009 D3DBACKBUFFER_TYPE Type
,
1010 IDirect3DSurface9
**ppBackBuffer
)
1012 user_assert(ppBackBuffer
!= NULL
, D3DERR_INVALIDCALL
);
1013 /* return NULL on error */
1014 *ppBackBuffer
= NULL
;
1015 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
1017 return NineSwapChain9_GetBackBuffer(This
->swapchains
[iSwapChain
],
1018 iBackBuffer
, Type
, ppBackBuffer
);
1022 NineDevice9_GetRasterStatus( struct NineDevice9
*This
,
1024 D3DRASTER_STATUS
*pRasterStatus
)
1026 user_assert(pRasterStatus
!= NULL
, D3DERR_INVALIDCALL
);
1027 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
1029 return NineSwapChain9_GetRasterStatus(This
->swapchains
[iSwapChain
],
1034 NineDevice9_SetDialogBoxMode( struct NineDevice9
*This
,
1035 BOOL bEnableDialogs
)
1037 STUB(D3DERR_INVALIDCALL
);
1041 NineDevice9_SetGammaRamp( struct NineDevice9
*This
,
1044 const D3DGAMMARAMP
*pRamp
)
1046 DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This
,
1047 iSwapChain
, Flags
, pRamp
);
1049 user_warn(iSwapChain
>= This
->nswapchains
);
1052 if (pRamp
&& (iSwapChain
< This
->nswapchains
)) {
1053 struct NineSwapChain9
*swap
= This
->swapchains
[iSwapChain
];
1054 swap
->gamma
= *pRamp
;
1055 ID3DPresent_SetGammaRamp(swap
->present
, pRamp
, swap
->params
.hDeviceWindow
);
1060 NineDevice9_GetGammaRamp( struct NineDevice9
*This
,
1062 D3DGAMMARAMP
*pRamp
)
1064 DBG("This=%p iSwapChain=%u pRamp=%p\n", This
, iSwapChain
, pRamp
);
1066 user_warn(iSwapChain
>= This
->nswapchains
);
1069 if (pRamp
&& (iSwapChain
< This
->nswapchains
))
1070 *pRamp
= This
->swapchains
[iSwapChain
]->gamma
;
1074 NineDevice9_CreateTexture( struct NineDevice9
*This
,
1081 IDirect3DTexture9
**ppTexture
,
1082 HANDLE
*pSharedHandle
)
1084 struct NineTexture9
*tex
;
1087 DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
1088 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Levels
,
1089 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1090 nine_D3DPOOL_to_str(Pool
), ppTexture
, pSharedHandle
);
1092 user_assert(ppTexture
!= NULL
, D3DERR_INVALIDCALL
);
1094 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DMAP
|
1095 D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
1096 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
;
1100 hr
= NineTexture9_new(This
, Width
, Height
, Levels
, Usage
, Format
, Pool
,
1101 &tex
, pSharedHandle
);
1103 *ppTexture
= (IDirect3DTexture9
*)tex
;
1109 NineDevice9_CreateVolumeTexture( struct NineDevice9
*This
,
1117 IDirect3DVolumeTexture9
**ppVolumeTexture
,
1118 HANDLE
*pSharedHandle
)
1120 struct NineVolumeTexture9
*tex
;
1123 DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
1124 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Depth
, Levels
,
1125 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1126 nine_D3DPOOL_to_str(Pool
), ppVolumeTexture
, pSharedHandle
);
1128 user_assert(ppVolumeTexture
!= NULL
, D3DERR_INVALIDCALL
);
1130 Usage
&= D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1131 D3DUSAGE_SOFTWAREPROCESSING
;
1133 *ppVolumeTexture
= NULL
;
1135 hr
= NineVolumeTexture9_new(This
, Width
, Height
, Depth
, Levels
,
1136 Usage
, Format
, Pool
, &tex
, pSharedHandle
);
1138 *ppVolumeTexture
= (IDirect3DVolumeTexture9
*)tex
;
1144 NineDevice9_CreateCubeTexture( struct NineDevice9
*This
,
1150 IDirect3DCubeTexture9
**ppCubeTexture
,
1151 HANDLE
*pSharedHandle
)
1153 struct NineCubeTexture9
*tex
;
1156 DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
1157 "pSharedHandle=%p\n", This
, EdgeLength
, Levels
,
1158 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1159 nine_D3DPOOL_to_str(Pool
), ppCubeTexture
, pSharedHandle
);
1161 user_assert(ppCubeTexture
!= NULL
, D3DERR_INVALIDCALL
);
1163 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DYNAMIC
|
1164 D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
1165 D3DUSAGE_SOFTWAREPROCESSING
;
1167 *ppCubeTexture
= NULL
;
1169 hr
= NineCubeTexture9_new(This
, EdgeLength
, Levels
, Usage
, Format
, Pool
,
1170 &tex
, pSharedHandle
);
1172 *ppCubeTexture
= (IDirect3DCubeTexture9
*)tex
;
1178 NineDevice9_CreateVertexBuffer( struct NineDevice9
*This
,
1183 IDirect3DVertexBuffer9
**ppVertexBuffer
,
1184 HANDLE
*pSharedHandle
)
1186 struct NineVertexBuffer9
*buf
;
1188 D3DVERTEXBUFFER_DESC desc
;
1190 DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
1191 This
, Length
, Usage
, FVF
, Pool
, ppVertexBuffer
, pSharedHandle
);
1193 user_assert(ppVertexBuffer
!= NULL
, D3DERR_INVALIDCALL
);
1194 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1196 desc
.Format
= D3DFMT_VERTEXDATA
;
1197 desc
.Type
= D3DRTYPE_VERTEXBUFFER
;
1198 desc
.Usage
= Usage
&
1199 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1200 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1201 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
|
1202 D3DUSAGE_WRITEONLY
);
1207 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1208 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1210 hr
= NineVertexBuffer9_new(This
, &desc
, &buf
);
1212 *ppVertexBuffer
= (IDirect3DVertexBuffer9
*)buf
;
1217 NineDevice9_CreateIndexBuffer( struct NineDevice9
*This
,
1222 IDirect3DIndexBuffer9
**ppIndexBuffer
,
1223 HANDLE
*pSharedHandle
)
1225 struct NineIndexBuffer9
*buf
;
1227 D3DINDEXBUFFER_DESC desc
;
1229 DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
1230 "pSharedHandle=%p\n", This
, Length
, Usage
,
1231 d3dformat_to_string(Format
), Pool
, ppIndexBuffer
, pSharedHandle
);
1233 user_assert(ppIndexBuffer
!= NULL
, D3DERR_INVALIDCALL
);
1234 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1236 desc
.Format
= Format
;
1237 desc
.Type
= D3DRTYPE_INDEXBUFFER
;
1238 desc
.Usage
= Usage
&
1239 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1240 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1241 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_WRITEONLY
);
1245 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1246 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1248 hr
= NineIndexBuffer9_new(This
, &desc
, &buf
);
1250 *ppIndexBuffer
= (IDirect3DIndexBuffer9
*)buf
;
1255 create_zs_or_rt_surface(struct NineDevice9
*This
,
1256 unsigned type
, /* 0 = RT, 1 = ZS, 2 = plain */
1258 UINT Width
, UINT Height
,
1260 D3DMULTISAMPLE_TYPE MultiSample
,
1261 DWORD MultisampleQuality
,
1262 BOOL Discard_or_Lockable
,
1263 IDirect3DSurface9
**ppSurface
,
1264 HANDLE
*pSharedHandle
)
1266 struct NineSurface9
*surface
;
1268 D3DSURFACE_DESC desc
;
1270 DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
1271 "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
1272 This
, type
, nine_D3DPOOL_to_str(Pool
), Width
, Height
,
1273 d3dformat_to_string(Format
), MultiSample
, MultisampleQuality
,
1274 Discard_or_Lockable
, ppSurface
, pSharedHandle
);
1277 DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
1279 user_assert(Width
&& Height
, D3DERR_INVALIDCALL
);
1280 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1282 desc
.Format
= Format
;
1283 desc
.Type
= D3DRTYPE_SURFACE
;
1286 desc
.MultiSampleType
= MultiSample
;
1287 desc
.MultiSampleQuality
= MultisampleQuality
;
1289 desc
.Height
= Height
;
1291 case 0: desc
.Usage
= D3DUSAGE_RENDERTARGET
; break;
1292 case 1: desc
.Usage
= D3DUSAGE_DEPTHSTENCIL
; break;
1293 default: assert(type
== 2); break;
1296 hr
= NineSurface9_new(This
, NULL
, NULL
, NULL
, 0, 0, 0, &desc
, &surface
);
1297 if (SUCCEEDED(hr
)) {
1298 *ppSurface
= (IDirect3DSurface9
*)surface
;
1300 if (surface
->base
.resource
&& Discard_or_Lockable
&& (type
!= 1))
1301 surface
->base
.resource
->flags
|= NINE_RESOURCE_FLAG_LOCKABLE
;
1308 NineDevice9_CreateRenderTarget( struct NineDevice9
*This
,
1312 D3DMULTISAMPLE_TYPE MultiSample
,
1313 DWORD MultisampleQuality
,
1315 IDirect3DSurface9
**ppSurface
,
1316 HANDLE
*pSharedHandle
)
1318 user_assert(ppSurface
!= NULL
, D3DERR_INVALIDCALL
);
1320 return create_zs_or_rt_surface(This
, 0, D3DPOOL_DEFAULT
,
1321 Width
, Height
, Format
,
1322 MultiSample
, MultisampleQuality
,
1323 Lockable
, ppSurface
, pSharedHandle
);
1327 NineDevice9_CreateDepthStencilSurface( struct NineDevice9
*This
,
1331 D3DMULTISAMPLE_TYPE MultiSample
,
1332 DWORD MultisampleQuality
,
1334 IDirect3DSurface9
**ppSurface
,
1335 HANDLE
*pSharedHandle
)
1337 user_assert(ppSurface
!= NULL
, D3DERR_INVALIDCALL
);
1339 if (!depth_stencil_format(Format
))
1340 return D3DERR_NOTAVAILABLE
;
1341 return create_zs_or_rt_surface(This
, 1, D3DPOOL_DEFAULT
,
1342 Width
, Height
, Format
,
1343 MultiSample
, MultisampleQuality
,
1344 Discard
, ppSurface
, pSharedHandle
);
1348 NineDevice9_UpdateSurface( struct NineDevice9
*This
,
1349 IDirect3DSurface9
*pSourceSurface
,
1350 const RECT
*pSourceRect
,
1351 IDirect3DSurface9
*pDestinationSurface
,
1352 const POINT
*pDestPoint
)
1354 struct NineSurface9
*dst
= NineSurface9(pDestinationSurface
);
1355 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1356 int copy_width
, copy_height
;
1359 DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
1360 "pSourceRect=%p pDestPoint=%p\n", This
,
1361 pSourceSurface
, pDestinationSurface
, pSourceRect
, pDestPoint
);
1363 DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
1364 pSourceRect
->left
, pSourceRect
->top
,
1365 pSourceRect
->right
, pSourceRect
->bottom
);
1367 DBG("pDestPoint = (%u,%u)\n", pDestPoint
->x
, pDestPoint
->y
);
1369 user_assert(dst
&& src
, D3DERR_INVALIDCALL
);
1371 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1372 user_assert(src
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1374 user_assert(dst
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1375 user_assert(src
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1377 user_assert(!src
->lock_count
, D3DERR_INVALIDCALL
);
1378 user_assert(!dst
->lock_count
, D3DERR_INVALIDCALL
);
1380 user_assert(dst
->desc
.Format
== src
->desc
.Format
, D3DERR_INVALIDCALL
);
1381 user_assert(!depth_stencil_format(dst
->desc
.Format
), D3DERR_INVALIDCALL
);
1384 copy_width
= pSourceRect
->right
- pSourceRect
->left
;
1385 copy_height
= pSourceRect
->bottom
- pSourceRect
->top
;
1387 user_assert(pSourceRect
->left
>= 0 &&
1389 pSourceRect
->right
<= src
->desc
.Width
&&
1390 pSourceRect
->top
>= 0 &&
1392 pSourceRect
->bottom
<= src
->desc
.Height
,
1393 D3DERR_INVALIDCALL
);
1395 copy_width
= src
->desc
.Width
;
1396 copy_height
= src
->desc
.Height
;
1399 destRect
.right
= copy_width
;
1400 destRect
.bottom
= copy_height
;
1403 user_assert(pDestPoint
->x
>= 0 && pDestPoint
->y
>= 0,
1404 D3DERR_INVALIDCALL
);
1405 destRect
.right
+= pDestPoint
->x
;
1406 destRect
.bottom
+= pDestPoint
->y
;
1409 user_assert(destRect
.right
<= dst
->desc
.Width
&&
1410 destRect
.bottom
<= dst
->desc
.Height
,
1411 D3DERR_INVALIDCALL
);
1413 if (compressed_format(dst
->desc
.Format
)) {
1414 const unsigned w
= util_format_get_blockwidth(dst
->base
.info
.format
);
1415 const unsigned h
= util_format_get_blockheight(dst
->base
.info
.format
);
1418 user_assert(!(pDestPoint
->x
% w
) && !(pDestPoint
->y
% h
),
1419 D3DERR_INVALIDCALL
);
1423 user_assert(!(pSourceRect
->left
% w
) && !(pSourceRect
->top
% h
),
1424 D3DERR_INVALIDCALL
);
1426 if (!(copy_width
== src
->desc
.Width
&&
1427 copy_width
== dst
->desc
.Width
&&
1428 copy_height
== src
->desc
.Height
&&
1429 copy_height
== dst
->desc
.Height
)) {
1430 user_assert(!(copy_width
% w
) && !(copy_height
% h
),
1431 D3DERR_INVALIDCALL
);
1435 NineSurface9_CopyMemToDefault(dst
, src
, pDestPoint
, pSourceRect
);
1441 NineDevice9_UpdateTexture( struct NineDevice9
*This
,
1442 IDirect3DBaseTexture9
*pSourceTexture
,
1443 IDirect3DBaseTexture9
*pDestinationTexture
)
1445 struct NineBaseTexture9
*dstb
= NineBaseTexture9(pDestinationTexture
);
1446 struct NineBaseTexture9
*srcb
= NineBaseTexture9(pSourceTexture
);
1448 unsigned last_src_level
, last_dst_level
;
1451 DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This
,
1452 pSourceTexture
, pDestinationTexture
);
1454 user_assert(pSourceTexture
&& pDestinationTexture
, D3DERR_INVALIDCALL
);
1455 user_assert(pSourceTexture
!= pDestinationTexture
, D3DERR_INVALIDCALL
);
1457 user_assert(dstb
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1458 user_assert(srcb
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1459 user_assert(dstb
->base
.type
== srcb
->base
.type
, D3DERR_INVALIDCALL
);
1460 user_assert(!(srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ||
1461 dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
, D3DERR_INVALIDCALL
);
1464 * . Different formats
1465 * . Fewer src levels than dst levels (if the opposite, only matching levels
1466 * are supposed to be copied)
1467 * . Levels do not match
1468 * DDI: Actually the above should pass because of legacy applications
1469 * Do what you want about these, but you shouldn't crash.
1470 * However driver can expect that the top dimension is greater for src than dst.
1471 * Wine tests: Every combination that passes the initial checks should pass.
1472 * . Different formats => conversion driver and format dependent.
1473 * . 1 level, but size not matching => copy is done (and even crash if src bigger
1474 * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied
1475 * or if a subrect is copied).
1476 * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect
1479 * From these, the proposal is:
1480 * . Different formats -> use util_format_translate to translate if possible for surfaces.
1481 * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations
1482 * . First level copied -> the first level such that src is smaller or equal to dst first level
1483 * . number of levels copied -> as long as it fits and textures have levels
1484 * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK)
1487 last_src_level
= (srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ? 0 : srcb
->base
.info
.last_level
;
1488 last_dst_level
= (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ? 0 : dstb
->base
.info
.last_level
;
1490 for (m
= 0; m
<= last_src_level
; ++m
) {
1491 unsigned w
= u_minify(srcb
->base
.info
.width0
, m
);
1492 unsigned h
= u_minify(srcb
->base
.info
.height0
, m
);
1493 unsigned d
= u_minify(srcb
->base
.info
.depth0
, m
);
1495 if (w
<= dstb
->base
.info
.width0
&&
1496 h
<= dstb
->base
.info
.height0
&&
1497 d
<= dstb
->base
.info
.depth0
)
1500 user_assert(m
<= last_src_level
, D3D_OK
);
1502 last_dst_level
= MIN2(srcb
->base
.info
.last_level
- m
, last_dst_level
);
1504 if (dstb
->base
.type
== D3DRTYPE_TEXTURE
) {
1505 struct NineTexture9
*dst
= NineTexture9(dstb
);
1506 struct NineTexture9
*src
= NineTexture9(srcb
);
1508 if (src
->dirty_rect
.width
== 0)
1511 pipe_box_to_rect(&rect
, &src
->dirty_rect
);
1512 for (l
= 0; l
< m
; ++l
)
1513 rect_minify_inclusive(&rect
);
1515 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
) {
1516 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1518 dst
->surfaces
[l
]->desc
.Width
,
1519 dst
->surfaces
[l
]->desc
.Height
);
1520 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
],
1524 rect_minify_inclusive(&rect
);
1526 u_box_origin_2d(0, 0, &src
->dirty_rect
);
1528 if (dstb
->base
.type
== D3DRTYPE_CUBETEXTURE
) {
1529 struct NineCubeTexture9
*dst
= NineCubeTexture9(dstb
);
1530 struct NineCubeTexture9
*src
= NineCubeTexture9(srcb
);
1533 /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
1534 for (z
= 0; z
< 6; ++z
) {
1535 if (src
->dirty_rect
[z
].width
== 0)
1538 pipe_box_to_rect(&rect
, &src
->dirty_rect
[z
]);
1539 for (l
= 0; l
< m
; ++l
)
1540 rect_minify_inclusive(&rect
);
1542 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
) {
1543 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1545 dst
->surfaces
[l
* 6 + z
]->desc
.Width
,
1546 dst
->surfaces
[l
* 6 + z
]->desc
.Height
);
1547 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
* 6 + z
],
1548 src
->surfaces
[m
* 6 + z
],
1551 rect_minify_inclusive(&rect
);
1553 u_box_origin_2d(0, 0, &src
->dirty_rect
[z
]);
1557 if (dstb
->base
.type
== D3DRTYPE_VOLUMETEXTURE
) {
1558 struct NineVolumeTexture9
*dst
= NineVolumeTexture9(dstb
);
1559 struct NineVolumeTexture9
*src
= NineVolumeTexture9(srcb
);
1561 if (src
->dirty_box
.width
== 0)
1563 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
)
1564 NineVolume9_CopyMemToDefault(dst
->volumes
[l
],
1565 src
->volumes
[m
], 0, 0, 0, NULL
);
1566 u_box_3d(0, 0, 0, 0, 0, 0, &src
->dirty_box
);
1568 assert(!"invalid texture type");
1571 if (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) {
1572 dstb
->dirty_mip
= TRUE
;
1573 NineBaseTexture9_GenerateMipSubLevels(dstb
);
1580 NineDevice9_GetRenderTargetData( struct NineDevice9
*This
,
1581 IDirect3DSurface9
*pRenderTarget
,
1582 IDirect3DSurface9
*pDestSurface
)
1584 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1585 struct NineSurface9
*src
= NineSurface9(pRenderTarget
);
1587 DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
1588 This
, pRenderTarget
, pDestSurface
);
1590 user_assert(pRenderTarget
&& pDestSurface
, D3DERR_INVALIDCALL
);
1592 user_assert(dst
->desc
.Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1593 user_assert(src
->desc
.Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1595 user_assert(dst
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1596 user_assert(src
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1598 user_assert(src
->desc
.Width
== dst
->desc
.Width
, D3DERR_INVALIDCALL
);
1599 user_assert(src
->desc
.Height
== dst
->desc
.Height
, D3DERR_INVALIDCALL
);
1601 user_assert(src
->desc
.Format
!= D3DFMT_NULL
, D3DERR_INVALIDCALL
);
1603 NineSurface9_CopyDefaultToMem(dst
, src
);
1609 NineDevice9_GetFrontBufferData( struct NineDevice9
*This
,
1611 IDirect3DSurface9
*pDestSurface
)
1613 DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This
,
1614 iSwapChain
, pDestSurface
);
1616 user_assert(pDestSurface
!= NULL
, D3DERR_INVALIDCALL
);
1617 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
1619 return NineSwapChain9_GetFrontBufferData(This
->swapchains
[iSwapChain
],
1624 NineDevice9_StretchRect( struct NineDevice9
*This
,
1625 IDirect3DSurface9
*pSourceSurface
,
1626 const RECT
*pSourceRect
,
1627 IDirect3DSurface9
*pDestSurface
,
1628 const RECT
*pDestRect
,
1629 D3DTEXTUREFILTERTYPE Filter
)
1631 struct pipe_screen
*screen
= This
->screen
;
1632 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1633 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1634 struct pipe_resource
*dst_res
, *src_res
;
1636 struct pipe_blit_info blit
;
1637 boolean scaled
, clamped
, ms
, flip_x
= FALSE
, flip_y
= FALSE
;
1639 DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
1640 "pDestRect=%p Filter=%u\n",
1641 This
, pSourceSurface
, pSourceRect
, pDestSurface
, pDestRect
, Filter
);
1643 DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
1644 pSourceRect
->left
, pSourceRect
->top
,
1645 pSourceRect
->right
, pSourceRect
->bottom
);
1647 DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect
->left
, pDestRect
->top
,
1648 pDestRect
->right
, pDestRect
->bottom
);
1650 user_assert(pSourceSurface
&& pDestSurface
, D3DERR_INVALIDCALL
);
1651 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
&&
1652 src
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1654 dst_res
= NineSurface9_GetResource(dst
);
1655 src_res
= NineSurface9_GetResource(src
);
1656 zs
= util_format_is_depth_or_stencil(dst_res
->format
);
1657 user_assert(!zs
|| !This
->in_scene
, D3DERR_INVALIDCALL
);
1658 user_assert(!zs
|| !pSourceRect
||
1659 (pSourceRect
->left
== 0 &&
1660 pSourceRect
->top
== 0 &&
1661 pSourceRect
->right
== src
->desc
.Width
&&
1662 pSourceRect
->bottom
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1663 user_assert(!zs
|| !pDestRect
||
1664 (pDestRect
->left
== 0 &&
1665 pDestRect
->top
== 0 &&
1666 pDestRect
->right
== dst
->desc
.Width
&&
1667 pDestRect
->bottom
== dst
->desc
.Height
), D3DERR_INVALIDCALL
);
1669 (dst
->desc
.Width
== src
->desc
.Width
&&
1670 dst
->desc
.Height
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1671 user_assert(zs
|| !util_format_is_depth_or_stencil(src_res
->format
),
1672 D3DERR_INVALIDCALL
);
1673 user_assert(!zs
|| dst
->desc
.Format
== src
->desc
.Format
,
1674 D3DERR_INVALIDCALL
);
1675 user_assert(screen
->is_format_supported(screen
, src_res
->format
,
1677 src_res
->nr_samples
,
1678 src_res
->nr_storage_samples
,
1679 PIPE_BIND_SAMPLER_VIEW
),
1680 D3DERR_INVALIDCALL
);
1682 /* We might want to permit these, but wine thinks we shouldn't. */
1683 user_assert(!pDestRect
||
1684 (pDestRect
->left
<= pDestRect
->right
&&
1685 pDestRect
->top
<= pDestRect
->bottom
), D3DERR_INVALIDCALL
);
1686 user_assert(!pSourceRect
||
1687 (pSourceRect
->left
<= pSourceRect
->right
&&
1688 pSourceRect
->top
<= pSourceRect
->bottom
), D3DERR_INVALIDCALL
);
1690 memset(&blit
, 0, sizeof(blit
));
1691 blit
.dst
.resource
= dst_res
;
1692 blit
.dst
.level
= dst
->level
;
1693 blit
.dst
.box
.z
= dst
->layer
;
1694 blit
.dst
.box
.depth
= 1;
1695 blit
.dst
.format
= dst_res
->format
;
1697 flip_x
= pDestRect
->left
> pDestRect
->right
;
1699 blit
.dst
.box
.x
= pDestRect
->right
;
1700 blit
.dst
.box
.width
= pDestRect
->left
- pDestRect
->right
;
1702 blit
.dst
.box
.x
= pDestRect
->left
;
1703 blit
.dst
.box
.width
= pDestRect
->right
- pDestRect
->left
;
1705 flip_y
= pDestRect
->top
> pDestRect
->bottom
;
1707 blit
.dst
.box
.y
= pDestRect
->bottom
;
1708 blit
.dst
.box
.height
= pDestRect
->top
- pDestRect
->bottom
;
1710 blit
.dst
.box
.y
= pDestRect
->top
;
1711 blit
.dst
.box
.height
= pDestRect
->bottom
- pDestRect
->top
;
1716 blit
.dst
.box
.width
= dst
->desc
.Width
;
1717 blit
.dst
.box
.height
= dst
->desc
.Height
;
1719 blit
.src
.resource
= src_res
;
1720 blit
.src
.level
= src
->level
;
1721 blit
.src
.box
.z
= src
->layer
;
1722 blit
.src
.box
.depth
= 1;
1723 blit
.src
.format
= src_res
->format
;
1725 if (flip_x
^ (pSourceRect
->left
> pSourceRect
->right
)) {
1726 blit
.src
.box
.x
= pSourceRect
->right
;
1727 blit
.src
.box
.width
= pSourceRect
->left
- pSourceRect
->right
;
1729 blit
.src
.box
.x
= pSourceRect
->left
;
1730 blit
.src
.box
.width
= pSourceRect
->right
- pSourceRect
->left
;
1732 if (flip_y
^ (pSourceRect
->top
> pSourceRect
->bottom
)) {
1733 blit
.src
.box
.y
= pSourceRect
->bottom
;
1734 blit
.src
.box
.height
= pSourceRect
->top
- pSourceRect
->bottom
;
1736 blit
.src
.box
.y
= pSourceRect
->top
;
1737 blit
.src
.box
.height
= pSourceRect
->bottom
- pSourceRect
->top
;
1740 blit
.src
.box
.x
= flip_x
? src
->desc
.Width
: 0;
1741 blit
.src
.box
.y
= flip_y
? src
->desc
.Height
: 0;
1742 blit
.src
.box
.width
= flip_x
? -src
->desc
.Width
: src
->desc
.Width
;
1743 blit
.src
.box
.height
= flip_y
? -src
->desc
.Height
: src
->desc
.Height
;
1745 blit
.mask
= zs
? PIPE_MASK_ZS
: PIPE_MASK_RGBA
;
1746 blit
.filter
= Filter
== D3DTEXF_LINEAR
?
1747 PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
1748 blit
.scissor_enable
= FALSE
;
1749 blit
.alpha_blend
= FALSE
;
1751 /* If both of a src and dst dimension are negative, flip them. */
1752 if (blit
.dst
.box
.width
< 0 && blit
.src
.box
.width
< 0) {
1753 blit
.dst
.box
.width
= -blit
.dst
.box
.width
;
1754 blit
.src
.box
.width
= -blit
.src
.box
.width
;
1756 if (blit
.dst
.box
.height
< 0 && blit
.src
.box
.height
< 0) {
1757 blit
.dst
.box
.height
= -blit
.dst
.box
.height
;
1758 blit
.src
.box
.height
= -blit
.src
.box
.height
;
1761 blit
.dst
.box
.width
!= blit
.src
.box
.width
||
1762 blit
.dst
.box
.height
!= blit
.src
.box
.height
;
1764 user_assert(!scaled
|| dst
!= src
, D3DERR_INVALIDCALL
);
1765 user_assert(!scaled
||
1766 !NineSurface9_IsOffscreenPlain(dst
), D3DERR_INVALIDCALL
);
1767 user_assert(!NineSurface9_IsOffscreenPlain(dst
) ||
1768 NineSurface9_IsOffscreenPlain(src
), D3DERR_INVALIDCALL
);
1769 user_assert(NineSurface9_IsOffscreenPlain(dst
) ||
1770 dst
->desc
.Usage
& (D3DUSAGE_RENDERTARGET
| D3DUSAGE_DEPTHSTENCIL
),
1771 D3DERR_INVALIDCALL
);
1772 user_assert(!scaled
||
1773 (!util_format_is_compressed(dst
->base
.info
.format
) &&
1774 !util_format_is_compressed(src
->base
.info
.format
)),
1775 D3DERR_INVALIDCALL
);
1777 user_warn(src
== dst
&&
1778 u_box_test_intersection_2d(&blit
.src
.box
, &blit
.dst
.box
));
1780 /* Check for clipping/clamping: */
1782 struct pipe_box box
;
1785 xy
= u_box_clip_2d(&box
, &blit
.dst
.box
,
1786 dst
->desc
.Width
, dst
->desc
.Height
);
1790 xy
= u_box_clip_2d(&box
, &blit
.src
.box
,
1791 src
->desc
.Width
, src
->desc
.Height
);
1795 ms
= (dst
->desc
.MultiSampleType
!= src
->desc
.MultiSampleType
) ||
1796 (dst
->desc
.MultiSampleQuality
!= src
->desc
.MultiSampleQuality
);
1798 if (clamped
|| scaled
|| (blit
.dst
.format
!= blit
.src
.format
) || ms
) {
1799 DBG("using pipe->blit()\n");
1800 /* TODO: software scaling */
1801 user_assert(screen
->is_format_supported(screen
, dst_res
->format
,
1803 dst_res
->nr_samples
,
1804 dst_res
->nr_storage_samples
,
1805 zs
? PIPE_BIND_DEPTH_STENCIL
:
1806 PIPE_BIND_RENDER_TARGET
),
1807 D3DERR_INVALIDCALL
);
1809 nine_context_blit(This
, (struct NineUnknown
*)dst
,
1810 (struct NineUnknown
*)src
, &blit
);
1812 assert(blit
.dst
.box
.x
>= 0 && blit
.dst
.box
.y
>= 0 &&
1813 blit
.src
.box
.x
>= 0 && blit
.src
.box
.y
>= 0 &&
1814 blit
.dst
.box
.x
+ blit
.dst
.box
.width
<= dst
->desc
.Width
&&
1815 blit
.src
.box
.x
+ blit
.src
.box
.width
<= src
->desc
.Width
&&
1816 blit
.dst
.box
.y
+ blit
.dst
.box
.height
<= dst
->desc
.Height
&&
1817 blit
.src
.box
.y
+ blit
.src
.box
.height
<= src
->desc
.Height
);
1818 /* Or drivers might crash ... */
1819 DBG("Using resource_copy_region.\n");
1820 nine_context_resource_copy_region(This
, (struct NineUnknown
*)dst
,
1821 (struct NineUnknown
*)src
,
1822 blit
.dst
.resource
, blit
.dst
.level
,
1824 blit
.src
.resource
, blit
.src
.level
,
1828 /* Communicate the container it needs to update sublevels - if apply */
1829 NineSurface9_MarkContainerDirty(dst
);
1835 NineDevice9_ColorFill( struct NineDevice9
*This
,
1836 IDirect3DSurface9
*pSurface
,
1840 struct NineSurface9
*surf
= NineSurface9(pSurface
);
1841 unsigned x
, y
, w
, h
;
1843 DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This
,
1844 pSurface
, pRect
, color
);
1846 DBG("pRect=(%u,%u)-(%u,%u)\n", pRect
->left
, pRect
->top
,
1847 pRect
->right
, pRect
->bottom
);
1849 user_assert(pSurface
!= NULL
, D3DERR_INVALIDCALL
);
1851 user_assert(surf
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1853 user_assert((surf
->base
.usage
& D3DUSAGE_RENDERTARGET
) ||
1854 NineSurface9_IsOffscreenPlain(surf
), D3DERR_INVALIDCALL
);
1856 user_assert(surf
->desc
.Format
!= D3DFMT_NULL
, D3D_OK
);
1861 w
= pRect
->right
- pRect
->left
;
1862 h
= pRect
->bottom
- pRect
->top
;
1864 if (compressed_format(surf
->desc
.Format
)) {
1865 const unsigned bw
= util_format_get_blockwidth(surf
->base
.info
.format
);
1866 const unsigned bh
= util_format_get_blockheight(surf
->base
.info
.format
);
1868 user_assert(!(x
% bw
) && !(y
% bh
) && !(w
% bw
) && !(h
% bh
),
1869 D3DERR_INVALIDCALL
);
1874 w
= surf
->desc
.Width
;
1875 h
= surf
->desc
.Height
;
1878 if (surf
->base
.info
.bind
& PIPE_BIND_RENDER_TARGET
) {
1879 nine_context_clear_render_target(This
, surf
, color
, x
, y
, w
, h
);
1881 D3DLOCKED_RECT lock
;
1882 union util_color uc
;
1884 /* XXX: lock pRect and fix util_fill_rect */
1885 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, pRect
? 0 : D3DLOCK_DISCARD
);
1888 util_pack_color_ub(color
>> 16, color
>> 8, color
>> 0, color
>> 24,
1889 surf
->base
.info
.format
, &uc
);
1890 util_fill_rect(lock
.pBits
, surf
->base
.info
.format
,lock
.Pitch
,
1892 NineSurface9_UnlockRect(surf
);
1899 NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9
*This
,
1904 IDirect3DSurface9
**ppSurface
,
1905 HANDLE
*pSharedHandle
)
1909 DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
1910 "ppSurface=%p pSharedHandle=%p\n", This
,
1911 Width
, Height
, d3dformat_to_string(Format
), Format
, Pool
,
1912 ppSurface
, pSharedHandle
);
1914 user_assert(ppSurface
!= NULL
, D3DERR_INVALIDCALL
);
1916 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
1917 || Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1918 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1920 /* Can be used with StretchRect and ColorFill. It's also always lockable.
1922 hr
= create_zs_or_rt_surface(This
, 2, Pool
, Width
, Height
,
1924 D3DMULTISAMPLE_NONE
, 0,
1926 ppSurface
, pSharedHandle
);
1928 DBG("Failed to create surface.\n");
1933 NineDevice9_SetRenderTarget( struct NineDevice9
*This
,
1934 DWORD RenderTargetIndex
,
1935 IDirect3DSurface9
*pRenderTarget
)
1937 struct NineSurface9
*rt
= NineSurface9(pRenderTarget
);
1938 const unsigned i
= RenderTargetIndex
;
1940 DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This
,
1941 RenderTargetIndex
, pRenderTarget
);
1943 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1944 user_assert(i
!= 0 || pRenderTarget
, D3DERR_INVALIDCALL
);
1945 user_assert(!pRenderTarget
||
1946 rt
->desc
.Usage
& D3DUSAGE_RENDERTARGET
, D3DERR_INVALIDCALL
);
1949 This
->state
.viewport
.X
= 0;
1950 This
->state
.viewport
.Y
= 0;
1951 This
->state
.viewport
.Width
= rt
->desc
.Width
;
1952 This
->state
.viewport
.Height
= rt
->desc
.Height
;
1953 This
->state
.viewport
.MinZ
= 0.0f
;
1954 This
->state
.viewport
.MaxZ
= 1.0f
;
1956 This
->state
.scissor
.minx
= 0;
1957 This
->state
.scissor
.miny
= 0;
1958 This
->state
.scissor
.maxx
= rt
->desc
.Width
;
1959 This
->state
.scissor
.maxy
= rt
->desc
.Height
;
1962 if (This
->state
.rt
[i
] != NineSurface9(pRenderTarget
))
1963 nine_bind(&This
->state
.rt
[i
], pRenderTarget
);
1965 nine_context_set_render_target(This
, i
, rt
);
1970 NineDevice9_GetRenderTarget( struct NineDevice9
*This
,
1971 DWORD RenderTargetIndex
,
1972 IDirect3DSurface9
**ppRenderTarget
)
1974 const unsigned i
= RenderTargetIndex
;
1976 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1977 user_assert(ppRenderTarget
, D3DERR_INVALIDCALL
);
1979 *ppRenderTarget
= (IDirect3DSurface9
*)This
->state
.rt
[i
];
1980 if (!This
->state
.rt
[i
])
1981 return D3DERR_NOTFOUND
;
1983 NineUnknown_AddRef(NineUnknown(This
->state
.rt
[i
]));
1988 NineDevice9_SetDepthStencilSurface( struct NineDevice9
*This
,
1989 IDirect3DSurface9
*pNewZStencil
)
1991 struct NineSurface9
*ds
= NineSurface9(pNewZStencil
);
1992 DBG("This=%p pNewZStencil=%p\n", This
, pNewZStencil
);
1994 user_assert(!ds
|| util_format_is_depth_or_stencil(ds
->base
.info
.format
),
1995 D3DERR_INVALIDCALL
);
1997 if (This
->state
.ds
!= ds
) {
1998 nine_bind(&This
->state
.ds
, ds
);
1999 nine_context_set_depth_stencil(This
, ds
);
2005 NineDevice9_GetDepthStencilSurface( struct NineDevice9
*This
,
2006 IDirect3DSurface9
**ppZStencilSurface
)
2008 user_assert(ppZStencilSurface
, D3DERR_INVALIDCALL
);
2010 *ppZStencilSurface
= (IDirect3DSurface9
*)This
->state
.ds
;
2011 if (!This
->state
.ds
)
2012 return D3DERR_NOTFOUND
;
2014 NineUnknown_AddRef(NineUnknown(This
->state
.ds
));
2019 NineDevice9_BeginScene( struct NineDevice9
*This
)
2021 DBG("This=%p\n", This
);
2022 user_assert(!This
->in_scene
, D3DERR_INVALIDCALL
);
2023 This
->in_scene
= TRUE
;
2024 /* Do we want to do anything else here ? */
2029 NineDevice9_EndScene( struct NineDevice9
*This
)
2031 DBG("This=%p\n", This
);
2032 user_assert(This
->in_scene
, D3DERR_INVALIDCALL
);
2033 This
->in_scene
= FALSE
;
2038 NineDevice9_Clear( struct NineDevice9
*This
,
2040 const D3DRECT
*pRects
,
2046 struct NineSurface9
*zsbuf_surf
= This
->state
.ds
;
2048 DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
2049 This
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
2051 user_assert(This
->state
.ds
|| !(Flags
& NINED3DCLEAR_DEPTHSTENCIL
),
2052 D3DERR_INVALIDCALL
);
2053 user_assert(!(Flags
& D3DCLEAR_STENCIL
) ||
2055 util_format_is_depth_and_stencil(zsbuf_surf
->base
.info
.format
)),
2056 D3DERR_INVALIDCALL
);
2058 user_assert((Count
&& pRects
) || (!Count
&& !pRects
), D3DERR_INVALIDCALL
);
2060 user_warn((pRects
&& !Count
) || (!pRects
&& Count
));
2061 if (pRects
&& !Count
)
2067 nine_context_clear_fb(This
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
2072 nine_D3DMATRIX_print(const D3DMATRIX
*M
)
2074 DBG("\n(%f %f %f %f)\n"
2078 M
->m
[0][0], M
->m
[0][1], M
->m
[0][2], M
->m
[0][3],
2079 M
->m
[1][0], M
->m
[1][1], M
->m
[1][2], M
->m
[1][3],
2080 M
->m
[2][0], M
->m
[2][1], M
->m
[2][2], M
->m
[2][3],
2081 M
->m
[3][0], M
->m
[3][1], M
->m
[3][2], M
->m
[3][3]);
2085 NineDevice9_SetTransform( struct NineDevice9
*This
,
2086 D3DTRANSFORMSTATETYPE State
,
2087 const D3DMATRIX
*pMatrix
)
2089 struct nine_state
*state
= This
->update
;
2090 D3DMATRIX
*M
= nine_state_access_transform(&state
->ff
, State
, TRUE
);
2092 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2094 user_assert(pMatrix
, D3DERR_INVALIDCALL
);
2095 user_assert(M
, D3DERR_INVALIDCALL
);
2096 nine_D3DMATRIX_print(pMatrix
);
2099 if (unlikely(This
->is_recording
)) {
2100 state
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
2101 state
->changed
.group
|= NINE_STATE_FF_VSTRANSF
;
2103 nine_context_set_transform(This
, State
, pMatrix
);
2109 NineDevice9_GetTransform( struct NineDevice9
*This
,
2110 D3DTRANSFORMSTATETYPE State
,
2111 D3DMATRIX
*pMatrix
)
2115 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2116 M
= nine_state_access_transform(&This
->state
.ff
, State
, FALSE
);
2117 user_assert(pMatrix
, D3DERR_INVALIDCALL
);
2118 user_assert(M
, D3DERR_INVALIDCALL
);
2124 NineDevice9_MultiplyTransform( struct NineDevice9
*This
,
2125 D3DTRANSFORMSTATETYPE State
,
2126 const D3DMATRIX
*pMatrix
)
2128 struct nine_state
*state
= This
->update
;
2130 D3DMATRIX
*M
= nine_state_access_transform(&state
->ff
, State
, TRUE
);
2132 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2134 user_assert(pMatrix
, D3DERR_INVALIDCALL
);
2135 user_assert(M
, D3DERR_INVALIDCALL
);
2137 nine_d3d_matrix_matrix_mul(&T
, pMatrix
, M
);
2138 return NineDevice9_SetTransform(This
, State
, &T
);
2142 NineDevice9_SetViewport( struct NineDevice9
*This
,
2143 const D3DVIEWPORT9
*pViewport
)
2145 struct nine_state
*state
= This
->update
;
2147 DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
2148 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
,
2149 pViewport
->MinZ
, pViewport
->MaxZ
);
2151 user_assert(pViewport
!= NULL
, D3DERR_INVALIDCALL
);
2152 state
->viewport
= *pViewport
;
2153 nine_context_set_viewport(This
, pViewport
);
2159 NineDevice9_GetViewport( struct NineDevice9
*This
,
2160 D3DVIEWPORT9
*pViewport
)
2162 user_assert(pViewport
!= NULL
, D3DERR_INVALIDCALL
);
2163 *pViewport
= This
->state
.viewport
;
2168 NineDevice9_SetMaterial( struct NineDevice9
*This
,
2169 const D3DMATERIAL9
*pMaterial
)
2171 struct nine_state
*state
= This
->update
;
2173 DBG("This=%p pMaterial=%p\n", This
, pMaterial
);
2175 nine_dump_D3DMATERIAL9(DBG_FF
, pMaterial
);
2177 user_assert(pMaterial
, E_POINTER
);
2179 state
->ff
.material
= *pMaterial
;
2180 if (unlikely(This
->is_recording
))
2181 state
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
2183 nine_context_set_material(This
, pMaterial
);
2189 NineDevice9_GetMaterial( struct NineDevice9
*This
,
2190 D3DMATERIAL9
*pMaterial
)
2192 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2193 user_assert(pMaterial
, E_POINTER
);
2194 *pMaterial
= This
->state
.ff
.material
;
2199 NineDevice9_SetLight( struct NineDevice9
*This
,
2201 const D3DLIGHT9
*pLight
)
2203 struct nine_state
*state
= This
->update
;
2206 DBG("This=%p Index=%u pLight=%p\n", This
, Index
, pLight
);
2208 nine_dump_D3DLIGHT9(DBG_FF
, pLight
);
2210 user_assert(pLight
, D3DERR_INVALIDCALL
);
2211 user_assert(pLight
->Type
< NINED3DLIGHT_INVALID
, D3DERR_INVALIDCALL
);
2213 user_assert(Index
< NINE_MAX_LIGHTS
, D3DERR_INVALIDCALL
); /* sanity */
2215 hr
= nine_state_set_light(&state
->ff
, Index
, pLight
);
2219 if (pLight
->Type
!= D3DLIGHT_DIRECTIONAL
&&
2220 pLight
->Attenuation0
== 0.0f
&&
2221 pLight
->Attenuation1
== 0.0f
&&
2222 pLight
->Attenuation2
== 0.0f
) {
2223 DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
2226 if (unlikely(This
->is_recording
))
2227 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2229 nine_context_set_light(This
, Index
, pLight
);
2235 NineDevice9_GetLight( struct NineDevice9
*This
,
2239 const struct nine_state
*state
= &This
->state
;
2241 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2242 user_assert(pLight
, D3DERR_INVALIDCALL
);
2243 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2244 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2245 D3DERR_INVALIDCALL
);
2247 *pLight
= state
->ff
.light
[Index
];
2253 NineDevice9_LightEnable( struct NineDevice9
*This
,
2257 struct nine_state
*state
= This
->update
;
2259 DBG("This=%p Index=%u Enable=%i\n", This
, Index
, Enable
);
2261 if (Index
>= state
->ff
.num_lights
||
2262 state
->ff
.light
[Index
].Type
== NINED3DLIGHT_INVALID
) {
2263 /* This should create a default light. */
2265 memset(&light
, 0, sizeof(light
));
2266 light
.Type
= D3DLIGHT_DIRECTIONAL
;
2267 light
.Diffuse
.r
= 1.0f
;
2268 light
.Diffuse
.g
= 1.0f
;
2269 light
.Diffuse
.b
= 1.0f
;
2270 light
.Direction
.z
= 1.0f
;
2271 NineDevice9_SetLight(This
, Index
, &light
);
2274 nine_state_light_enable(&state
->ff
, Index
, Enable
);
2275 if (likely(!This
->is_recording
))
2276 nine_context_light_enable(This
, Index
, Enable
);
2278 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2284 NineDevice9_GetLightEnable( struct NineDevice9
*This
,
2288 const struct nine_state
*state
= &This
->state
;
2291 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2292 user_assert(pEnable
!= NULL
, D3DERR_INVALIDCALL
);
2293 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2294 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2295 D3DERR_INVALIDCALL
);
2297 for (i
= 0; i
< state
->ff
.num_lights_active
; ++i
)
2298 if (state
->ff
.active_light
[i
] == Index
)
2301 *pEnable
= i
!= state
->ff
.num_lights_active
? 128 : 0; // Taken from wine
2307 NineDevice9_SetClipPlane( struct NineDevice9
*This
,
2309 const float *pPlane
)
2311 struct nine_state
*state
= This
->update
;
2313 user_assert(pPlane
, D3DERR_INVALIDCALL
);
2315 DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This
, Index
,
2316 pPlane
[0], pPlane
[1],
2317 pPlane
[2], pPlane
[3]);
2319 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2321 memcpy(&state
->clip
.ucp
[Index
][0], pPlane
, sizeof(state
->clip
.ucp
[0]));
2322 if (unlikely(This
->is_recording
))
2323 state
->changed
.ucp
|= 1 << Index
;
2325 nine_context_set_clip_plane(This
, Index
, (struct nine_clipplane
*)pPlane
);
2331 NineDevice9_GetClipPlane( struct NineDevice9
*This
,
2335 const struct nine_state
*state
= &This
->state
;
2337 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2338 user_assert(pPlane
!= NULL
, D3DERR_INVALIDCALL
);
2339 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2341 memcpy(pPlane
, &state
->clip
.ucp
[Index
][0], sizeof(state
->clip
.ucp
[0]));
2346 NineDevice9_SetRenderState( struct NineDevice9
*This
,
2347 D3DRENDERSTATETYPE State
,
2350 struct nine_state
*state
= This
->update
;
2352 DBG("This=%p State=%u(%s) Value=%08x\n", This
,
2353 State
, nine_d3drs_to_string(State
), Value
);
2355 user_assert(State
< D3DRS_COUNT
, D3D_OK
);
2357 if (unlikely(This
->is_recording
)) {
2358 state
->rs_advertised
[State
] = Value
;
2359 /* only need to record changed render states for stateblocks */
2360 state
->changed
.rs
[State
/ 32] |= 1 << (State
% 32);
2364 if (state
->rs_advertised
[State
] == Value
)
2367 state
->rs_advertised
[State
] = Value
;
2368 nine_context_set_render_state(This
, State
, Value
);
2374 NineDevice9_GetRenderState( struct NineDevice9
*This
,
2375 D3DRENDERSTATETYPE State
,
2378 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2379 user_assert(pValue
!= NULL
, D3DERR_INVALIDCALL
);
2380 /* TODO: This needs tests */
2381 if (State
>= D3DRS_COUNT
) {
2386 *pValue
= This
->state
.rs_advertised
[State
];
2391 NineDevice9_CreateStateBlock( struct NineDevice9
*This
,
2392 D3DSTATEBLOCKTYPE Type
,
2393 IDirect3DStateBlock9
**ppSB
)
2395 struct NineStateBlock9
*nsb
;
2396 struct nine_state
*dst
;
2398 enum nine_stateblock_type type
;
2401 DBG("This=%p Type=%u ppSB=%p\n", This
, Type
, ppSB
);
2403 user_assert(ppSB
!= NULL
, D3DERR_INVALIDCALL
);
2404 user_assert(Type
== D3DSBT_ALL
||
2405 Type
== D3DSBT_VERTEXSTATE
||
2406 Type
== D3DSBT_PIXELSTATE
, D3DERR_INVALIDCALL
);
2409 case D3DSBT_VERTEXSTATE
: type
= NINESBT_VERTEXSTATE
; break;
2410 case D3DSBT_PIXELSTATE
: type
= NINESBT_PIXELSTATE
; break;
2416 hr
= NineStateBlock9_new(This
, &nsb
, type
);
2419 *ppSB
= (IDirect3DStateBlock9
*)nsb
;
2422 dst
->changed
.group
= NINE_STATE_SAMPLER
;
2424 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_VERTEXSTATE
) {
2425 dst
->changed
.group
|=
2426 NINE_STATE_FF_LIGHTING
|
2427 NINE_STATE_VS
| NINE_STATE_VS_CONST
|
2429 /* TODO: texture/sampler state */
2430 memcpy(dst
->changed
.rs
,
2431 nine_render_states_vertex
, sizeof(dst
->changed
.rs
));
2432 nine_ranges_insert(&dst
->changed
.vs_const_f
, 0, This
->may_swvp
? NINE_MAX_CONST_F_SWVP
: This
->max_vs_const_f
,
2434 nine_ranges_insert(&dst
->changed
.vs_const_i
, 0, This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
,
2436 nine_ranges_insert(&dst
->changed
.vs_const_b
, 0, This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
,
2438 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2439 dst
->changed
.sampler
[s
] |= 1 << D3DSAMP_DMAPOFFSET
;
2440 if (This
->state
.ff
.num_lights
) {
2441 dst
->ff
.num_lights
= This
->state
.ff
.num_lights
;
2442 /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
2443 * all currently existing lights will be captured
2445 dst
->ff
.light
= CALLOC(This
->state
.ff
.num_lights
,
2447 if (!dst
->ff
.light
) {
2448 nine_bind(ppSB
, NULL
);
2449 return E_OUTOFMEMORY
;
2453 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_PIXELSTATE
) {
2454 dst
->changed
.group
|=
2455 NINE_STATE_PS
| NINE_STATE_PS_CONST
| NINE_STATE_FF_PS_CONSTS
;
2456 memcpy(dst
->changed
.rs
,
2457 nine_render_states_pixel
, sizeof(dst
->changed
.rs
));
2458 nine_ranges_insert(&dst
->changed
.ps_const_f
, 0, This
->max_ps_const_f
,
2460 dst
->changed
.ps_const_i
= 0xffff;
2461 dst
->changed
.ps_const_b
= 0xffff;
2462 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2463 dst
->changed
.sampler
[s
] |= 0x1ffe;
2464 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
2465 dst
->ff
.changed
.tex_stage
[s
][0] |= 0xffffffff;
2466 dst
->ff
.changed
.tex_stage
[s
][1] |= 0xffffffff;
2469 if (Type
== D3DSBT_ALL
) {
2470 dst
->changed
.group
|=
2471 NINE_STATE_VIEWPORT
|
2472 NINE_STATE_SCISSOR
|
2474 NINE_STATE_FF_MATERIAL
|
2475 NINE_STATE_FF_VSTRANSF
;
2476 memset(dst
->changed
.rs
, ~0, (D3DRS_COUNT
/ 32) * sizeof(uint32_t));
2477 dst
->changed
.rs
[D3DRS_LAST
/ 32] |= (1 << (D3DRS_COUNT
% 32)) - 1;
2478 dst
->changed
.vtxbuf
= (1ULL << This
->caps
.MaxStreams
) - 1;
2479 dst
->changed
.stream_freq
= dst
->changed
.vtxbuf
;
2480 dst
->changed
.ucp
= (1 << PIPE_MAX_CLIP_PLANES
) - 1;
2481 dst
->changed
.texture
= (1 << NINE_MAX_SAMPLERS
) - 1;
2482 /* The doc says the projection, world, view and texture matrices
2483 * are saved, which would translate to:
2484 * dst->ff.changed.transform[0] = 0x00FF000C;
2485 * dst->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32);
2486 * However we assume they meant save everything (which is basically just the
2487 * above plus the other world matrices).
2489 dst
->ff
.changed
.transform
[0] = 0x00FF000C;
2490 for (s
= 0; s
< 8; s
++)
2491 dst
->ff
.changed
.transform
[8+s
] = ~0;
2493 NineStateBlock9_Capture(NineStateBlock9(*ppSB
));
2495 /* TODO: fixed function state */
2501 NineDevice9_BeginStateBlock( struct NineDevice9
*This
)
2505 DBG("This=%p\n", This
);
2507 user_assert(!This
->record
, D3DERR_INVALIDCALL
);
2509 hr
= NineStateBlock9_new(This
, &This
->record
, NINESBT_CUSTOM
);
2512 NineUnknown_ConvertRefToBind(NineUnknown(This
->record
));
2514 This
->update
= &This
->record
->state
;
2515 This
->is_recording
= TRUE
;
2521 NineDevice9_EndStateBlock( struct NineDevice9
*This
,
2522 IDirect3DStateBlock9
**ppSB
)
2524 DBG("This=%p ppSB=%p\n", This
, ppSB
);
2526 user_assert(This
->record
, D3DERR_INVALIDCALL
);
2527 user_assert(ppSB
!= NULL
, D3DERR_INVALIDCALL
);
2529 This
->update
= &This
->state
;
2530 This
->is_recording
= FALSE
;
2532 NineUnknown_AddRef(NineUnknown(This
->record
));
2533 *ppSB
= (IDirect3DStateBlock9
*)This
->record
;
2534 NineUnknown_Unbind(NineUnknown(This
->record
));
2535 This
->record
= NULL
;
2541 NineDevice9_SetClipStatus( struct NineDevice9
*This
,
2542 const D3DCLIPSTATUS9
*pClipStatus
)
2544 STUB(D3DERR_INVALIDCALL
);
2548 NineDevice9_GetClipStatus( struct NineDevice9
*This
,
2549 D3DCLIPSTATUS9
*pClipStatus
)
2551 STUB(D3DERR_INVALIDCALL
);
2555 NineDevice9_GetTexture( struct NineDevice9
*This
,
2557 IDirect3DBaseTexture9
**ppTexture
)
2559 user_assert(Stage
< NINE_MAX_SAMPLERS_PS
||
2560 Stage
== D3DDMAPSAMPLER
||
2561 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2562 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2563 user_assert(ppTexture
, D3DERR_INVALIDCALL
);
2565 if (Stage
>= D3DDMAPSAMPLER
)
2566 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2568 *ppTexture
= (IDirect3DBaseTexture9
*)This
->state
.texture
[Stage
];
2570 if (This
->state
.texture
[Stage
])
2571 NineUnknown_AddRef(NineUnknown(This
->state
.texture
[Stage
]));
2576 NineDevice9_SetTexture( struct NineDevice9
*This
,
2578 IDirect3DBaseTexture9
*pTexture
)
2580 struct nine_state
*state
= This
->update
;
2581 struct NineBaseTexture9
*tex
= NineBaseTexture9(pTexture
);
2582 struct NineBaseTexture9
*old
;
2584 DBG("This=%p Stage=%u pTexture=%p\n", This
, Stage
, pTexture
);
2586 user_assert(Stage
< NINE_MAX_SAMPLERS_PS
||
2587 Stage
== D3DDMAPSAMPLER
||
2588 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2589 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2590 user_assert(!tex
|| (tex
->base
.pool
!= D3DPOOL_SCRATCH
&&
2591 tex
->base
.pool
!= D3DPOOL_SYSTEMMEM
), D3DERR_INVALIDCALL
);
2593 if (Stage
>= D3DDMAPSAMPLER
)
2594 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2596 if (This
->is_recording
) {
2597 state
->changed
.texture
|= 1 << Stage
;
2598 nine_bind(&state
->texture
[Stage
], pTexture
);
2602 old
= state
->texture
[Stage
];
2606 NineBindTextureToDevice(This
, &state
->texture
[Stage
], tex
);
2608 nine_context_set_texture(This
, Stage
, tex
);
2614 NineDevice9_GetTextureStageState( struct NineDevice9
*This
,
2616 D3DTEXTURESTAGESTATETYPE Type
,
2619 const struct nine_state
*state
= &This
->state
;
2621 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2622 user_assert(pValue
!= NULL
, D3DERR_INVALIDCALL
);
2623 user_assert(Stage
< ARRAY_SIZE(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2624 user_assert(Type
< ARRAY_SIZE(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2626 *pValue
= state
->ff
.tex_stage
[Stage
][Type
];
2632 NineDevice9_SetTextureStageState( struct NineDevice9
*This
,
2634 D3DTEXTURESTAGESTATETYPE Type
,
2637 struct nine_state
*state
= This
->update
;
2639 DBG("Stage=%u Type=%u Value=%08x\n", Stage
, Type
, Value
);
2640 nine_dump_D3DTSS_value(DBG_FF
, Type
, Value
);
2642 user_assert(Stage
< ARRAY_SIZE(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2643 user_assert(Type
< ARRAY_SIZE(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2645 state
->ff
.tex_stage
[Stage
][Type
] = Value
;
2647 if (unlikely(This
->is_recording
)) {
2648 state
->changed
.group
|= NINE_STATE_FF_PS_CONSTS
;
2649 state
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
2651 nine_context_set_texture_stage_state(This
, Stage
, Type
, Value
);
2657 NineDevice9_GetSamplerState( struct NineDevice9
*This
,
2659 D3DSAMPLERSTATETYPE Type
,
2662 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
2663 user_assert(pValue
!= NULL
, D3DERR_INVALIDCALL
);
2664 user_assert(Sampler
< NINE_MAX_SAMPLERS_PS
||
2665 Sampler
== D3DDMAPSAMPLER
||
2666 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2667 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2669 if (Sampler
>= D3DDMAPSAMPLER
)
2670 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2672 *pValue
= This
->state
.samp_advertised
[Sampler
][Type
];
2677 NineDevice9_SetSamplerState( struct NineDevice9
*This
,
2679 D3DSAMPLERSTATETYPE Type
,
2682 struct nine_state
*state
= This
->update
;
2684 DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This
,
2685 Sampler
, nine_D3DSAMP_to_str(Type
), Value
);
2687 user_assert(Sampler
< NINE_MAX_SAMPLERS_PS
||
2688 Sampler
== D3DDMAPSAMPLER
||
2689 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2690 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2692 if (Sampler
>= D3DDMAPSAMPLER
)
2693 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2695 if (unlikely(This
->is_recording
)) {
2696 state
->samp_advertised
[Sampler
][Type
] = Value
;
2697 state
->changed
.group
|= NINE_STATE_SAMPLER
;
2698 state
->changed
.sampler
[Sampler
] |= 1 << Type
;
2702 if (state
->samp_advertised
[Sampler
][Type
] == Value
)
2705 state
->samp_advertised
[Sampler
][Type
] = Value
;
2706 nine_context_set_sampler_state(This
, Sampler
, Type
, Value
);
2712 NineDevice9_ValidateDevice( struct NineDevice9
*This
,
2715 const struct nine_state
*state
= &This
->state
;
2717 unsigned w
= 0, h
= 0;
2719 DBG("This=%p pNumPasses=%p\n", This
, pNumPasses
);
2721 for (i
= 0; i
< ARRAY_SIZE(state
->samp_advertised
); ++i
) {
2722 if (state
->samp_advertised
[i
][D3DSAMP_MINFILTER
] == D3DTEXF_NONE
||
2723 state
->samp_advertised
[i
][D3DSAMP_MAGFILTER
] == D3DTEXF_NONE
)
2724 return D3DERR_UNSUPPORTEDTEXTUREFILTER
;
2727 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2731 w
= state
->rt
[i
]->desc
.Width
;
2732 h
= state
->rt
[i
]->desc
.Height
;
2734 if (state
->rt
[i
]->desc
.Width
!= w
|| state
->rt
[i
]->desc
.Height
!= h
) {
2735 return D3DERR_CONFLICTINGRENDERSTATE
;
2739 (state
->rs_advertised
[D3DRS_ZENABLE
] || state
->rs_advertised
[D3DRS_STENCILENABLE
])) {
2741 (state
->ds
->desc
.Width
!= w
|| state
->ds
->desc
.Height
!= h
))
2742 return D3DERR_CONFLICTINGRENDERSTATE
;
2752 NineDevice9_SetPaletteEntries( struct NineDevice9
*This
,
2754 const PALETTEENTRY
*pEntries
)
2756 STUB(D3D_OK
); /* like wine */
2760 NineDevice9_GetPaletteEntries( struct NineDevice9
*This
,
2762 PALETTEENTRY
*pEntries
)
2764 STUB(D3DERR_INVALIDCALL
);
2768 NineDevice9_SetCurrentTexturePalette( struct NineDevice9
*This
,
2769 UINT PaletteNumber
)
2771 STUB(D3D_OK
); /* like wine */
2775 NineDevice9_GetCurrentTexturePalette( struct NineDevice9
*This
,
2776 UINT
*PaletteNumber
)
2778 STUB(D3DERR_INVALIDCALL
);
2782 NineDevice9_SetScissorRect( struct NineDevice9
*This
,
2785 struct nine_state
*state
= This
->update
;
2787 user_assert(pRect
!= NULL
, D3DERR_INVALIDCALL
);
2789 DBG("x=(%u..%u) y=(%u..%u)\n",
2790 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
2792 state
->scissor
.minx
= pRect
->left
;
2793 state
->scissor
.miny
= pRect
->top
;
2794 state
->scissor
.maxx
= pRect
->right
;
2795 state
->scissor
.maxy
= pRect
->bottom
;
2797 if (unlikely(This
->is_recording
))
2798 state
->changed
.group
|= NINE_STATE_SCISSOR
;
2800 nine_context_set_scissor(This
, &state
->scissor
);
2806 NineDevice9_GetScissorRect( struct NineDevice9
*This
,
2809 user_assert(pRect
!= NULL
, D3DERR_INVALIDCALL
);
2811 pRect
->left
= This
->state
.scissor
.minx
;
2812 pRect
->top
= This
->state
.scissor
.miny
;
2813 pRect
->right
= This
->state
.scissor
.maxx
;
2814 pRect
->bottom
= This
->state
.scissor
.maxy
;
2820 NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9
*This
,
2823 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
) {
2824 This
->swvp
= bSoftware
;
2825 nine_context_set_swvp(This
, bSoftware
);
2828 return D3D_OK
; /* msdn seems to indicate INVALIDCALL, but at least Halo expects OK */
2832 NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9
*This
)
2838 NineDevice9_SetNPatchMode( struct NineDevice9
*This
,
2841 return D3D_OK
; /* Nothing to do because we don't advertise NPatch support */
2845 NineDevice9_GetNPatchMode( struct NineDevice9
*This
)
2850 /* TODO: only go through dirty textures */
2852 validate_textures(struct NineDevice9
*device
)
2854 struct NineBaseTexture9
*tex
, *ptr
;
2855 LIST_FOR_EACH_ENTRY_SAFE(tex
, ptr
, &device
->update_textures
, list
) {
2856 list_delinit(&tex
->list
);
2857 NineBaseTexture9_Validate(tex
);
2862 update_managed_buffers(struct NineDevice9
*device
)
2864 struct NineBuffer9
*buf
, *ptr
;
2865 LIST_FOR_EACH_ENTRY_SAFE(buf
, ptr
, &device
->update_buffers
, managed
.list
) {
2866 list_delinit(&buf
->managed
.list
);
2867 NineBuffer9_Upload(buf
);
2872 NineBeforeDraw( struct NineDevice9
*This
)
2874 /* Upload Managed dirty content */
2875 validate_textures(This
); /* may clobber state */
2876 update_managed_buffers(This
);
2880 NineAfterDraw( struct NineDevice9
*This
)
2883 struct nine_state
*state
= &This
->state
;
2884 unsigned ps_mask
= state
->ps
? state
->ps
->rt_mask
: 1;
2886 /* Flag render-targets with autogenmipmap for mipmap regeneration */
2887 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2888 struct NineSurface9
*rt
= state
->rt
[i
];
2890 if (rt
&& rt
->desc
.Format
!= D3DFMT_NULL
&& (ps_mask
& (1 << i
)) &&
2891 rt
->desc
.Usage
& D3DUSAGE_AUTOGENMIPMAP
) {
2892 assert(rt
->texture
== D3DRTYPE_TEXTURE
||
2893 rt
->texture
== D3DRTYPE_CUBETEXTURE
);
2894 NineBaseTexture9(rt
->base
.base
.container
)->dirty_mip
= TRUE
;
2900 NineDevice9_DrawPrimitive( struct NineDevice9
*This
,
2901 D3DPRIMITIVETYPE PrimitiveType
,
2903 UINT PrimitiveCount
)
2905 DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
2906 This
, PrimitiveType
, StartVertex
, PrimitiveCount
);
2908 NineBeforeDraw(This
);
2909 nine_context_draw_primitive(This
, PrimitiveType
, StartVertex
, PrimitiveCount
);
2910 NineAfterDraw(This
);
2916 NineDevice9_DrawIndexedPrimitive( struct NineDevice9
*This
,
2917 D3DPRIMITIVETYPE PrimitiveType
,
2918 INT BaseVertexIndex
,
2919 UINT MinVertexIndex
,
2922 UINT PrimitiveCount
)
2924 DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
2925 "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
2926 This
, PrimitiveType
, BaseVertexIndex
, MinVertexIndex
, NumVertices
,
2927 StartIndex
, PrimitiveCount
);
2929 user_assert(This
->state
.idxbuf
, D3DERR_INVALIDCALL
);
2930 user_assert(This
->state
.vdecl
, D3DERR_INVALIDCALL
);
2932 NineBeforeDraw(This
);
2933 nine_context_draw_indexed_primitive(This
, PrimitiveType
, BaseVertexIndex
,
2934 MinVertexIndex
, NumVertices
, StartIndex
,
2936 NineAfterDraw(This
);
2942 NineDevice9_DrawPrimitiveUP( struct NineDevice9
*This
,
2943 D3DPRIMITIVETYPE PrimitiveType
,
2944 UINT PrimitiveCount
,
2945 const void *pVertexStreamZeroData
,
2946 UINT VertexStreamZeroStride
)
2948 struct pipe_vertex_buffer vtxbuf
;
2950 DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
2951 This
, PrimitiveType
, PrimitiveCount
,
2952 pVertexStreamZeroData
, VertexStreamZeroStride
);
2954 user_assert(pVertexStreamZeroData
&& VertexStreamZeroStride
,
2955 D3DERR_INVALIDCALL
);
2956 user_assert(PrimitiveCount
, D3D_OK
);
2958 vtxbuf
.stride
= VertexStreamZeroStride
;
2959 vtxbuf
.buffer_offset
= 0;
2960 vtxbuf
.is_user_buffer
= true;
2961 vtxbuf
.buffer
.user
= pVertexStreamZeroData
;
2963 if (!This
->driver_caps
.user_vbufs
) {
2964 vtxbuf
.is_user_buffer
= false;
2965 vtxbuf
.buffer
.resource
= NULL
;
2966 u_upload_data(This
->vertex_uploader
,
2968 (prim_count_to_vertex_count(PrimitiveType
, PrimitiveCount
)) * VertexStreamZeroStride
, /* XXX */
2970 pVertexStreamZeroData
,
2971 &vtxbuf
.buffer_offset
,
2972 &vtxbuf
.buffer
.resource
);
2973 u_upload_unmap(This
->vertex_uploader
);
2976 NineBeforeDraw(This
);
2977 nine_context_draw_primitive_from_vtxbuf(This
, PrimitiveType
, PrimitiveCount
, &vtxbuf
);
2978 NineAfterDraw(This
);
2980 pipe_vertex_buffer_unreference(&vtxbuf
);
2982 NineDevice9_PauseRecording(This
);
2983 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
2984 NineDevice9_ResumeRecording(This
);
2990 NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9
*This
,
2991 D3DPRIMITIVETYPE PrimitiveType
,
2992 UINT MinVertexIndex
,
2994 UINT PrimitiveCount
,
2995 const void *pIndexData
,
2996 D3DFORMAT IndexDataFormat
,
2997 const void *pVertexStreamZeroData
,
2998 UINT VertexStreamZeroStride
)
3000 struct pipe_vertex_buffer vbuf
;
3002 DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
3003 "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
3004 "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
3005 This
, PrimitiveType
, MinVertexIndex
, NumVertices
, PrimitiveCount
,
3006 pIndexData
, IndexDataFormat
,
3007 pVertexStreamZeroData
, VertexStreamZeroStride
);
3009 user_assert(pIndexData
&& pVertexStreamZeroData
, D3DERR_INVALIDCALL
);
3010 user_assert(VertexStreamZeroStride
, D3DERR_INVALIDCALL
);
3011 user_assert(IndexDataFormat
== D3DFMT_INDEX16
||
3012 IndexDataFormat
== D3DFMT_INDEX32
, D3DERR_INVALIDCALL
);
3013 user_assert(PrimitiveCount
, D3D_OK
);
3015 vbuf
.stride
= VertexStreamZeroStride
;
3016 vbuf
.buffer_offset
= 0;
3017 vbuf
.is_user_buffer
= true;
3018 vbuf
.buffer
.user
= pVertexStreamZeroData
;
3020 unsigned index_size
= (IndexDataFormat
== D3DFMT_INDEX16
) ? 2 : 4;
3021 struct pipe_resource
*ibuf
= NULL
;
3023 if (!This
->driver_caps
.user_vbufs
) {
3024 const unsigned base
= MinVertexIndex
* VertexStreamZeroStride
;
3025 vbuf
.is_user_buffer
= false;
3026 vbuf
.buffer
.resource
= NULL
;
3027 u_upload_data(This
->vertex_uploader
,
3029 NumVertices
* VertexStreamZeroStride
, /* XXX */
3031 (const uint8_t *)pVertexStreamZeroData
+ base
,
3032 &vbuf
.buffer_offset
,
3033 &vbuf
.buffer
.resource
);
3034 u_upload_unmap(This
->vertex_uploader
);
3035 /* Won't be used: */
3036 vbuf
.buffer_offset
-= base
;
3039 unsigned index_offset
= 0;
3040 if (This
->csmt_active
) {
3041 u_upload_data(This
->pipe_secondary
->stream_uploader
,
3043 (prim_count_to_vertex_count(PrimitiveType
, PrimitiveCount
)) * index_size
,
3048 u_upload_unmap(This
->pipe_secondary
->stream_uploader
);
3051 NineBeforeDraw(This
);
3052 nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This
, PrimitiveType
,
3058 ibuf
? NULL
: (void*)pIndexData
,
3061 NineAfterDraw(This
);
3063 pipe_vertex_buffer_unreference(&vbuf
);
3064 pipe_resource_reference(&ibuf
, NULL
);
3066 NineDevice9_PauseRecording(This
);
3067 NineDevice9_SetIndices(This
, NULL
);
3068 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
3069 NineDevice9_ResumeRecording(This
);
3075 NineDevice9_ProcessVertices( struct NineDevice9
*This
,
3079 IDirect3DVertexBuffer9
*pDestBuffer
,
3080 IDirect3DVertexDeclaration9
*pVertexDecl
,
3083 struct pipe_screen
*screen_sw
= This
->screen_sw
;
3084 struct pipe_context
*pipe_sw
= This
->pipe_sw
;
3085 struct NineVertexDeclaration9
*vdecl
= NineVertexDeclaration9(pVertexDecl
);
3086 struct NineVertexBuffer9
*dst
= NineVertexBuffer9(pDestBuffer
);
3087 struct NineVertexShader9
*vs
;
3088 struct pipe_resource
*resource
;
3089 struct pipe_transfer
*transfer
= NULL
;
3090 struct pipe_stream_output_info so
;
3091 struct pipe_stream_output_target
*target
;
3092 struct pipe_draw_info draw
;
3093 struct pipe_box box
;
3094 bool programmable_vs
= This
->state
.vs
&& !(This
->state
.vdecl
&& This
->state
.vdecl
->position_t
);
3095 unsigned offsets
[1] = {0};
3097 unsigned buffer_size
;
3100 DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
3101 "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
3102 This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
,
3103 pVertexDecl
, Flags
);
3105 user_assert(pDestBuffer
&& pVertexDecl
, D3DERR_INVALIDCALL
);
3107 if (!screen_sw
->get_param(screen_sw
, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS
)) {
3108 DBG("ProcessVertices not supported\n");
3109 return D3DERR_INVALIDCALL
;
3113 vs
= programmable_vs
? This
->state
.vs
: This
->ff
.vs
;
3114 /* Note: version is 0 for ff */
3115 user_assert(vdecl
|| (vs
->byte_code
.version
< 0x30 && dst
->desc
.FVF
),
3116 D3DERR_INVALIDCALL
);
3118 DWORD FVF
= dst
->desc
.FVF
;
3119 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3121 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3125 _mesa_hash_table_insert(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3126 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3130 /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags
3131 * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular
3132 * if not set, everything from src will be used, and dst
3133 * must match exactly the ff vs outputs.
3134 * TODO: Handle all the checks, etc for ff */
3135 user_assert(vdecl
->position_t
|| programmable_vs
,
3136 D3DERR_INVALIDCALL
);
3138 /* TODO: Support vs < 3 and ff */
3139 user_assert(vs
->byte_code
.version
== 0x30,
3140 D3DERR_INVALIDCALL
);
3141 /* TODO: Not hardcode the constant buffers for swvp */
3142 user_assert(This
->may_swvp
,
3143 D3DERR_INVALIDCALL
);
3145 nine_state_prepare_draw_sw(This
, vdecl
, SrcStartIndex
, VertexCount
, &so
);
3147 buffer_size
= VertexCount
* so
.stride
[0] * 4;
3149 struct pipe_resource templ
;
3151 memset(&templ
, 0, sizeof(templ
));
3152 templ
.target
= PIPE_BUFFER
;
3153 templ
.format
= PIPE_FORMAT_R8_UNORM
;
3154 templ
.width0
= buffer_size
;
3156 templ
.bind
= PIPE_BIND_STREAM_OUTPUT
;
3157 templ
.usage
= PIPE_USAGE_STREAM
;
3158 templ
.height0
= templ
.depth0
= templ
.array_size
= 1;
3159 templ
.last_level
= templ
.nr_samples
= templ
.nr_storage_samples
= 0;
3161 resource
= screen_sw
->resource_create(screen_sw
, &templ
);
3163 return E_OUTOFMEMORY
;
3165 target
= pipe_sw
->create_stream_output_target(pipe_sw
, resource
,
3168 pipe_resource_reference(&resource
, NULL
);
3169 return D3DERR_DRIVERINTERNALERROR
;
3172 draw
.mode
= PIPE_PRIM_POINTS
;
3173 draw
.count
= VertexCount
;
3174 draw
.start_instance
= 0;
3175 draw
.primitive_restart
= FALSE
;
3176 draw
.restart_index
= 0;
3177 draw
.count_from_stream_output
= NULL
;
3178 draw
.indirect
= NULL
;
3179 draw
.instance_count
= 1;
3180 draw
.index_size
= 0;
3182 draw
.index_bias
= 0;
3184 draw
.max_index
= VertexCount
- 1;
3187 pipe_sw
->set_stream_output_targets(pipe_sw
, 1, &target
, offsets
);
3189 pipe_sw
->draw_vbo(pipe_sw
, &draw
);
3191 pipe_sw
->set_stream_output_targets(pipe_sw
, 0, NULL
, 0);
3192 pipe_sw
->stream_output_target_destroy(pipe_sw
, target
);
3194 u_box_1d(0, VertexCount
* so
.stride
[0] * 4, &box
);
3195 map
= pipe_sw
->transfer_map(pipe_sw
, resource
, 0, PIPE_TRANSFER_READ
, &box
,
3198 hr
= D3DERR_DRIVERINTERNALERROR
;
3202 hr
= NineVertexDeclaration9_ConvertStreamOutput(vdecl
,
3203 dst
, DestIndex
, VertexCount
,
3206 pipe_sw
->transfer_unmap(pipe_sw
, transfer
);
3209 nine_state_after_draw_sw(This
);
3210 pipe_resource_reference(&resource
, NULL
);
3215 NineDevice9_CreateVertexDeclaration( struct NineDevice9
*This
,
3216 const D3DVERTEXELEMENT9
*pVertexElements
,
3217 IDirect3DVertexDeclaration9
**ppDecl
)
3219 struct NineVertexDeclaration9
*vdecl
;
3221 DBG("This=%p pVertexElements=%p ppDecl=%p\n",
3222 This
, pVertexElements
, ppDecl
);
3224 user_assert(pVertexElements
&& ppDecl
, D3DERR_INVALIDCALL
);
3226 HRESULT hr
= NineVertexDeclaration9_new(This
, pVertexElements
, &vdecl
);
3228 *ppDecl
= (IDirect3DVertexDeclaration9
*)vdecl
;
3234 NineDevice9_SetVertexDeclaration( struct NineDevice9
*This
,
3235 IDirect3DVertexDeclaration9
*pDecl
)
3237 struct nine_state
*state
= This
->update
;
3238 struct NineVertexDeclaration9
*vdecl
= NineVertexDeclaration9(pDecl
);
3240 DBG("This=%p pDecl=%p\n", This
, pDecl
);
3242 if (unlikely(This
->is_recording
)) {
3243 nine_bind(&state
->vdecl
, vdecl
);
3244 state
->changed
.group
|= NINE_STATE_VDECL
;
3248 if (state
->vdecl
== vdecl
)
3251 nine_bind(&state
->vdecl
, vdecl
);
3253 nine_context_set_vertex_declaration(This
, vdecl
);
3259 NineDevice9_GetVertexDeclaration( struct NineDevice9
*This
,
3260 IDirect3DVertexDeclaration9
**ppDecl
)
3262 user_assert(ppDecl
, D3DERR_INVALIDCALL
);
3264 *ppDecl
= (IDirect3DVertexDeclaration9
*)This
->state
.vdecl
;
3266 NineUnknown_AddRef(NineUnknown(*ppDecl
));
3271 NineDevice9_SetFVF( struct NineDevice9
*This
,
3274 struct NineVertexDeclaration9
*vdecl
;
3277 DBG("FVF = %08x\n", FVF
);
3279 return D3D_OK
; /* like wine */
3281 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3283 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3287 _mesa_hash_table_insert(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3288 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3290 return NineDevice9_SetVertexDeclaration(
3291 This
, (IDirect3DVertexDeclaration9
*)vdecl
);
3295 NineDevice9_GetFVF( struct NineDevice9
*This
,
3298 user_assert(pFVF
!= NULL
, D3DERR_INVALIDCALL
);
3299 *pFVF
= This
->state
.vdecl
? This
->state
.vdecl
->fvf
: 0;
3304 NineDevice9_CreateVertexShader( struct NineDevice9
*This
,
3305 const DWORD
*pFunction
,
3306 IDirect3DVertexShader9
**ppShader
)
3308 struct NineVertexShader9
*vs
;
3311 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3313 user_assert(pFunction
&& ppShader
, D3DERR_INVALIDCALL
);
3315 hr
= NineVertexShader9_new(This
, &vs
, pFunction
, NULL
);
3318 *ppShader
= (IDirect3DVertexShader9
*)vs
;
3323 NineDevice9_SetVertexShader( struct NineDevice9
*This
,
3324 IDirect3DVertexShader9
*pShader
)
3326 struct nine_state
*state
= This
->update
;
3327 struct NineVertexShader9
*vs_shader
= (struct NineVertexShader9
*)pShader
;
3329 DBG("This=%p pShader=%p\n", This
, pShader
);
3331 if (unlikely(This
->is_recording
)) {
3332 nine_bind(&state
->vs
, vs_shader
);
3333 state
->changed
.group
|= NINE_STATE_VS
;
3337 if (state
->vs
== vs_shader
)
3340 nine_bind(&state
->vs
, vs_shader
);
3342 nine_context_set_vertex_shader(This
, vs_shader
);
3348 NineDevice9_GetVertexShader( struct NineDevice9
*This
,
3349 IDirect3DVertexShader9
**ppShader
)
3351 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3352 nine_reference_set(ppShader
, This
->state
.vs
);
3357 NineDevice9_SetVertexShaderConstantF( struct NineDevice9
*This
,
3359 const float *pConstantData
,
3360 UINT Vector4fCount
)
3362 struct nine_state
*state
= This
->update
;
3363 float *vs_const_f
= state
->vs_const_f
;
3365 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3366 This
, StartRegister
, pConstantData
, Vector4fCount
);
3368 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3369 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3373 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3375 if (unlikely(This
->is_recording
)) {
3376 memcpy(&vs_const_f
[StartRegister
* 4],
3378 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3380 nine_ranges_insert(&state
->changed
.vs_const_f
,
3381 StartRegister
, StartRegister
+ Vector4fCount
,
3384 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3389 if (!memcmp(&vs_const_f
[StartRegister
* 4], pConstantData
,
3390 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0])))
3393 memcpy(&vs_const_f
[StartRegister
* 4],
3395 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3397 nine_context_set_vertex_shader_constant_f(This
, StartRegister
, pConstantData
,
3398 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]),
3405 NineDevice9_GetVertexShaderConstantF( struct NineDevice9
*This
,
3407 float *pConstantData
,
3408 UINT Vector4fCount
)
3410 const struct nine_state
*state
= &This
->state
;
3412 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
3413 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3414 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3415 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3417 memcpy(pConstantData
,
3418 &state
->vs_const_f
[StartRegister
* 4],
3419 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3425 NineDevice9_SetVertexShaderConstantI( struct NineDevice9
*This
,
3427 const int *pConstantData
,
3428 UINT Vector4iCount
)
3430 struct nine_state
*state
= This
->update
;
3433 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3434 This
, StartRegister
, pConstantData
, Vector4iCount
);
3436 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3437 D3DERR_INVALIDCALL
);
3438 user_assert(StartRegister
+ Vector4iCount
<= (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3439 D3DERR_INVALIDCALL
);
3440 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3442 if (This
->driver_caps
.vs_integer
) {
3443 if (!This
->is_recording
) {
3444 if (!memcmp(&state
->vs_const_i
[4 * StartRegister
], pConstantData
,
3445 Vector4iCount
* sizeof(int[4])))
3448 memcpy(&state
->vs_const_i
[4 * StartRegister
],
3450 Vector4iCount
* sizeof(int[4]));
3452 for (i
= 0; i
< Vector4iCount
; i
++) {
3453 state
->vs_const_i
[4 * (StartRegister
+ i
)] = fui((float)(pConstantData
[4 * i
]));
3454 state
->vs_const_i
[4 * (StartRegister
+ i
) + 1] = fui((float)(pConstantData
[4 * i
+ 1]));
3455 state
->vs_const_i
[4 * (StartRegister
+ i
) + 2] = fui((float)(pConstantData
[4 * i
+ 2]));
3456 state
->vs_const_i
[4 * (StartRegister
+ i
) + 3] = fui((float)(pConstantData
[4 * i
+ 3]));
3460 if (unlikely(This
->is_recording
)) {
3461 nine_ranges_insert(&state
->changed
.vs_const_i
,
3462 StartRegister
, StartRegister
+ Vector4iCount
,
3464 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3466 nine_context_set_vertex_shader_constant_i(This
, StartRegister
, pConstantData
,
3467 Vector4iCount
* sizeof(int[4]), Vector4iCount
);
3473 NineDevice9_GetVertexShaderConstantI( struct NineDevice9
*This
,
3476 UINT Vector4iCount
)
3478 const struct nine_state
*state
= &This
->state
;
3481 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
3482 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3483 D3DERR_INVALIDCALL
);
3484 user_assert(StartRegister
+ Vector4iCount
<= (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3485 D3DERR_INVALIDCALL
);
3486 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3488 if (This
->driver_caps
.vs_integer
) {
3489 memcpy(pConstantData
,
3490 &state
->vs_const_i
[4 * StartRegister
],
3491 Vector4iCount
* sizeof(int[4]));
3493 for (i
= 0; i
< Vector4iCount
; i
++) {
3494 pConstantData
[4 * i
] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
)]);
3495 pConstantData
[4 * i
+ 1] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 1]);
3496 pConstantData
[4 * i
+ 2] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 2]);
3497 pConstantData
[4 * i
+ 3] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 3]);
3505 NineDevice9_SetVertexShaderConstantB( struct NineDevice9
*This
,
3507 const BOOL
*pConstantData
,
3510 struct nine_state
*state
= This
->update
;
3512 uint32_t bool_true
= This
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
3514 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3515 This
, StartRegister
, pConstantData
, BoolCount
);
3517 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3518 D3DERR_INVALIDCALL
);
3519 user_assert(StartRegister
+ BoolCount
<= (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3520 D3DERR_INVALIDCALL
);
3521 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3523 if (!This
->is_recording
) {
3524 bool noChange
= true;
3525 for (i
= 0; i
< BoolCount
; i
++) {
3526 if (!!state
->vs_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3533 for (i
= 0; i
< BoolCount
; i
++)
3534 state
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3536 if (unlikely(This
->is_recording
)) {
3537 nine_ranges_insert(&state
->changed
.vs_const_b
,
3538 StartRegister
, StartRegister
+ BoolCount
,
3540 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3542 nine_context_set_vertex_shader_constant_b(This
, StartRegister
, pConstantData
,
3543 sizeof(BOOL
) * BoolCount
, BoolCount
);
3549 NineDevice9_GetVertexShaderConstantB( struct NineDevice9
*This
,
3551 BOOL
*pConstantData
,
3554 const struct nine_state
*state
= &This
->state
;
3557 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
3558 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3559 D3DERR_INVALIDCALL
);
3560 user_assert(StartRegister
+ BoolCount
<= (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3561 D3DERR_INVALIDCALL
);
3562 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3564 for (i
= 0; i
< BoolCount
; i
++)
3565 pConstantData
[i
] = state
->vs_const_b
[StartRegister
+ i
] != 0 ? TRUE
: FALSE
;
3571 NineDevice9_SetStreamSource( struct NineDevice9
*This
,
3573 IDirect3DVertexBuffer9
*pStreamData
,
3577 struct nine_state
*state
= This
->update
;
3578 struct NineVertexBuffer9
*pVBuf9
= NineVertexBuffer9(pStreamData
);
3579 const unsigned i
= StreamNumber
;
3581 DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",
3582 This
, StreamNumber
, pStreamData
, OffsetInBytes
, Stride
);
3584 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3585 user_assert(Stride
<= This
->caps
.MaxStreamStride
, D3DERR_INVALIDCALL
);
3587 if (unlikely(This
->is_recording
)) {
3588 nine_bind(&state
->stream
[i
], pStreamData
);
3589 state
->changed
.vtxbuf
|= 1 << StreamNumber
;
3590 state
->vtxbuf
[i
].stride
= Stride
;
3591 state
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
3595 if (state
->stream
[i
] == NineVertexBuffer9(pStreamData
) &&
3596 state
->vtxbuf
[i
].stride
== Stride
&&
3597 state
->vtxbuf
[i
].buffer_offset
== OffsetInBytes
)
3600 state
->vtxbuf
[i
].stride
= Stride
;
3601 state
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
3603 NineBindBufferToDevice(This
,
3604 (struct NineBuffer9
**)&state
->stream
[i
],
3605 (struct NineBuffer9
*)pVBuf9
);
3607 nine_context_set_stream_source(This
,
3617 NineDevice9_GetStreamSource( struct NineDevice9
*This
,
3619 IDirect3DVertexBuffer9
**ppStreamData
,
3620 UINT
*pOffsetInBytes
,
3623 const struct nine_state
*state
= &This
->state
;
3624 const unsigned i
= StreamNumber
;
3626 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3627 user_assert(ppStreamData
&& pOffsetInBytes
&& pStride
, D3DERR_INVALIDCALL
);
3629 nine_reference_set(ppStreamData
, state
->stream
[i
]);
3630 *pStride
= state
->vtxbuf
[i
].stride
;
3631 *pOffsetInBytes
= state
->vtxbuf
[i
].buffer_offset
;
3637 NineDevice9_SetStreamSourceFreq( struct NineDevice9
*This
,
3641 struct nine_state
*state
= This
->update
;
3642 /* const UINT freq = Setting & 0x7FFFFF; */
3644 DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This
,
3645 StreamNumber
, Setting
);
3647 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3648 user_assert(StreamNumber
!= 0 || !(Setting
& D3DSTREAMSOURCE_INSTANCEDATA
),
3649 D3DERR_INVALIDCALL
);
3650 user_assert(!((Setting
& D3DSTREAMSOURCE_INSTANCEDATA
) &&
3651 (Setting
& D3DSTREAMSOURCE_INDEXEDDATA
)), D3DERR_INVALIDCALL
);
3652 user_assert(Setting
, D3DERR_INVALIDCALL
);
3654 if (unlikely(This
->is_recording
)) {
3655 state
->stream_freq
[StreamNumber
] = Setting
;
3656 state
->changed
.stream_freq
|= 1 << StreamNumber
;
3660 if (state
->stream_freq
[StreamNumber
] == Setting
)
3663 state
->stream_freq
[StreamNumber
] = Setting
;
3665 nine_context_set_stream_source_freq(This
, StreamNumber
, Setting
);
3670 NineDevice9_GetStreamSourceFreq( struct NineDevice9
*This
,
3674 user_assert(pSetting
!= NULL
, D3DERR_INVALIDCALL
);
3675 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3676 *pSetting
= This
->state
.stream_freq
[StreamNumber
];
3681 NineDevice9_SetIndices( struct NineDevice9
*This
,
3682 IDirect3DIndexBuffer9
*pIndexData
)
3684 struct nine_state
*state
= This
->update
;
3685 struct NineIndexBuffer9
*idxbuf
= NineIndexBuffer9(pIndexData
);
3687 DBG("This=%p pIndexData=%p\n", This
, pIndexData
);
3689 if (unlikely(This
->is_recording
)) {
3690 nine_bind(&state
->idxbuf
, idxbuf
);
3691 state
->changed
.group
|= NINE_STATE_IDXBUF
;
3695 if (state
->idxbuf
== idxbuf
)
3698 NineBindBufferToDevice(This
,
3699 (struct NineBuffer9
**)&state
->idxbuf
,
3700 (struct NineBuffer9
*)idxbuf
);
3702 nine_context_set_indices(This
, idxbuf
);
3707 /* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
3708 * here because it's an argument passed to the Draw calls.
3711 NineDevice9_GetIndices( struct NineDevice9
*This
,
3712 IDirect3DIndexBuffer9
**ppIndexData
)
3714 user_assert(ppIndexData
, D3DERR_INVALIDCALL
);
3715 nine_reference_set(ppIndexData
, This
->state
.idxbuf
);
3720 NineDevice9_CreatePixelShader( struct NineDevice9
*This
,
3721 const DWORD
*pFunction
,
3722 IDirect3DPixelShader9
**ppShader
)
3724 struct NinePixelShader9
*ps
;
3727 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3729 user_assert(pFunction
&& ppShader
, D3DERR_INVALIDCALL
);
3731 hr
= NinePixelShader9_new(This
, &ps
, pFunction
, NULL
);
3734 *ppShader
= (IDirect3DPixelShader9
*)ps
;
3739 NineDevice9_SetPixelShader( struct NineDevice9
*This
,
3740 IDirect3DPixelShader9
*pShader
)
3742 struct nine_state
*state
= This
->update
;
3743 struct NinePixelShader9
*ps
= (struct NinePixelShader9
*)pShader
;
3745 DBG("This=%p pShader=%p\n", This
, pShader
);
3747 if (unlikely(This
->is_recording
)) {
3748 nine_bind(&state
->ps
, pShader
);
3749 state
->changed
.group
|= NINE_STATE_PS
;
3753 if (state
->ps
== ps
)
3756 nine_bind(&state
->ps
, ps
);
3758 nine_context_set_pixel_shader(This
, ps
);
3764 NineDevice9_GetPixelShader( struct NineDevice9
*This
,
3765 IDirect3DPixelShader9
**ppShader
)
3767 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3768 nine_reference_set(ppShader
, This
->state
.ps
);
3773 NineDevice9_SetPixelShaderConstantF( struct NineDevice9
*This
,
3775 const float *pConstantData
,
3776 UINT Vector4fCount
)
3778 struct nine_state
*state
= This
->update
;
3780 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3781 This
, StartRegister
, pConstantData
, Vector4fCount
);
3783 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3784 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3788 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3790 if (unlikely(This
->is_recording
)) {
3791 memcpy(&state
->ps_const_f
[StartRegister
* 4],
3793 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3795 nine_ranges_insert(&state
->changed
.ps_const_f
,
3796 StartRegister
, StartRegister
+ Vector4fCount
,
3799 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3803 if (!memcmp(&state
->ps_const_f
[StartRegister
* 4], pConstantData
,
3804 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0])))
3807 memcpy(&state
->ps_const_f
[StartRegister
* 4],
3809 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3811 nine_context_set_pixel_shader_constant_f(This
, StartRegister
, pConstantData
,
3812 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]),
3819 NineDevice9_GetPixelShaderConstantF( struct NineDevice9
*This
,
3821 float *pConstantData
,
3822 UINT Vector4fCount
)
3824 const struct nine_state
*state
= &This
->state
;
3826 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
3827 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3828 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3829 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3831 memcpy(pConstantData
,
3832 &state
->ps_const_f
[StartRegister
* 4],
3833 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3839 NineDevice9_SetPixelShaderConstantI( struct NineDevice9
*This
,
3841 const int *pConstantData
,
3842 UINT Vector4iCount
)
3844 struct nine_state
*state
= This
->update
;
3847 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3848 This
, StartRegister
, pConstantData
, Vector4iCount
);
3850 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3851 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3852 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3854 if (This
->driver_caps
.ps_integer
) {
3855 if (!This
->is_recording
) {
3856 if (!memcmp(&state
->ps_const_i
[StartRegister
][0], pConstantData
,
3857 Vector4iCount
* sizeof(state
->ps_const_i
[0])))
3860 memcpy(&state
->ps_const_i
[StartRegister
][0],
3862 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3864 for (i
= 0; i
< Vector4iCount
; i
++) {
3865 state
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
3866 state
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
3867 state
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
3868 state
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
3872 if (unlikely(This
->is_recording
)) {
3873 state
->changed
.ps_const_i
|= ((1 << Vector4iCount
) - 1) << StartRegister
;
3874 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3876 nine_context_set_pixel_shader_constant_i(This
, StartRegister
, pConstantData
,
3877 sizeof(state
->ps_const_i
[0]) * Vector4iCount
, Vector4iCount
);
3883 NineDevice9_GetPixelShaderConstantI( struct NineDevice9
*This
,
3886 UINT Vector4iCount
)
3888 const struct nine_state
*state
= &This
->state
;
3891 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
3892 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3893 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3894 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3896 if (This
->driver_caps
.ps_integer
) {
3897 memcpy(pConstantData
,
3898 &state
->ps_const_i
[StartRegister
][0],
3899 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3901 for (i
= 0; i
< Vector4iCount
; i
++) {
3902 pConstantData
[4*i
] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][0]);
3903 pConstantData
[4*i
+1] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][1]);
3904 pConstantData
[4*i
+2] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][2]);
3905 pConstantData
[4*i
+3] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][3]);
3913 NineDevice9_SetPixelShaderConstantB( struct NineDevice9
*This
,
3915 const BOOL
*pConstantData
,
3918 struct nine_state
*state
= This
->update
;
3920 uint32_t bool_true
= This
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
3922 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3923 This
, StartRegister
, pConstantData
, BoolCount
);
3925 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3926 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3927 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3929 if (!This
->is_recording
) {
3930 bool noChange
= true;
3931 for (i
= 0; i
< BoolCount
; i
++) {
3932 if (!!state
->ps_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3939 for (i
= 0; i
< BoolCount
; i
++)
3940 state
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3942 if (unlikely(This
->is_recording
)) {
3943 state
->changed
.ps_const_b
|= ((1 << BoolCount
) - 1) << StartRegister
;
3944 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3946 nine_context_set_pixel_shader_constant_b(This
, StartRegister
, pConstantData
,
3947 sizeof(BOOL
) * BoolCount
, BoolCount
);
3953 NineDevice9_GetPixelShaderConstantB( struct NineDevice9
*This
,
3955 BOOL
*pConstantData
,
3958 const struct nine_state
*state
= &This
->state
;
3961 user_assert(!This
->pure
, D3DERR_INVALIDCALL
);
3962 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3963 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3964 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3966 for (i
= 0; i
< BoolCount
; i
++)
3967 pConstantData
[i
] = state
->ps_const_b
[StartRegister
+ i
] ? TRUE
: FALSE
;
3973 NineDevice9_DrawRectPatch( struct NineDevice9
*This
,
3975 const float *pNumSegs
,
3976 const D3DRECTPATCH_INFO
*pRectPatchInfo
)
3978 STUB(D3DERR_INVALIDCALL
);
3982 NineDevice9_DrawTriPatch( struct NineDevice9
*This
,
3984 const float *pNumSegs
,
3985 const D3DTRIPATCH_INFO
*pTriPatchInfo
)
3987 STUB(D3DERR_INVALIDCALL
);
3991 NineDevice9_DeletePatch( struct NineDevice9
*This
,
3994 STUB(D3DERR_INVALIDCALL
);
3998 NineDevice9_CreateQuery( struct NineDevice9
*This
,
4000 IDirect3DQuery9
**ppQuery
)
4002 struct NineQuery9
*query
;
4005 DBG("This=%p Type=%d ppQuery=%p\n", This
, Type
, ppQuery
);
4007 hr
= nine_is_query_supported(This
->screen
, Type
);
4008 if (!ppQuery
|| hr
!= D3D_OK
)
4011 hr
= NineQuery9_new(This
, &query
, Type
);
4014 *ppQuery
= (IDirect3DQuery9
*)query
;
4018 IDirect3DDevice9Vtbl NineDevice9_vtable
= {
4019 (void *)NineUnknown_QueryInterface
,
4020 (void *)NineUnknown_AddRef
,
4021 (void *)NineUnknown_Release
,
4022 (void *)NineDevice9_TestCooperativeLevel
,
4023 (void *)NineDevice9_GetAvailableTextureMem
,
4024 (void *)NineDevice9_EvictManagedResources
,
4025 (void *)NineDevice9_GetDirect3D
,
4026 (void *)NineDevice9_GetDeviceCaps
,
4027 (void *)NineDevice9_GetDisplayMode
,
4028 (void *)NineDevice9_GetCreationParameters
,
4029 (void *)NineDevice9_SetCursorProperties
,
4030 (void *)NineDevice9_SetCursorPosition
,
4031 (void *)NineDevice9_ShowCursor
,
4032 (void *)NineDevice9_CreateAdditionalSwapChain
,
4033 (void *)NineDevice9_GetSwapChain
,
4034 (void *)NineDevice9_GetNumberOfSwapChains
,
4035 (void *)NineDevice9_Reset
,
4036 (void *)NineDevice9_Present
,
4037 (void *)NineDevice9_GetBackBuffer
,
4038 (void *)NineDevice9_GetRasterStatus
,
4039 (void *)NineDevice9_SetDialogBoxMode
,
4040 (void *)NineDevice9_SetGammaRamp
,
4041 (void *)NineDevice9_GetGammaRamp
,
4042 (void *)NineDevice9_CreateTexture
,
4043 (void *)NineDevice9_CreateVolumeTexture
,
4044 (void *)NineDevice9_CreateCubeTexture
,
4045 (void *)NineDevice9_CreateVertexBuffer
,
4046 (void *)NineDevice9_CreateIndexBuffer
,
4047 (void *)NineDevice9_CreateRenderTarget
,
4048 (void *)NineDevice9_CreateDepthStencilSurface
,
4049 (void *)NineDevice9_UpdateSurface
,
4050 (void *)NineDevice9_UpdateTexture
,
4051 (void *)NineDevice9_GetRenderTargetData
,
4052 (void *)NineDevice9_GetFrontBufferData
,
4053 (void *)NineDevice9_StretchRect
,
4054 (void *)NineDevice9_ColorFill
,
4055 (void *)NineDevice9_CreateOffscreenPlainSurface
,
4056 (void *)NineDevice9_SetRenderTarget
,
4057 (void *)NineDevice9_GetRenderTarget
,
4058 (void *)NineDevice9_SetDepthStencilSurface
,
4059 (void *)NineDevice9_GetDepthStencilSurface
,
4060 (void *)NineDevice9_BeginScene
,
4061 (void *)NineDevice9_EndScene
,
4062 (void *)NineDevice9_Clear
,
4063 (void *)NineDevice9_SetTransform
,
4064 (void *)NineDevice9_GetTransform
,
4065 (void *)NineDevice9_MultiplyTransform
,
4066 (void *)NineDevice9_SetViewport
,
4067 (void *)NineDevice9_GetViewport
,
4068 (void *)NineDevice9_SetMaterial
,
4069 (void *)NineDevice9_GetMaterial
,
4070 (void *)NineDevice9_SetLight
,
4071 (void *)NineDevice9_GetLight
,
4072 (void *)NineDevice9_LightEnable
,
4073 (void *)NineDevice9_GetLightEnable
,
4074 (void *)NineDevice9_SetClipPlane
,
4075 (void *)NineDevice9_GetClipPlane
,
4076 (void *)NineDevice9_SetRenderState
,
4077 (void *)NineDevice9_GetRenderState
,
4078 (void *)NineDevice9_CreateStateBlock
,
4079 (void *)NineDevice9_BeginStateBlock
,
4080 (void *)NineDevice9_EndStateBlock
,
4081 (void *)NineDevice9_SetClipStatus
,
4082 (void *)NineDevice9_GetClipStatus
,
4083 (void *)NineDevice9_GetTexture
,
4084 (void *)NineDevice9_SetTexture
,
4085 (void *)NineDevice9_GetTextureStageState
,
4086 (void *)NineDevice9_SetTextureStageState
,
4087 (void *)NineDevice9_GetSamplerState
,
4088 (void *)NineDevice9_SetSamplerState
,
4089 (void *)NineDevice9_ValidateDevice
,
4090 (void *)NineDevice9_SetPaletteEntries
,
4091 (void *)NineDevice9_GetPaletteEntries
,
4092 (void *)NineDevice9_SetCurrentTexturePalette
,
4093 (void *)NineDevice9_GetCurrentTexturePalette
,
4094 (void *)NineDevice9_SetScissorRect
,
4095 (void *)NineDevice9_GetScissorRect
,
4096 (void *)NineDevice9_SetSoftwareVertexProcessing
,
4097 (void *)NineDevice9_GetSoftwareVertexProcessing
,
4098 (void *)NineDevice9_SetNPatchMode
,
4099 (void *)NineDevice9_GetNPatchMode
,
4100 (void *)NineDevice9_DrawPrimitive
,
4101 (void *)NineDevice9_DrawIndexedPrimitive
,
4102 (void *)NineDevice9_DrawPrimitiveUP
,
4103 (void *)NineDevice9_DrawIndexedPrimitiveUP
,
4104 (void *)NineDevice9_ProcessVertices
,
4105 (void *)NineDevice9_CreateVertexDeclaration
,
4106 (void *)NineDevice9_SetVertexDeclaration
,
4107 (void *)NineDevice9_GetVertexDeclaration
,
4108 (void *)NineDevice9_SetFVF
,
4109 (void *)NineDevice9_GetFVF
,
4110 (void *)NineDevice9_CreateVertexShader
,
4111 (void *)NineDevice9_SetVertexShader
,
4112 (void *)NineDevice9_GetVertexShader
,
4113 (void *)NineDevice9_SetVertexShaderConstantF
,
4114 (void *)NineDevice9_GetVertexShaderConstantF
,
4115 (void *)NineDevice9_SetVertexShaderConstantI
,
4116 (void *)NineDevice9_GetVertexShaderConstantI
,
4117 (void *)NineDevice9_SetVertexShaderConstantB
,
4118 (void *)NineDevice9_GetVertexShaderConstantB
,
4119 (void *)NineDevice9_SetStreamSource
,
4120 (void *)NineDevice9_GetStreamSource
,
4121 (void *)NineDevice9_SetStreamSourceFreq
,
4122 (void *)NineDevice9_GetStreamSourceFreq
,
4123 (void *)NineDevice9_SetIndices
,
4124 (void *)NineDevice9_GetIndices
,
4125 (void *)NineDevice9_CreatePixelShader
,
4126 (void *)NineDevice9_SetPixelShader
,
4127 (void *)NineDevice9_GetPixelShader
,
4128 (void *)NineDevice9_SetPixelShaderConstantF
,
4129 (void *)NineDevice9_GetPixelShaderConstantF
,
4130 (void *)NineDevice9_SetPixelShaderConstantI
,
4131 (void *)NineDevice9_GetPixelShaderConstantI
,
4132 (void *)NineDevice9_SetPixelShaderConstantB
,
4133 (void *)NineDevice9_GetPixelShaderConstantB
,
4134 (void *)NineDevice9_DrawRectPatch
,
4135 (void *)NineDevice9_DrawTriPatch
,
4136 (void *)NineDevice9_DeletePatch
,
4137 (void *)NineDevice9_CreateQuery
4140 static const GUID
*NineDevice9_IIDs
[] = {
4141 &IID_IDirect3DDevice9
,
4147 NineDevice9_new( struct pipe_screen
*pScreen
,
4148 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
4150 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
4152 ID3DPresentGroup
*pPresentationGroup
,
4153 struct d3dadapter9_context
*pCTX
,
4155 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
4156 struct NineDevice9
**ppOut
,
4157 int minorVersionNum
)
4160 lock
= !!(pCreationParameters
->BehaviorFlags
& D3DCREATE_MULTITHREADED
);
4162 NINE_NEW(Device9
, ppOut
, lock
, /* args */
4163 pScreen
, pCreationParameters
, pCaps
,
4164 pPresentationParameters
, pD3D9
, pPresentationGroup
, pCTX
,
4165 ex
, pFullscreenDisplayMode
, minorVersionNum
);