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/u_format.h"
51 #include "util/u_surface.h"
52 #include "util/u_upload_mgr.h"
53 #include "hud/hud_context.h"
55 #include "cso_cache/cso_context.h"
57 #define DBG_CHANNEL DBG_DEVICE
59 #if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))
61 static void nine_setup_fpu()
65 __asm__
__volatile__ ("fnstcw %0" : "=m" (*&c
));
67 /* clear the control word */
69 /* d3d9 doc/wine tests: mask all exceptions, use single-precision
70 * and round to nearest */
73 __asm__
__volatile__ ("fldcw %0" : : "m" (*&c
));
78 static void nine_setup_fpu(void)
80 WARN_ONCE("FPU setup not supported on non-x86 platforms\n");
86 NineDevice9_SetDefaultState( struct NineDevice9
*This
, boolean is_reset
)
88 struct NineSurface9
*refSurf
= NULL
;
90 DBG("This=%p is_reset=%d\n", This
, (int) is_reset
);
92 assert(!This
->is_recording
);
94 nine_state_set_defaults(This
, &This
->caps
, is_reset
);
96 refSurf
= This
->swapchains
[0]->buffers
[0];
99 This
->state
.viewport
.X
= 0;
100 This
->state
.viewport
.Y
= 0;
101 This
->state
.viewport
.Width
= refSurf
->desc
.Width
;
102 This
->state
.viewport
.Height
= refSurf
->desc
.Height
;
104 nine_context_set_viewport(This
, &This
->state
.viewport
);
106 This
->state
.scissor
.minx
= 0;
107 This
->state
.scissor
.miny
= 0;
108 This
->state
.scissor
.maxx
= refSurf
->desc
.Width
;
109 This
->state
.scissor
.maxy
= refSurf
->desc
.Height
;
111 nine_context_set_scissor(This
, &This
->state
.scissor
);
113 if (This
->nswapchains
&& This
->swapchains
[0]->params
.EnableAutoDepthStencil
) {
114 nine_context_set_render_state(This
, D3DRS_ZENABLE
, TRUE
);
115 This
->state
.rs_advertised
[D3DRS_ZENABLE
] = TRUE
;
117 if (This
->state
.rs_advertised
[D3DRS_ZENABLE
])
118 NineDevice9_SetDepthStencilSurface(
119 This
, (IDirect3DSurface9
*)This
->swapchains
[0]->zsbuf
);
122 #define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
124 NineDevice9_ctor( struct NineDevice9
*This
,
125 struct NineUnknownParams
*pParams
,
126 struct pipe_screen
*pScreen
,
127 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
129 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
131 ID3DPresentGroup
*pPresentationGroup
,
132 struct d3dadapter9_context
*pCTX
,
134 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
135 int minorVersionNum
)
138 HRESULT hr
= NineUnknown_ctor(&This
->base
, pParams
);
140 DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "
141 "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",
142 This
, pParams
, pScreen
, pCreationParameters
, pCaps
, pPresentationParameters
, pD3D9
,
143 pPresentationGroup
, pCTX
, (int) ex
, pFullscreenDisplayMode
);
145 if (FAILED(hr
)) { return hr
; }
147 list_inithead(&This
->update_buffers
);
148 list_inithead(&This
->update_textures
);
149 list_inithead(&This
->managed_buffers
);
150 list_inithead(&This
->managed_textures
);
152 This
->screen
= pScreen
;
153 This
->screen_sw
= pCTX
->ref
;
156 This
->params
= *pCreationParameters
;
158 This
->present
= pPresentationGroup
;
159 This
->minor_version_num
= minorVersionNum
;
161 IDirect3D9_AddRef(This
->d3d9
);
162 ID3DPresentGroup_AddRef(This
->present
);
164 if (!(This
->params
.BehaviorFlags
& D3DCREATE_FPU_PRESERVE
))
167 if (This
->params
.BehaviorFlags
& D3DCREATE_SOFTWARE_VERTEXPROCESSING
) {
168 DBG("Application asked full Software Vertex Processing.\n");
170 This
->may_swvp
= true;
173 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
) {
174 DBG("Application asked mixed Software Vertex Processing.\n");
175 This
->may_swvp
= true;
177 This
->context
.swvp
= This
->swvp
;
178 /* TODO: check if swvp is resetted by device Resets */
180 if (This
->may_swvp
&&
181 (This
->screen
->get_shader_param(This
->screen
, PIPE_SHADER_VERTEX
,
182 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
)
183 < (NINE_MAX_CONST_F_SWVP
/2) * sizeof(float[4]) ||
184 This
->screen
->get_shader_param(This
->screen
, PIPE_SHADER_VERTEX
,
185 PIPE_SHADER_CAP_MAX_CONST_BUFFERS
) < 5)) {
186 /* Note: We just go on, some apps never use the abilities of
187 * swvp, and just set more constants than allowed at init.
188 * Only cards we support that are affected are the r500 */
189 WARN("Card unable to handle Software Vertex Processing. Game may fail\n");
192 /* When may_swvp, SetConstant* limits are different */
194 This
->caps
.MaxVertexShaderConst
= NINE_MAX_CONST_F_SWVP
;
196 This
->context
.pipe
= This
->screen
->context_create(This
->screen
, NULL
, 0);
197 This
->pipe_secondary
= This
->screen
->context_create(This
->screen
, NULL
, 0);
198 if (!This
->context
.pipe
|| !This
->pipe_secondary
) { return E_OUTOFMEMORY
; } /* guess */
199 This
->pipe_sw
= This
->screen_sw
->context_create(This
->screen_sw
, NULL
, 0);
200 if (!This
->pipe_sw
) { return E_OUTOFMEMORY
; }
202 This
->context
.cso
= cso_create_context(This
->context
.pipe
);
203 if (!This
->context
.cso
) { return E_OUTOFMEMORY
; } /* also a guess */
204 This
->cso_sw
= cso_create_context(This
->pipe_sw
);
205 if (!This
->cso_sw
) { return E_OUTOFMEMORY
; }
207 /* Create first, it messes up our state. */
208 This
->hud
= hud_create(This
->context
.pipe
, This
->context
.cso
); /* NULL result is fine */
210 /* Available memory counter. Updated only for allocations with this device
211 * instance. This is the Win 7 behavior.
212 * Win XP shares this counter across multiple devices. */
213 This
->available_texture_mem
= This
->screen
->get_param(This
->screen
, PIPE_CAP_VIDEO_MEMORY
);
214 if (This
->available_texture_mem
< 4096)
215 This
->available_texture_mem
<<= 20;
217 This
->available_texture_mem
= UINT_MAX
;
218 /* We cap texture memory usage to 80% of what is reported free initially
219 * This helps get closer Win behaviour. For example VertexBuffer allocation
220 * still succeeds when texture allocation fails. */
221 This
->available_texture_limit
= This
->available_texture_mem
* 20LL / 100LL;
223 /* create implicit swapchains */
224 This
->nswapchains
= ID3DPresentGroup_GetMultiheadCount(This
->present
);
225 This
->swapchains
= CALLOC(This
->nswapchains
,
226 sizeof(struct NineSwapChain9
*));
227 if (!This
->swapchains
) { return E_OUTOFMEMORY
; }
229 for (i
= 0; i
< This
->nswapchains
; ++i
) {
230 ID3DPresent
*present
;
232 hr
= ID3DPresentGroup_GetPresent(This
->present
, i
, &present
);
237 D3DDISPLAYMODEEX
*mode
= NULL
;
238 struct NineSwapChain9Ex
**ret
=
239 (struct NineSwapChain9Ex
**)&This
->swapchains
[i
];
241 if (pFullscreenDisplayMode
) mode
= &(pFullscreenDisplayMode
[i
]);
242 /* when this is a Device9Ex, it should create SwapChain9Exs */
243 hr
= NineSwapChain9Ex_new(This
, TRUE
, present
,
244 &pPresentationParameters
[i
], pCTX
,
245 This
->params
.hFocusWindow
, mode
, ret
);
247 hr
= NineSwapChain9_new(This
, TRUE
, present
,
248 &pPresentationParameters
[i
], pCTX
,
249 This
->params
.hFocusWindow
,
250 &This
->swapchains
[i
]);
253 ID3DPresent_Release(present
);
256 NineUnknown_ConvertRefToBind(NineUnknown(This
->swapchains
[i
]));
258 hr
= NineSwapChain9_GetBackBuffer(This
->swapchains
[i
], 0,
259 D3DBACKBUFFER_TYPE_MONO
,
260 (IDirect3DSurface9
**)
264 NineUnknown_ConvertRefToBind(NineUnknown(This
->state
.rt
[i
]));
265 nine_bind(&This
->context
.rt
[i
], This
->state
.rt
[i
]);
268 /* Initialize CSMT */
269 if (pCTX
->csmt_force
== 1)
270 This
->csmt_active
= true;
271 else if (pCTX
->csmt_force
== 0)
272 This
->csmt_active
= false;
274 /* r600 and radeonsi are thread safe. */
275 This
->csmt_active
= strstr(pScreen
->get_name(pScreen
), "AMD") != NULL
;
277 /* We rely on u_upload_mgr using persistent coherent buffers (which don't
278 * require flush to work in multi-pipe_context scenario) for vertex and
280 if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT
))
281 This
->csmt_active
= false;
283 if (This
->csmt_active
) {
284 This
->csmt_ctx
= nine_csmt_create(This
);
286 return E_OUTOFMEMORY
;
289 if (This
->csmt_active
)
290 DBG("\033[1;32mCSMT is active\033[0m\n");
292 This
->buffer_upload
= nine_upload_create(This
->pipe_secondary
, 4 * 1024 * 1024, 4);
294 /* Initialize a dummy VBO to be used when a vertex declaration does not
295 * specify all the inputs needed by vertex shader, on win default behavior
296 * is to pass 0,0,0,0 to the shader */
298 struct pipe_transfer
*transfer
;
299 struct pipe_resource tmpl
;
303 memset(&tmpl
, 0, sizeof(tmpl
));
304 tmpl
.target
= PIPE_BUFFER
;
305 tmpl
.format
= PIPE_FORMAT_R8_UNORM
;
306 tmpl
.width0
= 16; /* 4 floats */
312 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
313 tmpl
.bind
= PIPE_BIND_VERTEX_BUFFER
;
315 This
->dummy_vbo
= pScreen
->resource_create(pScreen
, &tmpl
);
317 if (!This
->dummy_vbo
)
318 return D3DERR_OUTOFVIDEOMEMORY
;
320 u_box_1d(0, 16, &box
);
321 data
= This
->context
.pipe
->transfer_map(This
->context
.pipe
, This
->dummy_vbo
, 0,
322 PIPE_TRANSFER_WRITE
|
323 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
328 This
->context
.pipe
->transfer_unmap(This
->context
.pipe
, transfer
);
331 This
->cursor
.software
= FALSE
;
332 This
->cursor
.hotspot
.x
= -1;
333 This
->cursor
.hotspot
.y
= -1;
335 struct pipe_resource tmpl
;
336 memset(&tmpl
, 0, sizeof(tmpl
));
337 tmpl
.target
= PIPE_TEXTURE_2D
;
338 tmpl
.format
= PIPE_FORMAT_R8G8B8A8_UNORM
;
345 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
346 tmpl
.bind
= PIPE_BIND_CURSOR
| PIPE_BIND_SAMPLER_VIEW
;
349 This
->cursor
.image
= pScreen
->resource_create(pScreen
, &tmpl
);
350 if (!This
->cursor
.image
)
351 return D3DERR_OUTOFVIDEOMEMORY
;
353 /* For uploading 32x32 (argb) cursor */
354 This
->cursor
.hw_upload_temp
= MALLOC(32 * 4 * 32);
355 if (!This
->cursor
.hw_upload_temp
)
356 return D3DERR_OUTOFVIDEOMEMORY
;
359 /* Create constant buffers. */
361 unsigned max_const_vs
, max_const_ps
;
363 /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
364 * we have to take in some more slots for int and bool*/
365 max_const_vs
= _min(pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
,
366 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
) /
369 /* ps 3.0: 224 float constants. All cards supported support at least
370 * 256 constants for ps */
371 max_const_ps
= NINE_MAX_CONST_F_PS3
+ (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
373 This
->max_vs_const_f
= max_const_vs
-
374 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
375 This
->max_ps_const_f
= max_const_ps
-
376 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
378 This
->vs_const_size
= max_const_vs
* sizeof(float[4]);
379 This
->ps_const_size
= max_const_ps
* sizeof(float[4]);
380 /* Include space for I,B constants for user constbuf. */
381 if (This
->may_swvp
) {
382 This
->state
.vs_const_f
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
383 This
->context
.vs_const_f_swvp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
384 if (!This
->context
.vs_const_f_swvp
)
385 return E_OUTOFMEMORY
;
386 This
->state
.vs_lconstf_temp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
387 This
->context
.vs_lconstf_temp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
388 This
->state
.vs_const_i
= CALLOC(NINE_MAX_CONST_I_SWVP
* sizeof(int[4]), 1);
389 This
->context
.vs_const_i
= CALLOC(NINE_MAX_CONST_I_SWVP
* sizeof(int[4]), 1);
390 This
->state
.vs_const_b
= CALLOC(NINE_MAX_CONST_B_SWVP
* sizeof(BOOL
), 1);
391 This
->context
.vs_const_b
= CALLOC(NINE_MAX_CONST_B_SWVP
* sizeof(BOOL
), 1);
393 This
->state
.vs_const_f
= CALLOC(NINE_MAX_CONST_F
* sizeof(float[4]), 1);
394 This
->context
.vs_const_f_swvp
= NULL
;
395 This
->state
.vs_lconstf_temp
= CALLOC(This
->vs_const_size
,1);
396 This
->context
.vs_lconstf_temp
= CALLOC(This
->vs_const_size
,1);
397 This
->state
.vs_const_i
= CALLOC(NINE_MAX_CONST_I
* sizeof(int[4]), 1);
398 This
->context
.vs_const_i
= CALLOC(NINE_MAX_CONST_I
* sizeof(int[4]), 1);
399 This
->state
.vs_const_b
= CALLOC(NINE_MAX_CONST_B
* sizeof(BOOL
), 1);
400 This
->context
.vs_const_b
= CALLOC(NINE_MAX_CONST_B
* sizeof(BOOL
), 1);
402 This
->context
.vs_const_f
= CALLOC(This
->vs_const_size
, 1);
403 This
->state
.ps_const_f
= CALLOC(This
->ps_const_size
, 1);
404 This
->context
.ps_const_f
= CALLOC(This
->ps_const_size
, 1);
405 This
->context
.ps_lconstf_temp
= CALLOC(This
->ps_const_size
,1);
406 if (!This
->state
.vs_const_f
|| !This
->context
.vs_const_f
||
407 !This
->state
.ps_const_f
|| !This
->context
.ps_const_f
||
408 !This
->state
.vs_lconstf_temp
|| !This
->context
.vs_lconstf_temp
||
409 !This
->context
.ps_lconstf_temp
||
410 !This
->state
.vs_const_i
|| !This
->context
.vs_const_i
||
411 !This
->state
.vs_const_b
|| !This
->context
.vs_const_b
)
412 return E_OUTOFMEMORY
;
414 if (strstr(pScreen
->get_name(pScreen
), "AMD") ||
415 strstr(pScreen
->get_name(pScreen
), "ATI")) {
416 This
->driver_bugs
.buggy_barycentrics
= TRUE
;
420 /* allocate dummy texture/sampler for when there are missing ones bound */
422 struct pipe_resource tmplt
;
423 struct pipe_sampler_view templ
;
424 struct pipe_sampler_state samp
;
425 memset(&tmplt
, 0, sizeof(tmplt
));
426 memset(&samp
, 0, sizeof(samp
));
428 tmplt
.target
= PIPE_TEXTURE_2D
;
432 tmplt
.last_level
= 0;
433 tmplt
.array_size
= 1;
434 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
436 tmplt
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
437 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
;
438 tmplt
.nr_samples
= 0;
440 This
->dummy_texture
= This
->screen
->resource_create(This
->screen
, &tmplt
);
441 if (!This
->dummy_texture
)
442 return D3DERR_DRIVERINTERNALERROR
;
444 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
445 templ
.u
.tex
.first_layer
= 0;
446 templ
.u
.tex
.last_layer
= 0;
447 templ
.u
.tex
.first_level
= 0;
448 templ
.u
.tex
.last_level
= 0;
449 templ
.swizzle_r
= PIPE_SWIZZLE_0
;
450 templ
.swizzle_g
= PIPE_SWIZZLE_0
;
451 templ
.swizzle_b
= PIPE_SWIZZLE_0
;
452 templ
.swizzle_a
= PIPE_SWIZZLE_1
;
453 templ
.target
= This
->dummy_texture
->target
;
455 This
->dummy_sampler_view
= This
->context
.pipe
->create_sampler_view(This
->context
.pipe
, This
->dummy_texture
, &templ
);
456 if (!This
->dummy_sampler_view
)
457 return D3DERR_DRIVERINTERNALERROR
;
459 samp
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
460 samp
.max_lod
= 15.0f
;
461 samp
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
462 samp
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
463 samp
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
464 samp
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
465 samp
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
466 samp
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
467 samp
.compare_func
= PIPE_FUNC_LEQUAL
;
468 samp
.normalized_coords
= 1;
469 samp
.seamless_cube_map
= 0;
470 This
->dummy_sampler_state
= samp
;
473 /* Allocate upload helper for drivers that suck (from st pov ;). */
475 This
->driver_caps
.user_vbufs
= GET_PCAP(USER_VERTEX_BUFFERS
) && !This
->csmt_active
;
476 This
->driver_caps
.user_ibufs
= GET_PCAP(USER_INDEX_BUFFERS
) && !This
->csmt_active
;
477 This
->driver_caps
.user_cbufs
= GET_PCAP(USER_CONSTANT_BUFFERS
);
478 This
->driver_caps
.user_sw_vbufs
= This
->screen_sw
->get_param(This
->screen_sw
, PIPE_CAP_USER_VERTEX_BUFFERS
);
479 This
->driver_caps
.user_sw_cbufs
= This
->screen_sw
->get_param(This
->screen_sw
, PIPE_CAP_USER_CONSTANT_BUFFERS
);
481 /* Implicit use of context pipe for vertex and index uploaded when
482 * csmt is not active. Does not need to sync since csmt is unactive,
483 * thus no need to call NineDevice9_GetPipe at each upload. */
484 if (!This
->driver_caps
.user_vbufs
)
485 This
->vertex_uploader
= u_upload_create(This
->csmt_active
?
486 This
->pipe_secondary
: This
->context
.pipe
,
488 PIPE_BIND_VERTEX_BUFFER
, PIPE_USAGE_STREAM
);
489 This
->vertex_sw_uploader
= u_upload_create(This
->pipe_sw
, 65536,
490 PIPE_BIND_VERTEX_BUFFER
, PIPE_USAGE_STREAM
);
491 if (!This
->driver_caps
.user_ibufs
)
492 This
->index_uploader
= u_upload_create(This
->csmt_active
?
493 This
->pipe_secondary
: This
->context
.pipe
,
495 PIPE_BIND_INDEX_BUFFER
, PIPE_USAGE_STREAM
);
496 if (!This
->driver_caps
.user_cbufs
) {
497 This
->constbuf_alignment
= GET_PCAP(CONSTANT_BUFFER_OFFSET_ALIGNMENT
);
498 This
->constbuf_uploader
= u_upload_create(This
->context
.pipe
, This
->vs_const_size
,
499 PIPE_BIND_CONSTANT_BUFFER
, PIPE_USAGE_STREAM
);
502 This
->constbuf_sw_uploader
= u_upload_create(This
->pipe_sw
, 128 * 1024,
503 PIPE_BIND_CONSTANT_BUFFER
, PIPE_USAGE_STREAM
);
505 This
->driver_caps
.window_space_position_support
= GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION
);
506 This
->driver_caps
.vs_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
, PIPE_SHADER_CAP_INTEGERS
);
507 This
->driver_caps
.ps_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_INTEGERS
);
508 This
->driver_caps
.offset_units_unscaled
= GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED
);
510 nine_ff_init(This
); /* initialize fixed function code */
512 NineDevice9_SetDefaultState(This
, FALSE
);
515 struct pipe_poly_stipple stipple
;
516 memset(&stipple
, ~0, sizeof(stipple
));
517 This
->context
.pipe
->set_polygon_stipple(This
->context
.pipe
, &stipple
);
520 This
->update
= &This
->state
;
522 nine_state_init_sw(This
);
524 ID3DPresentGroup_Release(This
->present
);
525 nine_csmt_process(This
);
532 NineDevice9_dtor( struct NineDevice9
*This
)
536 DBG("This=%p\n", This
);
538 /* Flush all pending commands to get refcount right,
539 * and properly release bound objects. It is ok to still
540 * execute commands while we are in device dtor, because
541 * we haven't released anything yet. Note that no pending
542 * command can increase the device refcount. */
543 if (This
->csmt_active
&& This
->csmt_ctx
) {
544 nine_csmt_process(This
);
545 nine_csmt_destroy(This
, This
->csmt_ctx
);
546 This
->csmt_active
= FALSE
;
547 This
->csmt_ctx
= NULL
;
551 nine_state_destroy_sw(This
);
552 nine_state_clear(&This
->state
, TRUE
);
553 nine_context_clear(This
);
555 if (This
->vertex_uploader
)
556 u_upload_destroy(This
->vertex_uploader
);
557 if (This
->index_uploader
)
558 u_upload_destroy(This
->index_uploader
);
559 if (This
->constbuf_uploader
)
560 u_upload_destroy(This
->constbuf_uploader
);
561 if (This
->vertex_sw_uploader
)
562 u_upload_destroy(This
->vertex_sw_uploader
);
563 if (This
->constbuf_sw_uploader
)
564 u_upload_destroy(This
->constbuf_sw_uploader
);
566 nine_bind(&This
->record
, NULL
);
568 pipe_sampler_view_reference(&This
->dummy_sampler_view
, NULL
);
569 pipe_resource_reference(&This
->dummy_texture
, NULL
);
570 pipe_resource_reference(&This
->dummy_vbo
, NULL
);
571 FREE(This
->state
.vs_const_f
);
572 FREE(This
->context
.vs_const_f
);
573 FREE(This
->state
.ps_const_f
);
574 FREE(This
->context
.ps_const_f
);
575 FREE(This
->state
.vs_lconstf_temp
);
576 FREE(This
->context
.vs_lconstf_temp
);
577 FREE(This
->context
.ps_lconstf_temp
);
578 FREE(This
->state
.vs_const_i
);
579 FREE(This
->context
.vs_const_i
);
580 FREE(This
->state
.vs_const_b
);
581 FREE(This
->context
.vs_const_b
);
582 FREE(This
->context
.vs_const_f_swvp
);
584 pipe_resource_reference(&This
->cursor
.image
, NULL
);
585 FREE(This
->cursor
.hw_upload_temp
);
587 if (This
->swapchains
) {
588 for (i
= 0; i
< This
->nswapchains
; ++i
)
589 if (This
->swapchains
[i
])
590 NineUnknown_Unbind(NineUnknown(This
->swapchains
[i
]));
591 FREE(This
->swapchains
);
594 if (This
->buffer_upload
)
595 nine_upload_destroy(This
->buffer_upload
);
597 /* Destroy cso first */
598 if (This
->context
.cso
) { cso_destroy_context(This
->context
.cso
); }
599 if (This
->cso_sw
) { cso_destroy_context(This
->cso_sw
); }
600 if (This
->context
.pipe
&& This
->context
.pipe
->destroy
) { This
->context
.pipe
->destroy(This
->context
.pipe
); }
601 if (This
->pipe_secondary
&& This
->pipe_secondary
->destroy
) { This
->pipe_secondary
->destroy(This
->pipe_secondary
); }
602 if (This
->pipe_sw
&& This
->pipe_sw
->destroy
) { This
->pipe_sw
->destroy(This
->pipe_sw
); }
604 if (This
->present
) { ID3DPresentGroup_Release(This
->present
); }
605 if (This
->d3d9
) { IDirect3D9_Release(This
->d3d9
); }
607 NineUnknown_dtor(&This
->base
);
611 NineDevice9_GetScreen( struct NineDevice9
*This
)
616 struct pipe_context
*
617 NineDevice9_GetPipe( struct NineDevice9
*This
)
619 return nine_context_get_pipe(This
);
623 NineDevice9_GetCaps( struct NineDevice9
*This
)
629 NineDevice9_PauseRecording( struct NineDevice9
*This
)
632 This
->update
= &This
->state
;
633 This
->is_recording
= FALSE
;
638 NineDevice9_ResumeRecording( struct NineDevice9
*This
)
641 This
->update
= &This
->record
->state
;
642 This
->is_recording
= TRUE
;
647 NineDevice9_TestCooperativeLevel( struct NineDevice9
*This
)
649 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
650 This
->device_needs_reset
= TRUE
;
651 return D3DERR_DEVICELOST
;
652 } else if (NineSwapChain9_ResolutionMismatch(This
->swapchains
[0])) {
653 This
->device_needs_reset
= TRUE
;
654 return D3DERR_DEVICENOTRESET
;
655 } else if (This
->device_needs_reset
) {
656 return D3DERR_DEVICENOTRESET
;
663 NineDevice9_GetAvailableTextureMem( struct NineDevice9
*This
)
665 return This
->available_texture_mem
;
669 NineDevice9_EvictManagedResources( struct NineDevice9
*This
)
671 struct NineBaseTexture9
*tex
;
672 struct NineBuffer9
*buf
;
674 DBG("This=%p\n", This
);
675 LIST_FOR_EACH_ENTRY(tex
, &This
->managed_textures
, list2
) {
676 NineBaseTexture9_UnLoad(tex
);
678 /* Vertex/index buffers don't take a lot of space and aren't accounted
679 * for d3d memory usage. Instead of actually freeing from memory,
680 * just mark the buffer dirty to trigger a re-upload later. We
681 * could just ignore, but some bad behaving apps could rely on it (if
682 * they write outside the locked regions typically). */
683 LIST_FOR_EACH_ENTRY(buf
, &This
->managed_buffers
, managed
.list2
) {
684 NineBuffer9_SetDirty(buf
);
691 NineDevice9_GetDirect3D( struct NineDevice9
*This
,
692 IDirect3D9
**ppD3D9
)
694 user_assert(ppD3D9
!= NULL
, E_POINTER
);
695 IDirect3D9_AddRef(This
->d3d9
);
696 *ppD3D9
= This
->d3d9
;
701 NineDevice9_GetDeviceCaps( struct NineDevice9
*This
,
704 user_assert(pCaps
!= NULL
, D3DERR_INVALIDCALL
);
710 NineDevice9_GetDisplayMode( struct NineDevice9
*This
,
712 D3DDISPLAYMODE
*pMode
)
714 DBG("This=%p iSwapChain=%u pMode=%p\n", This
, iSwapChain
, pMode
);
716 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
718 return NineSwapChain9_GetDisplayMode(This
->swapchains
[iSwapChain
], pMode
);
722 NineDevice9_GetCreationParameters( struct NineDevice9
*This
,
723 D3DDEVICE_CREATION_PARAMETERS
*pParameters
)
725 user_assert(pParameters
!= NULL
, D3DERR_INVALIDCALL
);
726 *pParameters
= This
->params
;
731 NineDevice9_SetCursorProperties( struct NineDevice9
*This
,
734 IDirect3DSurface9
*pCursorBitmap
)
736 struct NineSurface9
*surf
= NineSurface9(pCursorBitmap
);
737 struct pipe_context
*pipe
= NineDevice9_GetPipe(This
);
739 struct pipe_transfer
*transfer
;
743 DBG_FLAG(DBG_SWAPCHAIN
, "This=%p XHotSpot=%u YHotSpot=%u "
744 "pCursorBitmap=%p\n", This
, XHotSpot
, YHotSpot
, pCursorBitmap
);
746 user_assert(pCursorBitmap
, D3DERR_INVALIDCALL
);
747 user_assert(surf
->desc
.Format
== D3DFMT_A8R8G8B8
, D3DERR_INVALIDCALL
);
749 if (This
->swapchains
[0]->params
.Windowed
) {
750 This
->cursor
.w
= MIN2(surf
->desc
.Width
, 32);
751 This
->cursor
.h
= MIN2(surf
->desc
.Height
, 32);
752 hw_cursor
= 1; /* always use hw cursor for windowed mode */
754 This
->cursor
.w
= MIN2(surf
->desc
.Width
, This
->cursor
.image
->width0
);
755 This
->cursor
.h
= MIN2(surf
->desc
.Height
, This
->cursor
.image
->height0
);
756 hw_cursor
= This
->cursor
.w
== 32 && This
->cursor
.h
== 32;
759 u_box_origin_2d(This
->cursor
.w
, This
->cursor
.h
, &box
);
761 ptr
= pipe
->transfer_map(pipe
, This
->cursor
.image
, 0,
762 PIPE_TRANSFER_WRITE
|
763 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
766 ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR
);
768 This
->cursor
.hotspot
.x
= XHotSpot
;
769 This
->cursor
.hotspot
.y
= YHotSpot
;
771 /* Copy cursor image to internal storage. */
775 const struct util_format_description
*sfmt
=
776 util_format_description(surf
->base
.info
.format
);
779 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, D3DLOCK_READONLY
);
781 ret_err("Failed to map cursor source image.\n",
782 D3DERR_DRIVERINTERNALERROR
);
784 sfmt
->unpack_rgba_8unorm(ptr
, transfer
->stride
,
785 lock
.pBits
, lock
.Pitch
,
786 This
->cursor
.w
, This
->cursor
.h
);
789 void *data
= lock
.pBits
;
790 /* SetCursor assumes 32x32 argb with pitch 128 */
791 if (lock
.Pitch
!= 128) {
792 sfmt
->unpack_rgba_8unorm(This
->cursor
.hw_upload_temp
, 128,
793 lock
.pBits
, lock
.Pitch
,
795 data
= This
->cursor
.hw_upload_temp
;
797 hw_cursor
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
,
799 &This
->cursor
.hotspot
,
800 This
->cursor
.visible
) == D3D_OK
;
803 NineSurface9_UnlockRect(surf
);
805 pipe
->transfer_unmap(pipe
, transfer
);
807 /* hide cursor if we emulate it */
809 ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, FALSE
);
810 This
->cursor
.software
= !hw_cursor
;
816 NineDevice9_SetCursorPosition( struct NineDevice9
*This
,
821 struct NineSwapChain9
*swap
= This
->swapchains
[0];
823 DBG("This=%p X=%d Y=%d Flags=%d\n", This
, X
, Y
, Flags
);
825 This
->cursor
.pos
.x
= X
;
826 This
->cursor
.pos
.y
= Y
;
828 if (!This
->cursor
.software
)
829 This
->cursor
.software
= ID3DPresent_SetCursorPos(swap
->present
, &This
->cursor
.pos
) != D3D_OK
;
833 NineDevice9_ShowCursor( struct NineDevice9
*This
,
836 BOOL old
= This
->cursor
.visible
;
838 DBG("This=%p bShow=%d\n", This
, (int) bShow
);
840 This
->cursor
.visible
= bShow
&& (This
->cursor
.hotspot
.x
!= -1);
841 if (!This
->cursor
.software
)
842 This
->cursor
.software
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, bShow
) != D3D_OK
;
848 NineDevice9_CreateAdditionalSwapChain( struct NineDevice9
*This
,
849 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
850 IDirect3DSwapChain9
**pSwapChain
)
852 struct NineSwapChain9
*swapchain
, *tmplt
= This
->swapchains
[0];
853 ID3DPresent
*present
;
856 DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",
857 This
, pPresentationParameters
, pSwapChain
);
859 user_assert(pPresentationParameters
, D3DERR_INVALIDCALL
);
860 user_assert(tmplt
->params
.Windowed
&& pPresentationParameters
->Windowed
, D3DERR_INVALIDCALL
);
862 /* TODO: this deserves more tests */
863 if (!pPresentationParameters
->hDeviceWindow
)
864 pPresentationParameters
->hDeviceWindow
= This
->params
.hFocusWindow
;
866 hr
= ID3DPresentGroup_CreateAdditionalPresent(This
->present
, pPresentationParameters
, &present
);
871 hr
= NineSwapChain9_new(This
, FALSE
, present
, pPresentationParameters
,
873 tmplt
->params
.hDeviceWindow
,
878 *pSwapChain
= (IDirect3DSwapChain9
*)swapchain
;
883 NineDevice9_GetSwapChain( struct NineDevice9
*This
,
885 IDirect3DSwapChain9
**pSwapChain
)
887 user_assert(pSwapChain
!= NULL
, D3DERR_INVALIDCALL
);
890 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
892 NineUnknown_AddRef(NineUnknown(This
->swapchains
[iSwapChain
]));
893 *pSwapChain
= (IDirect3DSwapChain9
*)This
->swapchains
[iSwapChain
];
899 NineDevice9_GetNumberOfSwapChains( struct NineDevice9
*This
)
901 return This
->nswapchains
;
905 NineDevice9_Reset( struct NineDevice9
*This
,
906 D3DPRESENT_PARAMETERS
*pPresentationParameters
)
911 DBG("This=%p pPresentationParameters=%p\n", This
, pPresentationParameters
);
913 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
914 This
->device_needs_reset
= TRUE
;
915 return D3DERR_DEVICELOST
;
918 for (i
= 0; i
< This
->nswapchains
; ++i
) {
919 D3DPRESENT_PARAMETERS
*params
= &pPresentationParameters
[i
];
920 hr
= NineSwapChain9_Resize(This
->swapchains
[i
], params
, NULL
);
925 nine_csmt_process(This
);
926 nine_state_clear(&This
->state
, TRUE
);
927 nine_context_clear(This
);
929 NineDevice9_SetDefaultState(This
, TRUE
);
930 NineDevice9_SetRenderTarget(
931 This
, 0, (IDirect3DSurface9
*)This
->swapchains
[0]->buffers
[0]);
932 /* XXX: better use GetBackBuffer here ? */
934 This
->device_needs_reset
= (hr
!= D3D_OK
);
939 NineDevice9_Present( struct NineDevice9
*This
,
940 const RECT
*pSourceRect
,
941 const RECT
*pDestRect
,
942 HWND hDestWindowOverride
,
943 const RGNDATA
*pDirtyRegion
)
948 DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",
949 This
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
);
951 /* XXX is this right? */
952 for (i
= 0; i
< This
->nswapchains
; ++i
) {
953 hr
= NineSwapChain9_Present(This
->swapchains
[i
], pSourceRect
, pDestRect
,
954 hDestWindowOverride
, pDirtyRegion
, 0);
955 if (FAILED(hr
)) { return hr
; }
962 NineDevice9_GetBackBuffer( struct NineDevice9
*This
,
965 D3DBACKBUFFER_TYPE Type
,
966 IDirect3DSurface9
**ppBackBuffer
)
968 user_assert(ppBackBuffer
!= NULL
, D3DERR_INVALIDCALL
);
969 /* return NULL on error */
970 *ppBackBuffer
= NULL
;
971 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
973 return NineSwapChain9_GetBackBuffer(This
->swapchains
[iSwapChain
],
974 iBackBuffer
, Type
, ppBackBuffer
);
978 NineDevice9_GetRasterStatus( struct NineDevice9
*This
,
980 D3DRASTER_STATUS
*pRasterStatus
)
982 user_assert(pRasterStatus
!= NULL
, D3DERR_INVALIDCALL
);
983 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
985 return NineSwapChain9_GetRasterStatus(This
->swapchains
[iSwapChain
],
990 NineDevice9_SetDialogBoxMode( struct NineDevice9
*This
,
991 BOOL bEnableDialogs
)
993 STUB(D3DERR_INVALIDCALL
);
997 NineDevice9_SetGammaRamp( struct NineDevice9
*This
,
1000 const D3DGAMMARAMP
*pRamp
)
1002 DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This
,
1003 iSwapChain
, Flags
, pRamp
);
1005 user_warn(iSwapChain
>= This
->nswapchains
);
1008 if (pRamp
&& (iSwapChain
< This
->nswapchains
)) {
1009 struct NineSwapChain9
*swap
= This
->swapchains
[iSwapChain
];
1010 swap
->gamma
= *pRamp
;
1011 ID3DPresent_SetGammaRamp(swap
->present
, pRamp
, swap
->params
.hDeviceWindow
);
1016 NineDevice9_GetGammaRamp( struct NineDevice9
*This
,
1018 D3DGAMMARAMP
*pRamp
)
1020 DBG("This=%p iSwapChain=%u pRamp=%p\n", This
, iSwapChain
, pRamp
);
1022 user_warn(iSwapChain
>= This
->nswapchains
);
1025 if (pRamp
&& (iSwapChain
< This
->nswapchains
))
1026 *pRamp
= This
->swapchains
[iSwapChain
]->gamma
;
1030 NineDevice9_CreateTexture( struct NineDevice9
*This
,
1037 IDirect3DTexture9
**ppTexture
,
1038 HANDLE
*pSharedHandle
)
1040 struct NineTexture9
*tex
;
1043 DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
1044 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Levels
,
1045 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1046 nine_D3DPOOL_to_str(Pool
), ppTexture
, pSharedHandle
);
1048 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DMAP
|
1049 D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
1050 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
;
1054 hr
= NineTexture9_new(This
, Width
, Height
, Levels
, Usage
, Format
, Pool
,
1055 &tex
, pSharedHandle
);
1057 *ppTexture
= (IDirect3DTexture9
*)tex
;
1063 NineDevice9_CreateVolumeTexture( struct NineDevice9
*This
,
1071 IDirect3DVolumeTexture9
**ppVolumeTexture
,
1072 HANDLE
*pSharedHandle
)
1074 struct NineVolumeTexture9
*tex
;
1077 DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
1078 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Depth
, Levels
,
1079 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1080 nine_D3DPOOL_to_str(Pool
), ppVolumeTexture
, pSharedHandle
);
1082 Usage
&= D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1083 D3DUSAGE_SOFTWAREPROCESSING
;
1085 *ppVolumeTexture
= NULL
;
1087 hr
= NineVolumeTexture9_new(This
, Width
, Height
, Depth
, Levels
,
1088 Usage
, Format
, Pool
, &tex
, pSharedHandle
);
1090 *ppVolumeTexture
= (IDirect3DVolumeTexture9
*)tex
;
1096 NineDevice9_CreateCubeTexture( struct NineDevice9
*This
,
1102 IDirect3DCubeTexture9
**ppCubeTexture
,
1103 HANDLE
*pSharedHandle
)
1105 struct NineCubeTexture9
*tex
;
1108 DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
1109 "pSharedHandle=%p\n", This
, EdgeLength
, Levels
,
1110 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1111 nine_D3DPOOL_to_str(Pool
), ppCubeTexture
, pSharedHandle
);
1113 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DYNAMIC
|
1114 D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
1115 D3DUSAGE_SOFTWAREPROCESSING
;
1117 *ppCubeTexture
= NULL
;
1119 hr
= NineCubeTexture9_new(This
, EdgeLength
, Levels
, Usage
, Format
, Pool
,
1120 &tex
, pSharedHandle
);
1122 *ppCubeTexture
= (IDirect3DCubeTexture9
*)tex
;
1128 NineDevice9_CreateVertexBuffer( struct NineDevice9
*This
,
1133 IDirect3DVertexBuffer9
**ppVertexBuffer
,
1134 HANDLE
*pSharedHandle
)
1136 struct NineVertexBuffer9
*buf
;
1138 D3DVERTEXBUFFER_DESC desc
;
1140 DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
1141 This
, Length
, Usage
, FVF
, Pool
, ppVertexBuffer
, pSharedHandle
);
1143 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1145 desc
.Format
= D3DFMT_VERTEXDATA
;
1146 desc
.Type
= D3DRTYPE_VERTEXBUFFER
;
1147 desc
.Usage
= Usage
&
1148 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1149 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1150 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
|
1151 D3DUSAGE_WRITEONLY
);
1156 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1157 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1159 hr
= NineVertexBuffer9_new(This
, &desc
, &buf
);
1161 *ppVertexBuffer
= (IDirect3DVertexBuffer9
*)buf
;
1166 NineDevice9_CreateIndexBuffer( struct NineDevice9
*This
,
1171 IDirect3DIndexBuffer9
**ppIndexBuffer
,
1172 HANDLE
*pSharedHandle
)
1174 struct NineIndexBuffer9
*buf
;
1176 D3DINDEXBUFFER_DESC desc
;
1178 DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
1179 "pSharedHandle=%p\n", This
, Length
, Usage
,
1180 d3dformat_to_string(Format
), Pool
, ppIndexBuffer
, pSharedHandle
);
1182 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1184 desc
.Format
= Format
;
1185 desc
.Type
= D3DRTYPE_INDEXBUFFER
;
1186 desc
.Usage
= Usage
&
1187 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1188 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1189 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_WRITEONLY
);
1193 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1194 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1196 hr
= NineIndexBuffer9_new(This
, &desc
, &buf
);
1198 *ppIndexBuffer
= (IDirect3DIndexBuffer9
*)buf
;
1203 create_zs_or_rt_surface(struct NineDevice9
*This
,
1204 unsigned type
, /* 0 = RT, 1 = ZS, 2 = plain */
1206 UINT Width
, UINT Height
,
1208 D3DMULTISAMPLE_TYPE MultiSample
,
1209 DWORD MultisampleQuality
,
1210 BOOL Discard_or_Lockable
,
1211 IDirect3DSurface9
**ppSurface
,
1212 HANDLE
*pSharedHandle
)
1214 struct NineSurface9
*surface
;
1216 D3DSURFACE_DESC desc
;
1218 DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
1219 "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
1220 This
, type
, nine_D3DPOOL_to_str(Pool
), Width
, Height
,
1221 d3dformat_to_string(Format
), MultiSample
, MultisampleQuality
,
1222 Discard_or_Lockable
, ppSurface
, pSharedHandle
);
1225 DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
1227 user_assert(Width
&& Height
, D3DERR_INVALIDCALL
);
1228 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1230 desc
.Format
= Format
;
1231 desc
.Type
= D3DRTYPE_SURFACE
;
1234 desc
.MultiSampleType
= MultiSample
;
1235 desc
.MultiSampleQuality
= MultisampleQuality
;
1237 desc
.Height
= Height
;
1239 case 0: desc
.Usage
= D3DUSAGE_RENDERTARGET
; break;
1240 case 1: desc
.Usage
= D3DUSAGE_DEPTHSTENCIL
; break;
1241 default: assert(type
== 2); break;
1244 hr
= NineSurface9_new(This
, NULL
, NULL
, NULL
, 0, 0, 0, &desc
, &surface
);
1245 if (SUCCEEDED(hr
)) {
1246 *ppSurface
= (IDirect3DSurface9
*)surface
;
1248 if (surface
->base
.resource
&& Discard_or_Lockable
&& (type
!= 1))
1249 surface
->base
.resource
->flags
|= NINE_RESOURCE_FLAG_LOCKABLE
;
1256 NineDevice9_CreateRenderTarget( struct NineDevice9
*This
,
1260 D3DMULTISAMPLE_TYPE MultiSample
,
1261 DWORD MultisampleQuality
,
1263 IDirect3DSurface9
**ppSurface
,
1264 HANDLE
*pSharedHandle
)
1267 return create_zs_or_rt_surface(This
, 0, D3DPOOL_DEFAULT
,
1268 Width
, Height
, Format
,
1269 MultiSample
, MultisampleQuality
,
1270 Lockable
, ppSurface
, pSharedHandle
);
1274 NineDevice9_CreateDepthStencilSurface( struct NineDevice9
*This
,
1278 D3DMULTISAMPLE_TYPE MultiSample
,
1279 DWORD MultisampleQuality
,
1281 IDirect3DSurface9
**ppSurface
,
1282 HANDLE
*pSharedHandle
)
1285 if (!depth_stencil_format(Format
))
1286 return D3DERR_NOTAVAILABLE
;
1287 return create_zs_or_rt_surface(This
, 1, D3DPOOL_DEFAULT
,
1288 Width
, Height
, Format
,
1289 MultiSample
, MultisampleQuality
,
1290 Discard
, ppSurface
, pSharedHandle
);
1294 NineDevice9_UpdateSurface( struct NineDevice9
*This
,
1295 IDirect3DSurface9
*pSourceSurface
,
1296 const RECT
*pSourceRect
,
1297 IDirect3DSurface9
*pDestinationSurface
,
1298 const POINT
*pDestPoint
)
1300 struct NineSurface9
*dst
= NineSurface9(pDestinationSurface
);
1301 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1302 int copy_width
, copy_height
;
1305 DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
1306 "pSourceRect=%p pDestPoint=%p\n", This
,
1307 pSourceSurface
, pDestinationSurface
, pSourceRect
, pDestPoint
);
1309 DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
1310 pSourceRect
->left
, pSourceRect
->top
,
1311 pSourceRect
->right
, pSourceRect
->bottom
);
1313 DBG("pDestPoint = (%u,%u)\n", pDestPoint
->x
, pDestPoint
->y
);
1315 user_assert(dst
&& src
, D3DERR_INVALIDCALL
);
1317 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1318 user_assert(src
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1320 user_assert(dst
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1321 user_assert(src
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1323 user_assert(!src
->lock_count
, D3DERR_INVALIDCALL
);
1324 user_assert(!dst
->lock_count
, D3DERR_INVALIDCALL
);
1326 user_assert(dst
->desc
.Format
== src
->desc
.Format
, D3DERR_INVALIDCALL
);
1327 user_assert(!depth_stencil_format(dst
->desc
.Format
), D3DERR_INVALIDCALL
);
1330 copy_width
= pSourceRect
->right
- pSourceRect
->left
;
1331 copy_height
= pSourceRect
->bottom
- pSourceRect
->top
;
1333 user_assert(pSourceRect
->left
>= 0 &&
1335 pSourceRect
->right
<= src
->desc
.Width
&&
1336 pSourceRect
->top
>= 0 &&
1338 pSourceRect
->bottom
<= src
->desc
.Height
,
1339 D3DERR_INVALIDCALL
);
1341 copy_width
= src
->desc
.Width
;
1342 copy_height
= src
->desc
.Height
;
1345 destRect
.right
= copy_width
;
1346 destRect
.bottom
= copy_height
;
1349 user_assert(pDestPoint
->x
>= 0 && pDestPoint
->y
>= 0,
1350 D3DERR_INVALIDCALL
);
1351 destRect
.right
+= pDestPoint
->x
;
1352 destRect
.bottom
+= pDestPoint
->y
;
1355 user_assert(destRect
.right
<= dst
->desc
.Width
&&
1356 destRect
.bottom
<= dst
->desc
.Height
,
1357 D3DERR_INVALIDCALL
);
1359 if (compressed_format(dst
->desc
.Format
)) {
1360 const unsigned w
= util_format_get_blockwidth(dst
->base
.info
.format
);
1361 const unsigned h
= util_format_get_blockheight(dst
->base
.info
.format
);
1364 user_assert(!(pDestPoint
->x
% w
) && !(pDestPoint
->y
% h
),
1365 D3DERR_INVALIDCALL
);
1369 user_assert(!(pSourceRect
->left
% w
) && !(pSourceRect
->top
% h
),
1370 D3DERR_INVALIDCALL
);
1372 if (!(copy_width
== src
->desc
.Width
&&
1373 copy_width
== dst
->desc
.Width
&&
1374 copy_height
== src
->desc
.Height
&&
1375 copy_height
== dst
->desc
.Height
)) {
1376 user_assert(!(copy_width
% w
) && !(copy_height
% h
),
1377 D3DERR_INVALIDCALL
);
1381 NineSurface9_CopyMemToDefault(dst
, src
, pDestPoint
, pSourceRect
);
1387 NineDevice9_UpdateTexture( struct NineDevice9
*This
,
1388 IDirect3DBaseTexture9
*pSourceTexture
,
1389 IDirect3DBaseTexture9
*pDestinationTexture
)
1391 struct NineBaseTexture9
*dstb
= NineBaseTexture9(pDestinationTexture
);
1392 struct NineBaseTexture9
*srcb
= NineBaseTexture9(pSourceTexture
);
1394 unsigned last_src_level
, last_dst_level
;
1397 DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This
,
1398 pSourceTexture
, pDestinationTexture
);
1400 user_assert(pSourceTexture
&& pDestinationTexture
, D3DERR_INVALIDCALL
);
1401 user_assert(pSourceTexture
!= pDestinationTexture
, D3DERR_INVALIDCALL
);
1403 user_assert(dstb
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1404 user_assert(srcb
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1405 user_assert(dstb
->base
.type
== srcb
->base
.type
, D3DERR_INVALIDCALL
);
1406 user_assert(!(srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ||
1407 dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
, D3DERR_INVALIDCALL
);
1410 * . Different formats
1411 * . Fewer src levels than dst levels (if the opposite, only matching levels
1412 * are supposed to be copied)
1413 * . Levels do not match
1414 * DDI: Actually the above should pass because of legacy applications
1415 * Do what you want about these, but you shouldn't crash.
1416 * However driver can expect that the top dimension is greater for src than dst.
1417 * Wine tests: Every combination that passes the initial checks should pass.
1418 * . Different formats => conversion driver and format dependent.
1419 * . 1 level, but size not matching => copy is done (and even crash if src bigger
1420 * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied
1421 * or if a subrect is copied).
1422 * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect
1425 * From these, the proposal is:
1426 * . Different formats -> use util_format_translate to translate if possible for surfaces.
1427 * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations
1428 * . First level copied -> the first level such that src is smaller or equal to dst first level
1429 * . number of levels copied -> as long as it fits and textures have levels
1430 * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK)
1433 last_src_level
= (srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ? 0 : srcb
->base
.info
.last_level
;
1434 last_dst_level
= (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ? 0 : dstb
->base
.info
.last_level
;
1436 for (m
= 0; m
<= last_src_level
; ++m
) {
1437 unsigned w
= u_minify(srcb
->base
.info
.width0
, m
);
1438 unsigned h
= u_minify(srcb
->base
.info
.height0
, m
);
1439 unsigned d
= u_minify(srcb
->base
.info
.depth0
, m
);
1441 if (w
<= dstb
->base
.info
.width0
&&
1442 h
<= dstb
->base
.info
.height0
&&
1443 d
<= dstb
->base
.info
.depth0
)
1446 user_assert(m
<= last_src_level
, D3D_OK
);
1448 last_dst_level
= MIN2(srcb
->base
.info
.last_level
- m
, last_dst_level
);
1450 if (dstb
->base
.type
== D3DRTYPE_TEXTURE
) {
1451 struct NineTexture9
*dst
= NineTexture9(dstb
);
1452 struct NineTexture9
*src
= NineTexture9(srcb
);
1454 if (src
->dirty_rect
.width
== 0)
1457 pipe_box_to_rect(&rect
, &src
->dirty_rect
);
1458 for (l
= 0; l
< m
; ++l
)
1459 rect_minify_inclusive(&rect
);
1461 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
) {
1462 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1464 dst
->surfaces
[l
]->desc
.Width
,
1465 dst
->surfaces
[l
]->desc
.Height
);
1466 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
],
1470 rect_minify_inclusive(&rect
);
1472 u_box_origin_2d(0, 0, &src
->dirty_rect
);
1474 if (dstb
->base
.type
== D3DRTYPE_CUBETEXTURE
) {
1475 struct NineCubeTexture9
*dst
= NineCubeTexture9(dstb
);
1476 struct NineCubeTexture9
*src
= NineCubeTexture9(srcb
);
1479 /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
1480 for (z
= 0; z
< 6; ++z
) {
1481 if (src
->dirty_rect
[z
].width
== 0)
1484 pipe_box_to_rect(&rect
, &src
->dirty_rect
[z
]);
1485 for (l
= 0; l
< m
; ++l
)
1486 rect_minify_inclusive(&rect
);
1488 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
) {
1489 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1491 dst
->surfaces
[l
* 6 + z
]->desc
.Width
,
1492 dst
->surfaces
[l
* 6 + z
]->desc
.Height
);
1493 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
* 6 + z
],
1494 src
->surfaces
[m
* 6 + z
],
1497 rect_minify_inclusive(&rect
);
1499 u_box_origin_2d(0, 0, &src
->dirty_rect
[z
]);
1503 if (dstb
->base
.type
== D3DRTYPE_VOLUMETEXTURE
) {
1504 struct NineVolumeTexture9
*dst
= NineVolumeTexture9(dstb
);
1505 struct NineVolumeTexture9
*src
= NineVolumeTexture9(srcb
);
1507 if (src
->dirty_box
.width
== 0)
1509 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
)
1510 NineVolume9_CopyMemToDefault(dst
->volumes
[l
],
1511 src
->volumes
[m
], 0, 0, 0, NULL
);
1512 u_box_3d(0, 0, 0, 0, 0, 0, &src
->dirty_box
);
1514 assert(!"invalid texture type");
1517 if (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) {
1518 dstb
->dirty_mip
= TRUE
;
1519 NineBaseTexture9_GenerateMipSubLevels(dstb
);
1526 NineDevice9_GetRenderTargetData( struct NineDevice9
*This
,
1527 IDirect3DSurface9
*pRenderTarget
,
1528 IDirect3DSurface9
*pDestSurface
)
1530 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1531 struct NineSurface9
*src
= NineSurface9(pRenderTarget
);
1533 DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
1534 This
, pRenderTarget
, pDestSurface
);
1536 user_assert(pRenderTarget
&& pDestSurface
, D3DERR_INVALIDCALL
);
1538 user_assert(dst
->desc
.Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1539 user_assert(src
->desc
.Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1541 user_assert(dst
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1542 user_assert(src
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1544 user_assert(src
->desc
.Width
== dst
->desc
.Width
, D3DERR_INVALIDCALL
);
1545 user_assert(src
->desc
.Height
== dst
->desc
.Height
, D3DERR_INVALIDCALL
);
1547 user_assert(src
->desc
.Format
!= D3DFMT_NULL
, D3DERR_INVALIDCALL
);
1549 NineSurface9_CopyDefaultToMem(dst
, src
);
1555 NineDevice9_GetFrontBufferData( struct NineDevice9
*This
,
1557 IDirect3DSurface9
*pDestSurface
)
1559 DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This
,
1560 iSwapChain
, pDestSurface
);
1562 user_assert(pDestSurface
!= NULL
, D3DERR_INVALIDCALL
);
1563 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
1565 return NineSwapChain9_GetFrontBufferData(This
->swapchains
[iSwapChain
],
1570 NineDevice9_StretchRect( struct NineDevice9
*This
,
1571 IDirect3DSurface9
*pSourceSurface
,
1572 const RECT
*pSourceRect
,
1573 IDirect3DSurface9
*pDestSurface
,
1574 const RECT
*pDestRect
,
1575 D3DTEXTUREFILTERTYPE Filter
)
1577 struct pipe_screen
*screen
= This
->screen
;
1578 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1579 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1580 struct pipe_resource
*dst_res
= NineSurface9_GetResource(dst
);
1581 struct pipe_resource
*src_res
= NineSurface9_GetResource(src
);
1583 struct pipe_blit_info blit
;
1584 boolean scaled
, clamped
, ms
, flip_x
= FALSE
, flip_y
= FALSE
;
1586 DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
1587 "pDestRect=%p Filter=%u\n",
1588 This
, pSourceSurface
, pSourceRect
, pDestSurface
, pDestRect
, Filter
);
1590 DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
1591 pSourceRect
->left
, pSourceRect
->top
,
1592 pSourceRect
->right
, pSourceRect
->bottom
);
1594 DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect
->left
, pDestRect
->top
,
1595 pDestRect
->right
, pDestRect
->bottom
);
1597 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
&&
1598 src
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1599 zs
= util_format_is_depth_or_stencil(dst_res
->format
);
1600 user_assert(!zs
|| !This
->in_scene
, D3DERR_INVALIDCALL
);
1601 user_assert(!zs
|| !pSourceRect
||
1602 (pSourceRect
->left
== 0 &&
1603 pSourceRect
->top
== 0 &&
1604 pSourceRect
->right
== src
->desc
.Width
&&
1605 pSourceRect
->bottom
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1606 user_assert(!zs
|| !pDestRect
||
1607 (pDestRect
->left
== 0 &&
1608 pDestRect
->top
== 0 &&
1609 pDestRect
->right
== dst
->desc
.Width
&&
1610 pDestRect
->bottom
== dst
->desc
.Height
), D3DERR_INVALIDCALL
);
1612 (dst
->desc
.Width
== src
->desc
.Width
&&
1613 dst
->desc
.Height
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1614 user_assert(zs
|| !util_format_is_depth_or_stencil(src_res
->format
),
1615 D3DERR_INVALIDCALL
);
1616 user_assert(!zs
|| dst
->desc
.Format
== src
->desc
.Format
,
1617 D3DERR_INVALIDCALL
);
1618 user_assert(screen
->is_format_supported(screen
, src_res
->format
,
1620 src_res
->nr_samples
,
1621 PIPE_BIND_SAMPLER_VIEW
),
1622 D3DERR_INVALIDCALL
);
1624 /* We might want to permit these, but wine thinks we shouldn't. */
1625 user_assert(!pDestRect
||
1626 (pDestRect
->left
<= pDestRect
->right
&&
1627 pDestRect
->top
<= pDestRect
->bottom
), D3DERR_INVALIDCALL
);
1628 user_assert(!pSourceRect
||
1629 (pSourceRect
->left
<= pSourceRect
->right
&&
1630 pSourceRect
->top
<= pSourceRect
->bottom
), D3DERR_INVALIDCALL
);
1632 memset(&blit
, 0, sizeof(blit
));
1633 blit
.dst
.resource
= dst_res
;
1634 blit
.dst
.level
= dst
->level
;
1635 blit
.dst
.box
.z
= dst
->layer
;
1636 blit
.dst
.box
.depth
= 1;
1637 blit
.dst
.format
= dst_res
->format
;
1639 flip_x
= pDestRect
->left
> pDestRect
->right
;
1641 blit
.dst
.box
.x
= pDestRect
->right
;
1642 blit
.dst
.box
.width
= pDestRect
->left
- pDestRect
->right
;
1644 blit
.dst
.box
.x
= pDestRect
->left
;
1645 blit
.dst
.box
.width
= pDestRect
->right
- pDestRect
->left
;
1647 flip_y
= pDestRect
->top
> pDestRect
->bottom
;
1649 blit
.dst
.box
.y
= pDestRect
->bottom
;
1650 blit
.dst
.box
.height
= pDestRect
->top
- pDestRect
->bottom
;
1652 blit
.dst
.box
.y
= pDestRect
->top
;
1653 blit
.dst
.box
.height
= pDestRect
->bottom
- pDestRect
->top
;
1658 blit
.dst
.box
.width
= dst
->desc
.Width
;
1659 blit
.dst
.box
.height
= dst
->desc
.Height
;
1661 blit
.src
.resource
= src_res
;
1662 blit
.src
.level
= src
->level
;
1663 blit
.src
.box
.z
= src
->layer
;
1664 blit
.src
.box
.depth
= 1;
1665 blit
.src
.format
= src_res
->format
;
1667 if (flip_x
^ (pSourceRect
->left
> pSourceRect
->right
)) {
1668 blit
.src
.box
.x
= pSourceRect
->right
;
1669 blit
.src
.box
.width
= pSourceRect
->left
- pSourceRect
->right
;
1671 blit
.src
.box
.x
= pSourceRect
->left
;
1672 blit
.src
.box
.width
= pSourceRect
->right
- pSourceRect
->left
;
1674 if (flip_y
^ (pSourceRect
->top
> pSourceRect
->bottom
)) {
1675 blit
.src
.box
.y
= pSourceRect
->bottom
;
1676 blit
.src
.box
.height
= pSourceRect
->top
- pSourceRect
->bottom
;
1678 blit
.src
.box
.y
= pSourceRect
->top
;
1679 blit
.src
.box
.height
= pSourceRect
->bottom
- pSourceRect
->top
;
1682 blit
.src
.box
.x
= flip_x
? src
->desc
.Width
: 0;
1683 blit
.src
.box
.y
= flip_y
? src
->desc
.Height
: 0;
1684 blit
.src
.box
.width
= flip_x
? -src
->desc
.Width
: src
->desc
.Width
;
1685 blit
.src
.box
.height
= flip_y
? -src
->desc
.Height
: src
->desc
.Height
;
1687 blit
.mask
= zs
? PIPE_MASK_ZS
: PIPE_MASK_RGBA
;
1688 blit
.filter
= Filter
== D3DTEXF_LINEAR
?
1689 PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
1690 blit
.scissor_enable
= FALSE
;
1691 blit
.alpha_blend
= FALSE
;
1693 /* If both of a src and dst dimension are negative, flip them. */
1694 if (blit
.dst
.box
.width
< 0 && blit
.src
.box
.width
< 0) {
1695 blit
.dst
.box
.width
= -blit
.dst
.box
.width
;
1696 blit
.src
.box
.width
= -blit
.src
.box
.width
;
1698 if (blit
.dst
.box
.height
< 0 && blit
.src
.box
.height
< 0) {
1699 blit
.dst
.box
.height
= -blit
.dst
.box
.height
;
1700 blit
.src
.box
.height
= -blit
.src
.box
.height
;
1703 blit
.dst
.box
.width
!= blit
.src
.box
.width
||
1704 blit
.dst
.box
.height
!= blit
.src
.box
.height
;
1706 user_assert(!scaled
|| dst
!= src
, D3DERR_INVALIDCALL
);
1707 user_assert(!scaled
||
1708 !NineSurface9_IsOffscreenPlain(dst
), D3DERR_INVALIDCALL
);
1709 user_assert(!NineSurface9_IsOffscreenPlain(dst
) ||
1710 NineSurface9_IsOffscreenPlain(src
), D3DERR_INVALIDCALL
);
1711 user_assert(NineSurface9_IsOffscreenPlain(dst
) ||
1712 dst
->desc
.Usage
& (D3DUSAGE_RENDERTARGET
| D3DUSAGE_DEPTHSTENCIL
),
1713 D3DERR_INVALIDCALL
);
1714 user_assert(!scaled
||
1715 (!util_format_is_compressed(dst
->base
.info
.format
) &&
1716 !util_format_is_compressed(src
->base
.info
.format
)),
1717 D3DERR_INVALIDCALL
);
1719 user_warn(src
== dst
&&
1720 u_box_test_intersection_2d(&blit
.src
.box
, &blit
.dst
.box
));
1722 /* Check for clipping/clamping: */
1724 struct pipe_box box
;
1727 xy
= u_box_clip_2d(&box
, &blit
.dst
.box
,
1728 dst
->desc
.Width
, dst
->desc
.Height
);
1732 xy
= u_box_clip_2d(&box
, &blit
.src
.box
,
1733 src
->desc
.Width
, src
->desc
.Height
);
1737 ms
= (dst
->desc
.MultiSampleType
!= src
->desc
.MultiSampleType
) ||
1738 (dst
->desc
.MultiSampleQuality
!= src
->desc
.MultiSampleQuality
);
1740 if (clamped
|| scaled
|| (blit
.dst
.format
!= blit
.src
.format
) || ms
) {
1741 DBG("using pipe->blit()\n");
1742 /* TODO: software scaling */
1743 user_assert(screen
->is_format_supported(screen
, dst_res
->format
,
1745 dst_res
->nr_samples
,
1746 zs
? PIPE_BIND_DEPTH_STENCIL
:
1747 PIPE_BIND_RENDER_TARGET
),
1748 D3DERR_INVALIDCALL
);
1750 nine_context_blit(This
, (struct NineUnknown
*)dst
,
1751 (struct NineUnknown
*)src
, &blit
);
1753 assert(blit
.dst
.box
.x
>= 0 && blit
.dst
.box
.y
>= 0 &&
1754 blit
.src
.box
.x
>= 0 && blit
.src
.box
.y
>= 0 &&
1755 blit
.dst
.box
.x
+ blit
.dst
.box
.width
<= dst
->desc
.Width
&&
1756 blit
.src
.box
.x
+ blit
.src
.box
.width
<= src
->desc
.Width
&&
1757 blit
.dst
.box
.y
+ blit
.dst
.box
.height
<= dst
->desc
.Height
&&
1758 blit
.src
.box
.y
+ blit
.src
.box
.height
<= src
->desc
.Height
);
1759 /* Or drivers might crash ... */
1760 DBG("Using resource_copy_region.\n");
1761 nine_context_resource_copy_region(This
, (struct NineUnknown
*)dst
,
1762 (struct NineUnknown
*)src
,
1763 blit
.dst
.resource
, blit
.dst
.level
,
1765 blit
.src
.resource
, blit
.src
.level
,
1769 /* Communicate the container it needs to update sublevels - if apply */
1770 NineSurface9_MarkContainerDirty(dst
);
1776 NineDevice9_ColorFill( struct NineDevice9
*This
,
1777 IDirect3DSurface9
*pSurface
,
1781 struct NineSurface9
*surf
= NineSurface9(pSurface
);
1782 unsigned x
, y
, w
, h
;
1784 DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This
,
1785 pSurface
, pRect
, color
);
1787 DBG("pRect=(%u,%u)-(%u,%u)\n", pRect
->left
, pRect
->top
,
1788 pRect
->right
, pRect
->bottom
);
1790 user_assert(surf
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1792 user_assert((surf
->base
.usage
& D3DUSAGE_RENDERTARGET
) ||
1793 NineSurface9_IsOffscreenPlain(surf
), D3DERR_INVALIDCALL
);
1795 user_assert(surf
->desc
.Format
!= D3DFMT_NULL
, D3D_OK
);
1800 w
= pRect
->right
- pRect
->left
;
1801 h
= pRect
->bottom
- pRect
->top
;
1803 if (compressed_format(surf
->desc
.Format
)) {
1804 const unsigned bw
= util_format_get_blockwidth(surf
->base
.info
.format
);
1805 const unsigned bh
= util_format_get_blockheight(surf
->base
.info
.format
);
1807 user_assert(!(x
% bw
) && !(y
% bh
) && !(w
% bw
) && !(h
% bh
),
1808 D3DERR_INVALIDCALL
);
1813 w
= surf
->desc
.Width
;
1814 h
= surf
->desc
.Height
;
1817 if (surf
->base
.info
.bind
& PIPE_BIND_RENDER_TARGET
) {
1818 nine_context_clear_render_target(This
, surf
, color
, x
, y
, w
, h
);
1820 D3DLOCKED_RECT lock
;
1821 union util_color uc
;
1823 /* XXX: lock pRect and fix util_fill_rect */
1824 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, pRect
? 0 : D3DLOCK_DISCARD
);
1827 util_pack_color_ub(color
>> 16, color
>> 8, color
>> 0, color
>> 24,
1828 surf
->base
.info
.format
, &uc
);
1829 util_fill_rect(lock
.pBits
, surf
->base
.info
.format
,lock
.Pitch
,
1831 NineSurface9_UnlockRect(surf
);
1838 NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9
*This
,
1843 IDirect3DSurface9
**ppSurface
,
1844 HANDLE
*pSharedHandle
)
1848 DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
1849 "ppSurface=%p pSharedHandle=%p\n", This
,
1850 Width
, Height
, d3dformat_to_string(Format
), Format
, Pool
,
1851 ppSurface
, pSharedHandle
);
1854 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
1855 || Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1856 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1858 /* Can be used with StretchRect and ColorFill. It's also always lockable.
1860 hr
= create_zs_or_rt_surface(This
, 2, Pool
, Width
, Height
,
1862 D3DMULTISAMPLE_NONE
, 0,
1864 ppSurface
, pSharedHandle
);
1866 DBG("Failed to create surface.\n");
1871 NineDevice9_SetRenderTarget( struct NineDevice9
*This
,
1872 DWORD RenderTargetIndex
,
1873 IDirect3DSurface9
*pRenderTarget
)
1875 struct NineSurface9
*rt
= NineSurface9(pRenderTarget
);
1876 const unsigned i
= RenderTargetIndex
;
1878 DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This
,
1879 RenderTargetIndex
, pRenderTarget
);
1881 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1882 user_assert(i
!= 0 || pRenderTarget
, D3DERR_INVALIDCALL
);
1883 user_assert(!pRenderTarget
||
1884 rt
->desc
.Usage
& D3DUSAGE_RENDERTARGET
, D3DERR_INVALIDCALL
);
1887 This
->state
.viewport
.X
= 0;
1888 This
->state
.viewport
.Y
= 0;
1889 This
->state
.viewport
.Width
= rt
->desc
.Width
;
1890 This
->state
.viewport
.Height
= rt
->desc
.Height
;
1891 This
->state
.viewport
.MinZ
= 0.0f
;
1892 This
->state
.viewport
.MaxZ
= 1.0f
;
1894 This
->state
.scissor
.minx
= 0;
1895 This
->state
.scissor
.miny
= 0;
1896 This
->state
.scissor
.maxx
= rt
->desc
.Width
;
1897 This
->state
.scissor
.maxy
= rt
->desc
.Height
;
1900 if (This
->state
.rt
[i
] != NineSurface9(pRenderTarget
))
1901 nine_bind(&This
->state
.rt
[i
], pRenderTarget
);
1903 nine_context_set_render_target(This
, i
, rt
);
1908 NineDevice9_GetRenderTarget( struct NineDevice9
*This
,
1909 DWORD RenderTargetIndex
,
1910 IDirect3DSurface9
**ppRenderTarget
)
1912 const unsigned i
= RenderTargetIndex
;
1914 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1915 user_assert(ppRenderTarget
, D3DERR_INVALIDCALL
);
1917 *ppRenderTarget
= (IDirect3DSurface9
*)This
->state
.rt
[i
];
1918 if (!This
->state
.rt
[i
])
1919 return D3DERR_NOTFOUND
;
1921 NineUnknown_AddRef(NineUnknown(This
->state
.rt
[i
]));
1926 NineDevice9_SetDepthStencilSurface( struct NineDevice9
*This
,
1927 IDirect3DSurface9
*pNewZStencil
)
1929 struct NineSurface9
*ds
= NineSurface9(pNewZStencil
);
1930 DBG("This=%p pNewZStencil=%p\n", This
, pNewZStencil
);
1932 if (This
->state
.ds
!= ds
) {
1933 nine_bind(&This
->state
.ds
, ds
);
1934 nine_context_set_depth_stencil(This
, ds
);
1940 NineDevice9_GetDepthStencilSurface( struct NineDevice9
*This
,
1941 IDirect3DSurface9
**ppZStencilSurface
)
1943 user_assert(ppZStencilSurface
, D3DERR_INVALIDCALL
);
1945 *ppZStencilSurface
= (IDirect3DSurface9
*)This
->state
.ds
;
1946 if (!This
->state
.ds
)
1947 return D3DERR_NOTFOUND
;
1949 NineUnknown_AddRef(NineUnknown(This
->state
.ds
));
1954 NineDevice9_BeginScene( struct NineDevice9
*This
)
1956 DBG("This=%p\n", This
);
1957 user_assert(!This
->in_scene
, D3DERR_INVALIDCALL
);
1958 This
->in_scene
= TRUE
;
1959 /* Do we want to do anything else here ? */
1964 NineDevice9_EndScene( struct NineDevice9
*This
)
1966 DBG("This=%p\n", This
);
1967 user_assert(This
->in_scene
, D3DERR_INVALIDCALL
);
1968 This
->in_scene
= FALSE
;
1973 NineDevice9_Clear( struct NineDevice9
*This
,
1975 const D3DRECT
*pRects
,
1981 struct NineSurface9
*zsbuf_surf
= This
->state
.ds
;
1983 DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
1984 This
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
1986 user_assert(This
->state
.ds
|| !(Flags
& NINED3DCLEAR_DEPTHSTENCIL
),
1987 D3DERR_INVALIDCALL
);
1988 user_assert(!(Flags
& D3DCLEAR_STENCIL
) ||
1990 util_format_is_depth_and_stencil(zsbuf_surf
->base
.info
.format
)),
1991 D3DERR_INVALIDCALL
);
1993 user_assert((Count
&& pRects
) || (!Count
&& !pRects
), D3DERR_INVALIDCALL
);
1995 user_warn((pRects
&& !Count
) || (!pRects
&& Count
));
1996 if (pRects
&& !Count
)
2002 nine_context_clear_fb(This
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
2007 NineDevice9_SetTransform( struct NineDevice9
*This
,
2008 D3DTRANSFORMSTATETYPE State
,
2009 const D3DMATRIX
*pMatrix
)
2011 struct nine_state
*state
= This
->update
;
2012 D3DMATRIX
*M
= nine_state_access_transform(&state
->ff
, State
, TRUE
);
2014 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2016 user_assert(M
, D3DERR_INVALIDCALL
);
2019 if (unlikely(This
->is_recording
)) {
2020 state
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
2021 state
->changed
.group
|= NINE_STATE_FF
;
2023 nine_context_set_transform(This
, State
, pMatrix
);
2029 NineDevice9_GetTransform( struct NineDevice9
*This
,
2030 D3DTRANSFORMSTATETYPE State
,
2031 D3DMATRIX
*pMatrix
)
2033 D3DMATRIX
*M
= nine_state_access_transform(&This
->state
.ff
, State
, FALSE
);
2034 user_assert(M
, D3DERR_INVALIDCALL
);
2040 NineDevice9_MultiplyTransform( struct NineDevice9
*This
,
2041 D3DTRANSFORMSTATETYPE State
,
2042 const D3DMATRIX
*pMatrix
)
2044 struct nine_state
*state
= This
->update
;
2046 D3DMATRIX
*M
= nine_state_access_transform(&state
->ff
, State
, TRUE
);
2048 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2050 user_assert(M
, D3DERR_INVALIDCALL
);
2052 nine_d3d_matrix_matrix_mul(&T
, pMatrix
, M
);
2053 return NineDevice9_SetTransform(This
, State
, &T
);
2057 NineDevice9_SetViewport( struct NineDevice9
*This
,
2058 const D3DVIEWPORT9
*pViewport
)
2060 struct nine_state
*state
= This
->update
;
2062 DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
2063 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
,
2064 pViewport
->MinZ
, pViewport
->MaxZ
);
2066 state
->viewport
= *pViewport
;
2067 nine_context_set_viewport(This
, pViewport
);
2073 NineDevice9_GetViewport( struct NineDevice9
*This
,
2074 D3DVIEWPORT9
*pViewport
)
2076 *pViewport
= This
->state
.viewport
;
2081 NineDevice9_SetMaterial( struct NineDevice9
*This
,
2082 const D3DMATERIAL9
*pMaterial
)
2084 struct nine_state
*state
= This
->update
;
2086 DBG("This=%p pMaterial=%p\n", This
, pMaterial
);
2088 nine_dump_D3DMATERIAL9(DBG_FF
, pMaterial
);
2090 user_assert(pMaterial
, E_POINTER
);
2092 state
->ff
.material
= *pMaterial
;
2093 if (unlikely(This
->is_recording
))
2094 state
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
2096 nine_context_set_material(This
, pMaterial
);
2102 NineDevice9_GetMaterial( struct NineDevice9
*This
,
2103 D3DMATERIAL9
*pMaterial
)
2105 user_assert(pMaterial
, E_POINTER
);
2106 *pMaterial
= This
->state
.ff
.material
;
2111 NineDevice9_SetLight( struct NineDevice9
*This
,
2113 const D3DLIGHT9
*pLight
)
2115 struct nine_state
*state
= This
->update
;
2118 DBG("This=%p Index=%u pLight=%p\n", This
, Index
, pLight
);
2120 nine_dump_D3DLIGHT9(DBG_FF
, pLight
);
2122 user_assert(pLight
, D3DERR_INVALIDCALL
);
2123 user_assert(pLight
->Type
< NINED3DLIGHT_INVALID
, D3DERR_INVALIDCALL
);
2125 user_assert(Index
< NINE_MAX_LIGHTS
, D3DERR_INVALIDCALL
); /* sanity */
2127 hr
= nine_state_set_light(&state
->ff
, Index
, pLight
);
2131 if (pLight
->Type
!= D3DLIGHT_DIRECTIONAL
&&
2132 pLight
->Attenuation0
== 0.0f
&&
2133 pLight
->Attenuation1
== 0.0f
&&
2134 pLight
->Attenuation2
== 0.0f
) {
2135 DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
2138 if (unlikely(This
->is_recording
))
2139 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2141 nine_context_set_light(This
, Index
, pLight
);
2147 NineDevice9_GetLight( struct NineDevice9
*This
,
2151 const struct nine_state
*state
= &This
->state
;
2153 user_assert(pLight
, D3DERR_INVALIDCALL
);
2154 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2155 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2156 D3DERR_INVALIDCALL
);
2158 *pLight
= state
->ff
.light
[Index
];
2164 NineDevice9_LightEnable( struct NineDevice9
*This
,
2168 struct nine_state
*state
= This
->update
;
2170 DBG("This=%p Index=%u Enable=%i\n", This
, Index
, Enable
);
2172 if (Index
>= state
->ff
.num_lights
||
2173 state
->ff
.light
[Index
].Type
== NINED3DLIGHT_INVALID
) {
2174 /* This should create a default light. */
2176 memset(&light
, 0, sizeof(light
));
2177 light
.Type
= D3DLIGHT_DIRECTIONAL
;
2178 light
.Diffuse
.r
= 1.0f
;
2179 light
.Diffuse
.g
= 1.0f
;
2180 light
.Diffuse
.b
= 1.0f
;
2181 light
.Direction
.z
= 1.0f
;
2182 NineDevice9_SetLight(This
, Index
, &light
);
2185 nine_state_light_enable(&state
->ff
, &state
->changed
.group
, Index
, Enable
);
2186 if (likely(!This
->is_recording
))
2187 nine_context_light_enable(This
, Index
, Enable
);
2193 NineDevice9_GetLightEnable( struct NineDevice9
*This
,
2197 const struct nine_state
*state
= &This
->state
;
2200 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2201 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2202 D3DERR_INVALIDCALL
);
2204 for (i
= 0; i
< state
->ff
.num_lights_active
; ++i
)
2205 if (state
->ff
.active_light
[i
] == Index
)
2208 *pEnable
= i
!= state
->ff
.num_lights_active
? 128 : 0; // Taken from wine
2214 NineDevice9_SetClipPlane( struct NineDevice9
*This
,
2216 const float *pPlane
)
2218 struct nine_state
*state
= This
->update
;
2220 user_assert(pPlane
, D3DERR_INVALIDCALL
);
2222 DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This
, Index
,
2223 pPlane
[0], pPlane
[1],
2224 pPlane
[2], pPlane
[3]);
2226 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2228 memcpy(&state
->clip
.ucp
[Index
][0], pPlane
, sizeof(state
->clip
.ucp
[0]));
2229 if (unlikely(This
->is_recording
))
2230 state
->changed
.ucp
|= 1 << Index
;
2232 nine_context_set_clip_plane(This
, Index
, (struct nine_clipplane
*)pPlane
);
2238 NineDevice9_GetClipPlane( struct NineDevice9
*This
,
2242 const struct nine_state
*state
= &This
->state
;
2244 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2246 memcpy(pPlane
, &state
->clip
.ucp
[Index
][0], sizeof(state
->clip
.ucp
[0]));
2251 NineDevice9_SetRenderState( struct NineDevice9
*This
,
2252 D3DRENDERSTATETYPE State
,
2255 struct nine_state
*state
= This
->update
;
2257 DBG("This=%p State=%u(%s) Value=%08x\n", This
,
2258 State
, nine_d3drs_to_string(State
), Value
);
2260 user_assert(State
< D3DRS_COUNT
, D3DERR_INVALIDCALL
);
2262 if (unlikely(This
->is_recording
)) {
2263 state
->rs_advertised
[State
] = Value
;
2264 /* only need to record changed render states for stateblocks */
2265 state
->changed
.rs
[State
/ 32] |= 1 << (State
% 32);
2266 state
->changed
.group
|= nine_render_state_group
[State
];
2270 if (state
->rs_advertised
[State
] == Value
)
2273 state
->rs_advertised
[State
] = Value
;
2274 nine_context_set_render_state(This
, State
, Value
);
2280 NineDevice9_GetRenderState( struct NineDevice9
*This
,
2281 D3DRENDERSTATETYPE State
,
2284 user_assert(State
< D3DRS_COUNT
, D3DERR_INVALIDCALL
);
2286 *pValue
= This
->state
.rs_advertised
[State
];
2291 NineDevice9_CreateStateBlock( struct NineDevice9
*This
,
2292 D3DSTATEBLOCKTYPE Type
,
2293 IDirect3DStateBlock9
**ppSB
)
2295 struct NineStateBlock9
*nsb
;
2296 struct nine_state
*dst
;
2298 enum nine_stateblock_type type
;
2301 DBG("This=%p Type=%u ppSB=%p\n", This
, Type
, ppSB
);
2303 user_assert(Type
== D3DSBT_ALL
||
2304 Type
== D3DSBT_VERTEXSTATE
||
2305 Type
== D3DSBT_PIXELSTATE
, D3DERR_INVALIDCALL
);
2308 case D3DSBT_VERTEXSTATE
: type
= NINESBT_VERTEXSTATE
; break;
2309 case D3DSBT_PIXELSTATE
: type
= NINESBT_PIXELSTATE
; break;
2315 hr
= NineStateBlock9_new(This
, &nsb
, type
);
2318 *ppSB
= (IDirect3DStateBlock9
*)nsb
;
2321 dst
->changed
.group
=
2322 NINE_STATE_TEXTURE
|
2325 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_VERTEXSTATE
) {
2326 dst
->changed
.group
|=
2327 NINE_STATE_FF_LIGHTING
|
2328 NINE_STATE_VS
| NINE_STATE_VS_CONST
|
2330 /* TODO: texture/sampler state */
2331 memcpy(dst
->changed
.rs
,
2332 nine_render_states_vertex
, sizeof(dst
->changed
.rs
));
2333 nine_ranges_insert(&dst
->changed
.vs_const_f
, 0, This
->may_swvp
? NINE_MAX_CONST_F_SWVP
: This
->max_vs_const_f
,
2335 nine_ranges_insert(&dst
->changed
.vs_const_i
, 0, This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
,
2337 nine_ranges_insert(&dst
->changed
.vs_const_b
, 0, This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
,
2339 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2340 dst
->changed
.sampler
[s
] |= 1 << D3DSAMP_DMAPOFFSET
;
2341 if (This
->state
.ff
.num_lights
) {
2342 dst
->ff
.num_lights
= This
->state
.ff
.num_lights
;
2343 /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
2344 * all currently existing lights will be captured
2346 dst
->ff
.light
= CALLOC(This
->state
.ff
.num_lights
,
2348 if (!dst
->ff
.light
) {
2349 nine_bind(ppSB
, NULL
);
2350 return E_OUTOFMEMORY
;
2354 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_PIXELSTATE
) {
2355 dst
->changed
.group
|=
2356 NINE_STATE_PS
| NINE_STATE_PS_CONST
| NINE_STATE_BLEND
|
2357 NINE_STATE_FF_OTHER
| NINE_STATE_FF_PSSTAGES
| NINE_STATE_PS_CONST
|
2358 NINE_STATE_FB
| NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
|
2359 NINE_STATE_RASTERIZER
| NINE_STATE_STENCIL_REF
;
2360 memcpy(dst
->changed
.rs
,
2361 nine_render_states_pixel
, sizeof(dst
->changed
.rs
));
2362 nine_ranges_insert(&dst
->changed
.ps_const_f
, 0, This
->max_ps_const_f
,
2364 dst
->changed
.ps_const_i
= 0xffff;
2365 dst
->changed
.ps_const_b
= 0xffff;
2366 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2367 dst
->changed
.sampler
[s
] |= 0x1ffe;
2368 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
2369 dst
->ff
.changed
.tex_stage
[s
][0] |= 0xffffffff;
2370 dst
->ff
.changed
.tex_stage
[s
][1] |= 0xffffffff;
2373 if (Type
== D3DSBT_ALL
) {
2374 dst
->changed
.group
|=
2375 NINE_STATE_VIEWPORT
|
2376 NINE_STATE_SCISSOR
|
2377 NINE_STATE_RASTERIZER
|
2381 NINE_STATE_MATERIAL
|
2382 NINE_STATE_BLEND_COLOR
|
2383 NINE_STATE_SAMPLE_MASK
;
2384 memset(dst
->changed
.rs
, ~0, (D3DRS_COUNT
/ 32) * sizeof(uint32_t));
2385 dst
->changed
.rs
[D3DRS_LAST
/ 32] |= (1 << (D3DRS_COUNT
% 32)) - 1;
2386 dst
->changed
.vtxbuf
= (1ULL << This
->caps
.MaxStreams
) - 1;
2387 dst
->changed
.stream_freq
= dst
->changed
.vtxbuf
;
2388 dst
->changed
.ucp
= (1 << PIPE_MAX_CLIP_PLANES
) - 1;
2389 dst
->changed
.texture
= (1 << NINE_MAX_SAMPLERS
) - 1;
2391 NineStateBlock9_Capture(NineStateBlock9(*ppSB
));
2393 /* TODO: fixed function state */
2399 NineDevice9_BeginStateBlock( struct NineDevice9
*This
)
2403 DBG("This=%p\n", This
);
2405 user_assert(!This
->record
, D3DERR_INVALIDCALL
);
2407 hr
= NineStateBlock9_new(This
, &This
->record
, NINESBT_CUSTOM
);
2410 NineUnknown_ConvertRefToBind(NineUnknown(This
->record
));
2412 This
->update
= &This
->record
->state
;
2413 This
->is_recording
= TRUE
;
2419 NineDevice9_EndStateBlock( struct NineDevice9
*This
,
2420 IDirect3DStateBlock9
**ppSB
)
2422 DBG("This=%p ppSB=%p\n", This
, ppSB
);
2424 user_assert(This
->record
, D3DERR_INVALIDCALL
);
2426 This
->update
= &This
->state
;
2427 This
->is_recording
= FALSE
;
2429 NineUnknown_AddRef(NineUnknown(This
->record
));
2430 *ppSB
= (IDirect3DStateBlock9
*)This
->record
;
2431 NineUnknown_Unbind(NineUnknown(This
->record
));
2432 This
->record
= NULL
;
2438 NineDevice9_SetClipStatus( struct NineDevice9
*This
,
2439 const D3DCLIPSTATUS9
*pClipStatus
)
2441 STUB(D3DERR_INVALIDCALL
);
2445 NineDevice9_GetClipStatus( struct NineDevice9
*This
,
2446 D3DCLIPSTATUS9
*pClipStatus
)
2448 STUB(D3DERR_INVALIDCALL
);
2452 NineDevice9_GetTexture( struct NineDevice9
*This
,
2454 IDirect3DBaseTexture9
**ppTexture
)
2456 user_assert(Stage
< This
->caps
.MaxSimultaneousTextures
||
2457 Stage
== D3DDMAPSAMPLER
||
2458 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2459 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2460 user_assert(ppTexture
, D3DERR_INVALIDCALL
);
2462 if (Stage
>= D3DDMAPSAMPLER
)
2463 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2465 *ppTexture
= (IDirect3DBaseTexture9
*)This
->state
.texture
[Stage
];
2467 if (This
->state
.texture
[Stage
])
2468 NineUnknown_AddRef(NineUnknown(This
->state
.texture
[Stage
]));
2473 NineDevice9_SetTexture( struct NineDevice9
*This
,
2475 IDirect3DBaseTexture9
*pTexture
)
2477 struct nine_state
*state
= This
->update
;
2478 struct NineBaseTexture9
*tex
= NineBaseTexture9(pTexture
);
2479 struct NineBaseTexture9
*old
;
2481 DBG("This=%p Stage=%u pTexture=%p\n", This
, Stage
, pTexture
);
2483 user_assert(Stage
< This
->caps
.MaxSimultaneousTextures
||
2484 Stage
== D3DDMAPSAMPLER
||
2485 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2486 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2487 user_assert(!tex
|| (tex
->base
.pool
!= D3DPOOL_SCRATCH
&&
2488 tex
->base
.pool
!= D3DPOOL_SYSTEMMEM
), D3DERR_INVALIDCALL
);
2490 if (Stage
>= D3DDMAPSAMPLER
)
2491 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2493 if (This
->is_recording
) {
2494 state
->changed
.texture
|= 1 << Stage
;
2495 state
->changed
.group
|= NINE_STATE_TEXTURE
;
2496 nine_bind(&state
->texture
[Stage
], pTexture
);
2500 old
= state
->texture
[Stage
];
2504 NineBindTextureToDevice(This
, &state
->texture
[Stage
], tex
);
2506 nine_context_set_texture(This
, Stage
, tex
);
2512 NineDevice9_GetTextureStageState( struct NineDevice9
*This
,
2514 D3DTEXTURESTAGESTATETYPE Type
,
2517 const struct nine_state
*state
= &This
->state
;
2519 user_assert(Stage
< ARRAY_SIZE(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2520 user_assert(Type
< ARRAY_SIZE(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2522 *pValue
= state
->ff
.tex_stage
[Stage
][Type
];
2528 NineDevice9_SetTextureStageState( struct NineDevice9
*This
,
2530 D3DTEXTURESTAGESTATETYPE Type
,
2533 struct nine_state
*state
= This
->update
;
2535 DBG("Stage=%u Type=%u Value=%08x\n", Stage
, Type
, Value
);
2536 nine_dump_D3DTSS_value(DBG_FF
, Type
, Value
);
2538 user_assert(Stage
< ARRAY_SIZE(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2539 user_assert(Type
< ARRAY_SIZE(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2541 state
->ff
.tex_stage
[Stage
][Type
] = Value
;
2543 if (unlikely(This
->is_recording
)) {
2544 if (Type
== D3DTSS_TEXTURETRANSFORMFLAGS
)
2545 state
->changed
.group
|= NINE_STATE_PS1X_SHADER
;
2546 state
->changed
.group
|= NINE_STATE_FF_PSSTAGES
;
2547 state
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
2549 nine_context_set_texture_stage_state(This
, Stage
, Type
, Value
);
2555 NineDevice9_GetSamplerState( struct NineDevice9
*This
,
2557 D3DSAMPLERSTATETYPE Type
,
2560 user_assert(Sampler
< This
->caps
.MaxSimultaneousTextures
||
2561 Sampler
== D3DDMAPSAMPLER
||
2562 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2563 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2565 if (Sampler
>= D3DDMAPSAMPLER
)
2566 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2568 *pValue
= This
->state
.samp_advertised
[Sampler
][Type
];
2573 NineDevice9_SetSamplerState( struct NineDevice9
*This
,
2575 D3DSAMPLERSTATETYPE Type
,
2578 struct nine_state
*state
= This
->update
;
2580 DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This
,
2581 Sampler
, nine_D3DSAMP_to_str(Type
), Value
);
2583 user_assert(Sampler
< This
->caps
.MaxSimultaneousTextures
||
2584 Sampler
== D3DDMAPSAMPLER
||
2585 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2586 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2588 if (Sampler
>= D3DDMAPSAMPLER
)
2589 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2591 if (unlikely(This
->is_recording
)) {
2592 state
->samp_advertised
[Sampler
][Type
] = Value
;
2593 state
->changed
.group
|= NINE_STATE_SAMPLER
;
2594 state
->changed
.sampler
[Sampler
] |= 1 << Type
;
2598 if (state
->samp_advertised
[Sampler
][Type
] == Value
)
2601 state
->samp_advertised
[Sampler
][Type
] = Value
;
2602 nine_context_set_sampler_state(This
, Sampler
, Type
, Value
);
2608 NineDevice9_ValidateDevice( struct NineDevice9
*This
,
2611 const struct nine_state
*state
= &This
->state
;
2613 unsigned w
= 0, h
= 0;
2615 DBG("This=%p pNumPasses=%p\n", This
, pNumPasses
);
2617 for (i
= 0; i
< ARRAY_SIZE(state
->samp_advertised
); ++i
) {
2618 if (state
->samp_advertised
[i
][D3DSAMP_MINFILTER
] == D3DTEXF_NONE
||
2619 state
->samp_advertised
[i
][D3DSAMP_MAGFILTER
] == D3DTEXF_NONE
)
2620 return D3DERR_UNSUPPORTEDTEXTUREFILTER
;
2623 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2627 w
= state
->rt
[i
]->desc
.Width
;
2628 h
= state
->rt
[i
]->desc
.Height
;
2630 if (state
->rt
[i
]->desc
.Width
!= w
|| state
->rt
[i
]->desc
.Height
!= h
) {
2631 return D3DERR_CONFLICTINGRENDERSTATE
;
2635 (state
->rs_advertised
[D3DRS_ZENABLE
] || state
->rs_advertised
[D3DRS_STENCILENABLE
])) {
2637 (state
->ds
->desc
.Width
!= w
|| state
->ds
->desc
.Height
!= h
))
2638 return D3DERR_CONFLICTINGRENDERSTATE
;
2648 NineDevice9_SetPaletteEntries( struct NineDevice9
*This
,
2650 const PALETTEENTRY
*pEntries
)
2652 STUB(D3D_OK
); /* like wine */
2656 NineDevice9_GetPaletteEntries( struct NineDevice9
*This
,
2658 PALETTEENTRY
*pEntries
)
2660 STUB(D3DERR_INVALIDCALL
);
2664 NineDevice9_SetCurrentTexturePalette( struct NineDevice9
*This
,
2665 UINT PaletteNumber
)
2667 STUB(D3D_OK
); /* like wine */
2671 NineDevice9_GetCurrentTexturePalette( struct NineDevice9
*This
,
2672 UINT
*PaletteNumber
)
2674 STUB(D3DERR_INVALIDCALL
);
2678 NineDevice9_SetScissorRect( struct NineDevice9
*This
,
2681 struct nine_state
*state
= This
->update
;
2683 DBG("x=(%u..%u) y=(%u..%u)\n",
2684 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
2686 state
->scissor
.minx
= pRect
->left
;
2687 state
->scissor
.miny
= pRect
->top
;
2688 state
->scissor
.maxx
= pRect
->right
;
2689 state
->scissor
.maxy
= pRect
->bottom
;
2691 if (unlikely(This
->is_recording
))
2692 state
->changed
.group
|= NINE_STATE_SCISSOR
;
2694 nine_context_set_scissor(This
, &state
->scissor
);
2700 NineDevice9_GetScissorRect( struct NineDevice9
*This
,
2703 pRect
->left
= This
->state
.scissor
.minx
;
2704 pRect
->top
= This
->state
.scissor
.miny
;
2705 pRect
->right
= This
->state
.scissor
.maxx
;
2706 pRect
->bottom
= This
->state
.scissor
.maxy
;
2712 NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9
*This
,
2715 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
) {
2716 This
->swvp
= bSoftware
;
2717 nine_context_set_swvp(This
, bSoftware
);
2720 return D3DERR_INVALIDCALL
; /* msdn. TODO: check in practice */
2724 NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9
*This
)
2730 NineDevice9_SetNPatchMode( struct NineDevice9
*This
,
2733 return D3D_OK
; /* Nothing to do because we don't advertise NPatch support */
2737 NineDevice9_GetNPatchMode( struct NineDevice9
*This
)
2742 /* TODO: only go through dirty textures */
2744 validate_textures(struct NineDevice9
*device
)
2746 struct NineBaseTexture9
*tex
, *ptr
;
2747 LIST_FOR_EACH_ENTRY_SAFE(tex
, ptr
, &device
->update_textures
, list
) {
2748 list_delinit(&tex
->list
);
2749 NineBaseTexture9_Validate(tex
);
2754 update_managed_buffers(struct NineDevice9
*device
)
2756 struct NineBuffer9
*buf
, *ptr
;
2757 LIST_FOR_EACH_ENTRY_SAFE(buf
, ptr
, &device
->update_buffers
, managed
.list
) {
2758 list_delinit(&buf
->managed
.list
);
2759 NineBuffer9_Upload(buf
);
2764 NineBeforeDraw( struct NineDevice9
*This
)
2766 /* Upload Managed dirty content */
2767 validate_textures(This
); /* may clobber state */
2768 update_managed_buffers(This
);
2772 NineAfterDraw( struct NineDevice9
*This
)
2775 struct nine_state
*state
= &This
->state
;
2776 unsigned ps_mask
= state
->ps
? state
->ps
->rt_mask
: 1;
2778 /* Flag render-targets with autogenmipmap for mipmap regeneration */
2779 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2780 struct NineSurface9
*rt
= state
->rt
[i
];
2782 if (rt
&& rt
->desc
.Format
!= D3DFMT_NULL
&& (ps_mask
& (1 << i
)) &&
2783 rt
->desc
.Usage
& D3DUSAGE_AUTOGENMIPMAP
) {
2784 assert(rt
->texture
== D3DRTYPE_TEXTURE
||
2785 rt
->texture
== D3DRTYPE_CUBETEXTURE
);
2786 NineBaseTexture9(rt
->base
.base
.container
)->dirty_mip
= TRUE
;
2792 NineDevice9_DrawPrimitive( struct NineDevice9
*This
,
2793 D3DPRIMITIVETYPE PrimitiveType
,
2795 UINT PrimitiveCount
)
2797 DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
2798 This
, PrimitiveType
, StartVertex
, PrimitiveCount
);
2800 NineBeforeDraw(This
);
2801 nine_context_draw_primitive(This
, PrimitiveType
, StartVertex
, PrimitiveCount
);
2802 NineAfterDraw(This
);
2808 NineDevice9_DrawIndexedPrimitive( struct NineDevice9
*This
,
2809 D3DPRIMITIVETYPE PrimitiveType
,
2810 INT BaseVertexIndex
,
2811 UINT MinVertexIndex
,
2814 UINT PrimitiveCount
)
2816 DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
2817 "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
2818 This
, PrimitiveType
, BaseVertexIndex
, MinVertexIndex
, NumVertices
,
2819 StartIndex
, PrimitiveCount
);
2821 user_assert(This
->state
.idxbuf
, D3DERR_INVALIDCALL
);
2822 user_assert(This
->state
.vdecl
, D3DERR_INVALIDCALL
);
2824 NineBeforeDraw(This
);
2825 nine_context_draw_indexed_primitive(This
, PrimitiveType
, BaseVertexIndex
,
2826 MinVertexIndex
, NumVertices
, StartIndex
,
2828 NineAfterDraw(This
);
2834 NineDevice9_DrawPrimitiveUP( struct NineDevice9
*This
,
2835 D3DPRIMITIVETYPE PrimitiveType
,
2836 UINT PrimitiveCount
,
2837 const void *pVertexStreamZeroData
,
2838 UINT VertexStreamZeroStride
)
2840 struct pipe_vertex_buffer vtxbuf
;
2842 DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
2843 This
, PrimitiveType
, PrimitiveCount
,
2844 pVertexStreamZeroData
, VertexStreamZeroStride
);
2846 user_assert(pVertexStreamZeroData
&& VertexStreamZeroStride
,
2847 D3DERR_INVALIDCALL
);
2848 user_assert(PrimitiveCount
, D3D_OK
);
2850 vtxbuf
.stride
= VertexStreamZeroStride
;
2851 vtxbuf
.buffer_offset
= 0;
2852 vtxbuf
.buffer
= NULL
;
2853 vtxbuf
.user_buffer
= pVertexStreamZeroData
;
2855 if (!This
->driver_caps
.user_vbufs
) {
2856 u_upload_data(This
->vertex_uploader
,
2858 (prim_count_to_vertex_count(PrimitiveType
, PrimitiveCount
)) * VertexStreamZeroStride
, /* XXX */
2861 &vtxbuf
.buffer_offset
,
2863 u_upload_unmap(This
->vertex_uploader
);
2864 vtxbuf
.user_buffer
= NULL
;
2867 NineBeforeDraw(This
);
2868 nine_context_draw_primitive_from_vtxbuf(This
, PrimitiveType
, PrimitiveCount
, &vtxbuf
);
2869 NineAfterDraw(This
);
2871 pipe_resource_reference(&vtxbuf
.buffer
, NULL
);
2873 NineDevice9_PauseRecording(This
);
2874 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
2875 NineDevice9_ResumeRecording(This
);
2881 NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9
*This
,
2882 D3DPRIMITIVETYPE PrimitiveType
,
2883 UINT MinVertexIndex
,
2885 UINT PrimitiveCount
,
2886 const void *pIndexData
,
2887 D3DFORMAT IndexDataFormat
,
2888 const void *pVertexStreamZeroData
,
2889 UINT VertexStreamZeroStride
)
2891 struct pipe_vertex_buffer vbuf
;
2892 struct pipe_index_buffer ibuf
;
2894 DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
2895 "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
2896 "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
2897 This
, PrimitiveType
, MinVertexIndex
, NumVertices
, PrimitiveCount
,
2898 pIndexData
, IndexDataFormat
,
2899 pVertexStreamZeroData
, VertexStreamZeroStride
);
2901 user_assert(pIndexData
&& pVertexStreamZeroData
, D3DERR_INVALIDCALL
);
2902 user_assert(VertexStreamZeroStride
, D3DERR_INVALIDCALL
);
2903 user_assert(IndexDataFormat
== D3DFMT_INDEX16
||
2904 IndexDataFormat
== D3DFMT_INDEX32
, D3DERR_INVALIDCALL
);
2905 user_assert(PrimitiveCount
, D3D_OK
);
2907 vbuf
.stride
= VertexStreamZeroStride
;
2908 vbuf
.buffer_offset
= 0;
2910 vbuf
.user_buffer
= pVertexStreamZeroData
;
2912 ibuf
.index_size
= (IndexDataFormat
== D3DFMT_INDEX16
) ? 2 : 4;
2915 ibuf
.user_buffer
= pIndexData
;
2917 if (!This
->driver_caps
.user_vbufs
) {
2918 const unsigned base
= MinVertexIndex
* VertexStreamZeroStride
;
2919 u_upload_data(This
->vertex_uploader
,
2921 NumVertices
* VertexStreamZeroStride
, /* XXX */
2923 (const uint8_t *)vbuf
.user_buffer
+ base
,
2924 &vbuf
.buffer_offset
,
2926 u_upload_unmap(This
->vertex_uploader
);
2927 /* Won't be used: */
2928 vbuf
.buffer_offset
-= base
;
2929 vbuf
.user_buffer
= NULL
;
2931 if (!This
->driver_caps
.user_ibufs
) {
2932 u_upload_data(This
->index_uploader
,
2934 (prim_count_to_vertex_count(PrimitiveType
, PrimitiveCount
)) * ibuf
.index_size
,
2939 u_upload_unmap(This
->index_uploader
);
2940 ibuf
.user_buffer
= NULL
;
2943 NineBeforeDraw(This
);
2944 nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This
, PrimitiveType
,
2950 NineAfterDraw(This
);
2952 pipe_resource_reference(&vbuf
.buffer
, NULL
);
2953 pipe_resource_reference(&ibuf
.buffer
, NULL
);
2955 NineDevice9_PauseRecording(This
);
2956 NineDevice9_SetIndices(This
, NULL
);
2957 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
2958 NineDevice9_ResumeRecording(This
);
2964 NineDevice9_ProcessVertices( struct NineDevice9
*This
,
2968 IDirect3DVertexBuffer9
*pDestBuffer
,
2969 IDirect3DVertexDeclaration9
*pVertexDecl
,
2972 struct pipe_screen
*screen_sw
= This
->screen_sw
;
2973 struct pipe_context
*pipe_sw
= This
->pipe_sw
;
2974 struct NineVertexDeclaration9
*vdecl
= NineVertexDeclaration9(pVertexDecl
);
2975 struct NineVertexBuffer9
*dst
= NineVertexBuffer9(pDestBuffer
);
2976 struct NineVertexShader9
*vs
;
2977 struct pipe_resource
*resource
;
2978 struct pipe_transfer
*transfer
= NULL
;
2979 struct pipe_stream_output_info so
;
2980 struct pipe_stream_output_target
*target
;
2981 struct pipe_draw_info draw
;
2982 struct pipe_box box
;
2983 bool programmable_vs
= This
->state
.vs
&& !(This
->state
.vdecl
&& This
->state
.vdecl
->position_t
);
2984 unsigned offsets
[1] = {0};
2986 unsigned buffer_size
;
2989 DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
2990 "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
2991 This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
,
2992 pVertexDecl
, Flags
);
2994 if (!screen_sw
->get_param(screen_sw
, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS
)) {
2995 DBG("ProcessVertices not supported\n");
2996 return D3DERR_INVALIDCALL
;
3000 vs
= programmable_vs
? This
->state
.vs
: This
->ff
.vs
;
3001 /* Note: version is 0 for ff */
3002 user_assert(vdecl
|| (vs
->byte_code
.version
< 0x30 && dst
->desc
.FVF
),
3003 D3DERR_INVALIDCALL
);
3005 DWORD FVF
= dst
->desc
.FVF
;
3006 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3008 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3012 util_hash_table_set(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3013 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3017 /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags
3018 * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular
3019 * if not set, everything from src will be used, and dst
3020 * must match exactly the ff vs outputs.
3021 * TODO: Handle all the checks, etc for ff */
3022 user_assert(vdecl
->position_t
|| programmable_vs
,
3023 D3DERR_INVALIDCALL
);
3025 /* TODO: Support vs < 3 and ff */
3026 user_assert(vs
->byte_code
.version
== 0x30,
3027 D3DERR_INVALIDCALL
);
3028 /* TODO: Not hardcode the constant buffers for swvp */
3029 user_assert(This
->may_swvp
,
3030 D3DERR_INVALIDCALL
);
3032 nine_state_prepare_draw_sw(This
, vdecl
, SrcStartIndex
, VertexCount
, &so
);
3034 buffer_size
= VertexCount
* so
.stride
[0] * 4;
3036 struct pipe_resource templ
;
3038 memset(&templ
, 0, sizeof(templ
));
3039 templ
.target
= PIPE_BUFFER
;
3040 templ
.format
= PIPE_FORMAT_R8_UNORM
;
3041 templ
.width0
= buffer_size
;
3043 templ
.bind
= PIPE_BIND_STREAM_OUTPUT
;
3044 templ
.usage
= PIPE_USAGE_STREAM
;
3045 templ
.height0
= templ
.depth0
= templ
.array_size
= 1;
3046 templ
.last_level
= templ
.nr_samples
= 0;
3048 resource
= screen_sw
->resource_create(screen_sw
, &templ
);
3050 return E_OUTOFMEMORY
;
3052 target
= pipe_sw
->create_stream_output_target(pipe_sw
, resource
,
3055 pipe_resource_reference(&resource
, NULL
);
3056 return D3DERR_DRIVERINTERNALERROR
;
3059 draw
.mode
= PIPE_PRIM_POINTS
;
3060 draw
.count
= VertexCount
;
3061 draw
.start_instance
= 0;
3062 draw
.primitive_restart
= FALSE
;
3063 draw
.restart_index
= 0;
3064 draw
.count_from_stream_output
= NULL
;
3065 draw
.indirect
= NULL
;
3066 draw
.indirect_params
= NULL
;
3067 draw
.instance_count
= 1;
3068 draw
.indexed
= FALSE
;
3070 draw
.index_bias
= 0;
3072 draw
.max_index
= VertexCount
- 1;
3075 pipe_sw
->set_stream_output_targets(pipe_sw
, 1, &target
, offsets
);
3077 pipe_sw
->draw_vbo(pipe_sw
, &draw
);
3079 pipe_sw
->set_stream_output_targets(pipe_sw
, 0, NULL
, 0);
3080 pipe_sw
->stream_output_target_destroy(pipe_sw
, target
);
3082 u_box_1d(0, VertexCount
* so
.stride
[0] * 4, &box
);
3083 map
= pipe_sw
->transfer_map(pipe_sw
, resource
, 0, PIPE_TRANSFER_READ
, &box
,
3086 hr
= D3DERR_DRIVERINTERNALERROR
;
3090 hr
= NineVertexDeclaration9_ConvertStreamOutput(vdecl
,
3091 dst
, DestIndex
, VertexCount
,
3094 pipe_sw
->transfer_unmap(pipe_sw
, transfer
);
3097 nine_state_after_draw_sw(This
);
3098 pipe_resource_reference(&resource
, NULL
);
3103 NineDevice9_CreateVertexDeclaration( struct NineDevice9
*This
,
3104 const D3DVERTEXELEMENT9
*pVertexElements
,
3105 IDirect3DVertexDeclaration9
**ppDecl
)
3107 struct NineVertexDeclaration9
*vdecl
;
3109 DBG("This=%p pVertexElements=%p ppDecl=%p\n",
3110 This
, pVertexElements
, ppDecl
);
3112 HRESULT hr
= NineVertexDeclaration9_new(This
, pVertexElements
, &vdecl
);
3114 *ppDecl
= (IDirect3DVertexDeclaration9
*)vdecl
;
3120 NineDevice9_SetVertexDeclaration( struct NineDevice9
*This
,
3121 IDirect3DVertexDeclaration9
*pDecl
)
3123 struct nine_state
*state
= This
->update
;
3124 struct NineVertexDeclaration9
*vdecl
= NineVertexDeclaration9(pDecl
);
3126 DBG("This=%p pDecl=%p\n", This
, pDecl
);
3128 if (unlikely(This
->is_recording
)) {
3129 nine_bind(&state
->vdecl
, vdecl
);
3130 state
->changed
.group
|= NINE_STATE_VDECL
;
3134 if (state
->vdecl
== vdecl
)
3137 nine_bind(&state
->vdecl
, vdecl
);
3139 nine_context_set_vertex_declaration(This
, vdecl
);
3145 NineDevice9_GetVertexDeclaration( struct NineDevice9
*This
,
3146 IDirect3DVertexDeclaration9
**ppDecl
)
3148 user_assert(ppDecl
, D3DERR_INVALIDCALL
);
3150 *ppDecl
= (IDirect3DVertexDeclaration9
*)This
->state
.vdecl
;
3152 NineUnknown_AddRef(NineUnknown(*ppDecl
));
3157 NineDevice9_SetFVF( struct NineDevice9
*This
,
3160 struct NineVertexDeclaration9
*vdecl
;
3163 DBG("FVF = %08x\n", FVF
);
3165 return D3D_OK
; /* like wine */
3167 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3169 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3173 util_hash_table_set(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3174 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3176 return NineDevice9_SetVertexDeclaration(
3177 This
, (IDirect3DVertexDeclaration9
*)vdecl
);
3181 NineDevice9_GetFVF( struct NineDevice9
*This
,
3184 *pFVF
= This
->state
.vdecl
? This
->state
.vdecl
->fvf
: 0;
3189 NineDevice9_CreateVertexShader( struct NineDevice9
*This
,
3190 const DWORD
*pFunction
,
3191 IDirect3DVertexShader9
**ppShader
)
3193 struct NineVertexShader9
*vs
;
3196 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3198 hr
= NineVertexShader9_new(This
, &vs
, pFunction
, NULL
);
3201 *ppShader
= (IDirect3DVertexShader9
*)vs
;
3206 NineDevice9_SetVertexShader( struct NineDevice9
*This
,
3207 IDirect3DVertexShader9
*pShader
)
3209 struct nine_state
*state
= This
->update
;
3210 struct NineVertexShader9
*vs_shader
= (struct NineVertexShader9
*)pShader
;
3212 DBG("This=%p pShader=%p\n", This
, pShader
);
3214 if (unlikely(This
->is_recording
)) {
3215 nine_bind(&state
->vs
, vs_shader
);
3216 state
->changed
.group
|= NINE_STATE_VS
;
3220 if (state
->vs
== vs_shader
)
3223 nine_bind(&state
->vs
, vs_shader
);
3225 nine_context_set_vertex_shader(This
, vs_shader
);
3231 NineDevice9_GetVertexShader( struct NineDevice9
*This
,
3232 IDirect3DVertexShader9
**ppShader
)
3234 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3235 nine_reference_set(ppShader
, This
->state
.vs
);
3240 NineDevice9_SetVertexShaderConstantF( struct NineDevice9
*This
,
3242 const float *pConstantData
,
3243 UINT Vector4fCount
)
3245 struct nine_state
*state
= This
->update
;
3246 float *vs_const_f
= state
->vs_const_f
;
3248 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3249 This
, StartRegister
, pConstantData
, Vector4fCount
);
3251 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3252 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3256 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3258 if (unlikely(This
->is_recording
)) {
3259 memcpy(&vs_const_f
[StartRegister
* 4],
3261 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3263 nine_ranges_insert(&state
->changed
.vs_const_f
,
3264 StartRegister
, StartRegister
+ Vector4fCount
,
3267 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3272 if (!memcmp(&vs_const_f
[StartRegister
* 4], pConstantData
,
3273 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0])))
3276 memcpy(&vs_const_f
[StartRegister
* 4],
3278 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3280 nine_context_set_vertex_shader_constant_f(This
, StartRegister
, pConstantData
,
3281 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]),
3288 NineDevice9_GetVertexShaderConstantF( struct NineDevice9
*This
,
3290 float *pConstantData
,
3291 UINT Vector4fCount
)
3293 const struct nine_state
*state
= &This
->state
;
3295 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3296 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3297 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3299 memcpy(pConstantData
,
3300 &state
->vs_const_f
[StartRegister
* 4],
3301 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3307 NineDevice9_SetVertexShaderConstantI( struct NineDevice9
*This
,
3309 const int *pConstantData
,
3310 UINT Vector4iCount
)
3312 struct nine_state
*state
= This
->update
;
3315 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3316 This
, StartRegister
, pConstantData
, Vector4iCount
);
3318 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3319 D3DERR_INVALIDCALL
);
3320 user_assert(StartRegister
+ Vector4iCount
<= (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3321 D3DERR_INVALIDCALL
);
3322 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3324 if (This
->driver_caps
.vs_integer
) {
3325 if (!This
->is_recording
) {
3326 if (!memcmp(&state
->vs_const_i
[4 * StartRegister
], pConstantData
,
3327 Vector4iCount
* sizeof(int[4])))
3330 memcpy(&state
->vs_const_i
[4 * StartRegister
],
3332 Vector4iCount
* sizeof(int[4]));
3334 for (i
= 0; i
< Vector4iCount
; i
++) {
3335 state
->vs_const_i
[4 * (StartRegister
+ i
)] = fui((float)(pConstantData
[4 * i
]));
3336 state
->vs_const_i
[4 * (StartRegister
+ i
) + 1] = fui((float)(pConstantData
[4 * i
+ 1]));
3337 state
->vs_const_i
[4 * (StartRegister
+ i
) + 2] = fui((float)(pConstantData
[4 * i
+ 2]));
3338 state
->vs_const_i
[4 * (StartRegister
+ i
) + 3] = fui((float)(pConstantData
[4 * i
+ 3]));
3342 if (unlikely(This
->is_recording
)) {
3343 nine_ranges_insert(&state
->changed
.vs_const_i
,
3344 StartRegister
, StartRegister
+ Vector4iCount
,
3346 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3348 nine_context_set_vertex_shader_constant_i(This
, StartRegister
, pConstantData
,
3349 Vector4iCount
* sizeof(int[4]), Vector4iCount
);
3355 NineDevice9_GetVertexShaderConstantI( struct NineDevice9
*This
,
3358 UINT Vector4iCount
)
3360 const struct nine_state
*state
= &This
->state
;
3363 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3364 D3DERR_INVALIDCALL
);
3365 user_assert(StartRegister
+ Vector4iCount
<= (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3366 D3DERR_INVALIDCALL
);
3367 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3369 if (This
->driver_caps
.vs_integer
) {
3370 memcpy(pConstantData
,
3371 &state
->vs_const_i
[4 * StartRegister
],
3372 Vector4iCount
* sizeof(int[4]));
3374 for (i
= 0; i
< Vector4iCount
; i
++) {
3375 pConstantData
[4 * i
] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
)]);
3376 pConstantData
[4 * i
+ 1] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 1]);
3377 pConstantData
[4 * i
+ 2] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 2]);
3378 pConstantData
[4 * i
+ 3] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 3]);
3386 NineDevice9_SetVertexShaderConstantB( struct NineDevice9
*This
,
3388 const BOOL
*pConstantData
,
3391 struct nine_state
*state
= This
->update
;
3393 uint32_t bool_true
= This
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
3395 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3396 This
, StartRegister
, pConstantData
, BoolCount
);
3398 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3399 D3DERR_INVALIDCALL
);
3400 user_assert(StartRegister
+ BoolCount
<= (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3401 D3DERR_INVALIDCALL
);
3402 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3404 if (!This
->is_recording
) {
3405 bool noChange
= true;
3406 for (i
= 0; i
< BoolCount
; i
++) {
3407 if (!!state
->vs_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3414 for (i
= 0; i
< BoolCount
; i
++)
3415 state
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3417 if (unlikely(This
->is_recording
)) {
3418 nine_ranges_insert(&state
->changed
.vs_const_b
,
3419 StartRegister
, StartRegister
+ BoolCount
,
3421 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3423 nine_context_set_vertex_shader_constant_b(This
, StartRegister
, pConstantData
,
3424 sizeof(BOOL
) * BoolCount
, BoolCount
);
3430 NineDevice9_GetVertexShaderConstantB( struct NineDevice9
*This
,
3432 BOOL
*pConstantData
,
3435 const struct nine_state
*state
= &This
->state
;
3438 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3439 D3DERR_INVALIDCALL
);
3440 user_assert(StartRegister
+ BoolCount
<= (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3441 D3DERR_INVALIDCALL
);
3442 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3444 for (i
= 0; i
< BoolCount
; i
++)
3445 pConstantData
[i
] = state
->vs_const_b
[StartRegister
+ i
] != 0 ? TRUE
: FALSE
;
3451 NineDevice9_SetStreamSource( struct NineDevice9
*This
,
3453 IDirect3DVertexBuffer9
*pStreamData
,
3457 struct nine_state
*state
= This
->update
;
3458 struct NineVertexBuffer9
*pVBuf9
= NineVertexBuffer9(pStreamData
);
3459 const unsigned i
= StreamNumber
;
3461 DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",
3462 This
, StreamNumber
, pStreamData
, OffsetInBytes
, Stride
);
3464 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3465 user_assert(Stride
<= This
->caps
.MaxStreamStride
, D3DERR_INVALIDCALL
);
3467 if (unlikely(This
->is_recording
)) {
3468 nine_bind(&state
->stream
[i
], pStreamData
);
3469 state
->changed
.vtxbuf
|= 1 << StreamNumber
;
3470 state
->vtxbuf
[i
].stride
= Stride
;
3471 state
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
3475 if (state
->stream
[i
] == NineVertexBuffer9(pStreamData
) &&
3476 state
->vtxbuf
[i
].stride
== Stride
&&
3477 state
->vtxbuf
[i
].buffer_offset
== OffsetInBytes
)
3480 state
->vtxbuf
[i
].stride
= Stride
;
3481 state
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
3483 NineBindBufferToDevice(This
,
3484 (struct NineBuffer9
**)&state
->stream
[i
],
3485 (struct NineBuffer9
*)pVBuf9
);
3487 nine_context_set_stream_source(This
,
3497 NineDevice9_GetStreamSource( struct NineDevice9
*This
,
3499 IDirect3DVertexBuffer9
**ppStreamData
,
3500 UINT
*pOffsetInBytes
,
3503 const struct nine_state
*state
= &This
->state
;
3504 const unsigned i
= StreamNumber
;
3506 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3507 user_assert(ppStreamData
, D3DERR_INVALIDCALL
);
3509 nine_reference_set(ppStreamData
, state
->stream
[i
]);
3510 *pStride
= state
->vtxbuf
[i
].stride
;
3511 *pOffsetInBytes
= state
->vtxbuf
[i
].buffer_offset
;
3517 NineDevice9_SetStreamSourceFreq( struct NineDevice9
*This
,
3521 struct nine_state
*state
= This
->update
;
3522 /* const UINT freq = Setting & 0x7FFFFF; */
3524 DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This
,
3525 StreamNumber
, Setting
);
3527 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3528 user_assert(StreamNumber
!= 0 || !(Setting
& D3DSTREAMSOURCE_INSTANCEDATA
),
3529 D3DERR_INVALIDCALL
);
3530 user_assert(!((Setting
& D3DSTREAMSOURCE_INSTANCEDATA
) &&
3531 (Setting
& D3DSTREAMSOURCE_INDEXEDDATA
)), D3DERR_INVALIDCALL
);
3532 user_assert(Setting
, D3DERR_INVALIDCALL
);
3534 if (unlikely(This
->is_recording
)) {
3535 state
->stream_freq
[StreamNumber
] = Setting
;
3536 state
->changed
.stream_freq
|= 1 << StreamNumber
;
3537 if (StreamNumber
!= 0)
3538 state
->changed
.group
|= NINE_STATE_STREAMFREQ
;
3542 if (state
->stream_freq
[StreamNumber
] == Setting
)
3545 state
->stream_freq
[StreamNumber
] = Setting
;
3547 nine_context_set_stream_source_freq(This
, StreamNumber
, Setting
);
3552 NineDevice9_GetStreamSourceFreq( struct NineDevice9
*This
,
3556 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3557 *pSetting
= This
->state
.stream_freq
[StreamNumber
];
3562 NineDevice9_SetIndices( struct NineDevice9
*This
,
3563 IDirect3DIndexBuffer9
*pIndexData
)
3565 struct nine_state
*state
= This
->update
;
3566 struct NineIndexBuffer9
*idxbuf
= NineIndexBuffer9(pIndexData
);
3568 DBG("This=%p pIndexData=%p\n", This
, pIndexData
);
3570 if (unlikely(This
->is_recording
)) {
3571 nine_bind(&state
->idxbuf
, idxbuf
);
3572 state
->changed
.group
|= NINE_STATE_IDXBUF
;
3576 if (state
->idxbuf
== idxbuf
)
3579 NineBindBufferToDevice(This
,
3580 (struct NineBuffer9
**)&state
->idxbuf
,
3581 (struct NineBuffer9
*)idxbuf
);
3583 nine_context_set_indices(This
, idxbuf
);
3588 /* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
3589 * here because it's an argument passed to the Draw calls.
3592 NineDevice9_GetIndices( struct NineDevice9
*This
,
3593 IDirect3DIndexBuffer9
**ppIndexData
)
3595 user_assert(ppIndexData
, D3DERR_INVALIDCALL
);
3596 nine_reference_set(ppIndexData
, This
->state
.idxbuf
);
3601 NineDevice9_CreatePixelShader( struct NineDevice9
*This
,
3602 const DWORD
*pFunction
,
3603 IDirect3DPixelShader9
**ppShader
)
3605 struct NinePixelShader9
*ps
;
3608 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3610 hr
= NinePixelShader9_new(This
, &ps
, pFunction
, NULL
);
3613 *ppShader
= (IDirect3DPixelShader9
*)ps
;
3618 NineDevice9_SetPixelShader( struct NineDevice9
*This
,
3619 IDirect3DPixelShader9
*pShader
)
3621 struct nine_state
*state
= This
->update
;
3622 struct NinePixelShader9
*ps
= (struct NinePixelShader9
*)pShader
;
3624 DBG("This=%p pShader=%p\n", This
, pShader
);
3626 if (unlikely(This
->is_recording
)) {
3627 /* Technically we need NINE_STATE_FB only
3628 * if the ps mask changes, but put it always
3630 nine_bind(&state
->ps
, pShader
);
3631 state
->changed
.group
|= NINE_STATE_PS
| NINE_STATE_FB
;
3635 if (state
->ps
== ps
)
3638 nine_bind(&state
->ps
, ps
);
3640 nine_context_set_pixel_shader(This
, ps
);
3646 NineDevice9_GetPixelShader( struct NineDevice9
*This
,
3647 IDirect3DPixelShader9
**ppShader
)
3649 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3650 nine_reference_set(ppShader
, This
->state
.ps
);
3655 NineDevice9_SetPixelShaderConstantF( struct NineDevice9
*This
,
3657 const float *pConstantData
,
3658 UINT Vector4fCount
)
3660 struct nine_state
*state
= This
->update
;
3662 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3663 This
, StartRegister
, pConstantData
, Vector4fCount
);
3665 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3666 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3670 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3672 if (unlikely(This
->is_recording
)) {
3673 memcpy(&state
->ps_const_f
[StartRegister
* 4],
3675 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3677 nine_ranges_insert(&state
->changed
.ps_const_f
,
3678 StartRegister
, StartRegister
+ Vector4fCount
,
3681 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3685 if (!memcmp(&state
->ps_const_f
[StartRegister
* 4], pConstantData
,
3686 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0])))
3689 memcpy(&state
->ps_const_f
[StartRegister
* 4],
3691 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3693 nine_context_set_pixel_shader_constant_f(This
, StartRegister
, pConstantData
,
3694 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]),
3701 NineDevice9_GetPixelShaderConstantF( struct NineDevice9
*This
,
3703 float *pConstantData
,
3704 UINT Vector4fCount
)
3706 const struct nine_state
*state
= &This
->state
;
3708 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3709 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3710 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3712 memcpy(pConstantData
,
3713 &state
->ps_const_f
[StartRegister
* 4],
3714 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3720 NineDevice9_SetPixelShaderConstantI( struct NineDevice9
*This
,
3722 const int *pConstantData
,
3723 UINT Vector4iCount
)
3725 struct nine_state
*state
= This
->update
;
3728 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3729 This
, StartRegister
, pConstantData
, Vector4iCount
);
3731 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3732 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3733 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3735 if (This
->driver_caps
.ps_integer
) {
3736 if (!This
->is_recording
) {
3737 if (!memcmp(&state
->ps_const_i
[StartRegister
][0], pConstantData
,
3738 Vector4iCount
* sizeof(state
->ps_const_i
[0])))
3741 memcpy(&state
->ps_const_i
[StartRegister
][0],
3743 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3745 for (i
= 0; i
< Vector4iCount
; i
++) {
3746 state
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
3747 state
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
3748 state
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
3749 state
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
3753 if (unlikely(This
->is_recording
)) {
3754 state
->changed
.ps_const_i
|= ((1 << Vector4iCount
) - 1) << StartRegister
;
3755 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3757 nine_context_set_pixel_shader_constant_i(This
, StartRegister
, pConstantData
,
3758 sizeof(state
->ps_const_i
[0]) * Vector4iCount
, Vector4iCount
);
3764 NineDevice9_GetPixelShaderConstantI( struct NineDevice9
*This
,
3767 UINT Vector4iCount
)
3769 const struct nine_state
*state
= &This
->state
;
3772 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3773 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3774 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3776 if (This
->driver_caps
.ps_integer
) {
3777 memcpy(pConstantData
,
3778 &state
->ps_const_i
[StartRegister
][0],
3779 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3781 for (i
= 0; i
< Vector4iCount
; i
++) {
3782 pConstantData
[4*i
] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][0]);
3783 pConstantData
[4*i
+1] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][1]);
3784 pConstantData
[4*i
+2] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][2]);
3785 pConstantData
[4*i
+3] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][3]);
3793 NineDevice9_SetPixelShaderConstantB( struct NineDevice9
*This
,
3795 const BOOL
*pConstantData
,
3798 struct nine_state
*state
= This
->update
;
3800 uint32_t bool_true
= This
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
3802 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3803 This
, StartRegister
, pConstantData
, BoolCount
);
3805 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3806 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3807 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3809 if (!This
->is_recording
) {
3810 bool noChange
= true;
3811 for (i
= 0; i
< BoolCount
; i
++) {
3812 if (!!state
->ps_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3819 for (i
= 0; i
< BoolCount
; i
++)
3820 state
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3822 if (unlikely(This
->is_recording
)) {
3823 state
->changed
.ps_const_b
|= ((1 << BoolCount
) - 1) << StartRegister
;
3824 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3826 nine_context_set_pixel_shader_constant_b(This
, StartRegister
, pConstantData
,
3827 sizeof(BOOL
) * BoolCount
, BoolCount
);
3833 NineDevice9_GetPixelShaderConstantB( struct NineDevice9
*This
,
3835 BOOL
*pConstantData
,
3838 const struct nine_state
*state
= &This
->state
;
3841 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3842 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3843 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3845 for (i
= 0; i
< BoolCount
; i
++)
3846 pConstantData
[i
] = state
->ps_const_b
[StartRegister
+ i
] ? TRUE
: FALSE
;
3852 NineDevice9_DrawRectPatch( struct NineDevice9
*This
,
3854 const float *pNumSegs
,
3855 const D3DRECTPATCH_INFO
*pRectPatchInfo
)
3857 STUB(D3DERR_INVALIDCALL
);
3861 NineDevice9_DrawTriPatch( struct NineDevice9
*This
,
3863 const float *pNumSegs
,
3864 const D3DTRIPATCH_INFO
*pTriPatchInfo
)
3866 STUB(D3DERR_INVALIDCALL
);
3870 NineDevice9_DeletePatch( struct NineDevice9
*This
,
3873 STUB(D3DERR_INVALIDCALL
);
3877 NineDevice9_CreateQuery( struct NineDevice9
*This
,
3879 IDirect3DQuery9
**ppQuery
)
3881 struct NineQuery9
*query
;
3884 DBG("This=%p Type=%d ppQuery=%p\n", This
, Type
, ppQuery
);
3886 hr
= nine_is_query_supported(This
->screen
, Type
);
3887 if (!ppQuery
|| hr
!= D3D_OK
)
3890 hr
= NineQuery9_new(This
, &query
, Type
);
3893 *ppQuery
= (IDirect3DQuery9
*)query
;
3897 IDirect3DDevice9Vtbl NineDevice9_vtable
= {
3898 (void *)NineUnknown_QueryInterface
,
3899 (void *)NineUnknown_AddRef
,
3900 (void *)NineUnknown_Release
,
3901 (void *)NineDevice9_TestCooperativeLevel
,
3902 (void *)NineDevice9_GetAvailableTextureMem
,
3903 (void *)NineDevice9_EvictManagedResources
,
3904 (void *)NineDevice9_GetDirect3D
,
3905 (void *)NineDevice9_GetDeviceCaps
,
3906 (void *)NineDevice9_GetDisplayMode
,
3907 (void *)NineDevice9_GetCreationParameters
,
3908 (void *)NineDevice9_SetCursorProperties
,
3909 (void *)NineDevice9_SetCursorPosition
,
3910 (void *)NineDevice9_ShowCursor
,
3911 (void *)NineDevice9_CreateAdditionalSwapChain
,
3912 (void *)NineDevice9_GetSwapChain
,
3913 (void *)NineDevice9_GetNumberOfSwapChains
,
3914 (void *)NineDevice9_Reset
,
3915 (void *)NineDevice9_Present
,
3916 (void *)NineDevice9_GetBackBuffer
,
3917 (void *)NineDevice9_GetRasterStatus
,
3918 (void *)NineDevice9_SetDialogBoxMode
,
3919 (void *)NineDevice9_SetGammaRamp
,
3920 (void *)NineDevice9_GetGammaRamp
,
3921 (void *)NineDevice9_CreateTexture
,
3922 (void *)NineDevice9_CreateVolumeTexture
,
3923 (void *)NineDevice9_CreateCubeTexture
,
3924 (void *)NineDevice9_CreateVertexBuffer
,
3925 (void *)NineDevice9_CreateIndexBuffer
,
3926 (void *)NineDevice9_CreateRenderTarget
,
3927 (void *)NineDevice9_CreateDepthStencilSurface
,
3928 (void *)NineDevice9_UpdateSurface
,
3929 (void *)NineDevice9_UpdateTexture
,
3930 (void *)NineDevice9_GetRenderTargetData
,
3931 (void *)NineDevice9_GetFrontBufferData
,
3932 (void *)NineDevice9_StretchRect
,
3933 (void *)NineDevice9_ColorFill
,
3934 (void *)NineDevice9_CreateOffscreenPlainSurface
,
3935 (void *)NineDevice9_SetRenderTarget
,
3936 (void *)NineDevice9_GetRenderTarget
,
3937 (void *)NineDevice9_SetDepthStencilSurface
,
3938 (void *)NineDevice9_GetDepthStencilSurface
,
3939 (void *)NineDevice9_BeginScene
,
3940 (void *)NineDevice9_EndScene
,
3941 (void *)NineDevice9_Clear
,
3942 (void *)NineDevice9_SetTransform
,
3943 (void *)NineDevice9_GetTransform
,
3944 (void *)NineDevice9_MultiplyTransform
,
3945 (void *)NineDevice9_SetViewport
,
3946 (void *)NineDevice9_GetViewport
,
3947 (void *)NineDevice9_SetMaterial
,
3948 (void *)NineDevice9_GetMaterial
,
3949 (void *)NineDevice9_SetLight
,
3950 (void *)NineDevice9_GetLight
,
3951 (void *)NineDevice9_LightEnable
,
3952 (void *)NineDevice9_GetLightEnable
,
3953 (void *)NineDevice9_SetClipPlane
,
3954 (void *)NineDevice9_GetClipPlane
,
3955 (void *)NineDevice9_SetRenderState
,
3956 (void *)NineDevice9_GetRenderState
,
3957 (void *)NineDevice9_CreateStateBlock
,
3958 (void *)NineDevice9_BeginStateBlock
,
3959 (void *)NineDevice9_EndStateBlock
,
3960 (void *)NineDevice9_SetClipStatus
,
3961 (void *)NineDevice9_GetClipStatus
,
3962 (void *)NineDevice9_GetTexture
,
3963 (void *)NineDevice9_SetTexture
,
3964 (void *)NineDevice9_GetTextureStageState
,
3965 (void *)NineDevice9_SetTextureStageState
,
3966 (void *)NineDevice9_GetSamplerState
,
3967 (void *)NineDevice9_SetSamplerState
,
3968 (void *)NineDevice9_ValidateDevice
,
3969 (void *)NineDevice9_SetPaletteEntries
,
3970 (void *)NineDevice9_GetPaletteEntries
,
3971 (void *)NineDevice9_SetCurrentTexturePalette
,
3972 (void *)NineDevice9_GetCurrentTexturePalette
,
3973 (void *)NineDevice9_SetScissorRect
,
3974 (void *)NineDevice9_GetScissorRect
,
3975 (void *)NineDevice9_SetSoftwareVertexProcessing
,
3976 (void *)NineDevice9_GetSoftwareVertexProcessing
,
3977 (void *)NineDevice9_SetNPatchMode
,
3978 (void *)NineDevice9_GetNPatchMode
,
3979 (void *)NineDevice9_DrawPrimitive
,
3980 (void *)NineDevice9_DrawIndexedPrimitive
,
3981 (void *)NineDevice9_DrawPrimitiveUP
,
3982 (void *)NineDevice9_DrawIndexedPrimitiveUP
,
3983 (void *)NineDevice9_ProcessVertices
,
3984 (void *)NineDevice9_CreateVertexDeclaration
,
3985 (void *)NineDevice9_SetVertexDeclaration
,
3986 (void *)NineDevice9_GetVertexDeclaration
,
3987 (void *)NineDevice9_SetFVF
,
3988 (void *)NineDevice9_GetFVF
,
3989 (void *)NineDevice9_CreateVertexShader
,
3990 (void *)NineDevice9_SetVertexShader
,
3991 (void *)NineDevice9_GetVertexShader
,
3992 (void *)NineDevice9_SetVertexShaderConstantF
,
3993 (void *)NineDevice9_GetVertexShaderConstantF
,
3994 (void *)NineDevice9_SetVertexShaderConstantI
,
3995 (void *)NineDevice9_GetVertexShaderConstantI
,
3996 (void *)NineDevice9_SetVertexShaderConstantB
,
3997 (void *)NineDevice9_GetVertexShaderConstantB
,
3998 (void *)NineDevice9_SetStreamSource
,
3999 (void *)NineDevice9_GetStreamSource
,
4000 (void *)NineDevice9_SetStreamSourceFreq
,
4001 (void *)NineDevice9_GetStreamSourceFreq
,
4002 (void *)NineDevice9_SetIndices
,
4003 (void *)NineDevice9_GetIndices
,
4004 (void *)NineDevice9_CreatePixelShader
,
4005 (void *)NineDevice9_SetPixelShader
,
4006 (void *)NineDevice9_GetPixelShader
,
4007 (void *)NineDevice9_SetPixelShaderConstantF
,
4008 (void *)NineDevice9_GetPixelShaderConstantF
,
4009 (void *)NineDevice9_SetPixelShaderConstantI
,
4010 (void *)NineDevice9_GetPixelShaderConstantI
,
4011 (void *)NineDevice9_SetPixelShaderConstantB
,
4012 (void *)NineDevice9_GetPixelShaderConstantB
,
4013 (void *)NineDevice9_DrawRectPatch
,
4014 (void *)NineDevice9_DrawTriPatch
,
4015 (void *)NineDevice9_DeletePatch
,
4016 (void *)NineDevice9_CreateQuery
4019 static const GUID
*NineDevice9_IIDs
[] = {
4020 &IID_IDirect3DDevice9
,
4026 NineDevice9_new( struct pipe_screen
*pScreen
,
4027 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
4029 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
4031 ID3DPresentGroup
*pPresentationGroup
,
4032 struct d3dadapter9_context
*pCTX
,
4034 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
4035 struct NineDevice9
**ppOut
,
4036 int minorVersionNum
)
4039 lock
= !!(pCreationParameters
->BehaviorFlags
& D3DCREATE_MULTITHREADED
);
4041 NINE_NEW(Device9
, ppOut
, lock
, /* args */
4042 pScreen
, pCreationParameters
, pCaps
,
4043 pPresentationParameters
, pD3D9
, pPresentationGroup
, pCTX
,
4044 ex
, pFullscreenDisplayMode
, minorVersionNum
);