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_helpers.h"
38 #include "nine_pipe.h"
40 #include "nine_dump.h"
41 #include "nine_limits.h"
43 #include "pipe/p_screen.h"
44 #include "pipe/p_context.h"
45 #include "pipe/p_config.h"
46 #include "util/u_math.h"
47 #include "util/u_inlines.h"
48 #include "util/u_hash_table.h"
49 #include "util/u_format.h"
50 #include "util/u_surface.h"
51 #include "util/u_upload_mgr.h"
52 #include "hud/hud_context.h"
54 #include "cso_cache/cso_context.h"
56 #define DBG_CHANNEL DBG_DEVICE
58 #if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))
60 static void nine_setup_fpu()
64 __asm__
__volatile__ ("fnstcw %0" : "=m" (*&c
));
66 /* clear the control word */
68 /* d3d9 doc/wine tests: mask all exceptions, use single-precision
69 * and round to nearest */
72 __asm__
__volatile__ ("fldcw %0" : : "m" (*&c
));
77 static void nine_setup_fpu(void)
79 WARN_ONCE("FPU setup not supported on non-x86 platforms\n");
85 NineDevice9_SetDefaultState( struct NineDevice9
*This
, boolean is_reset
)
87 struct NineSurface9
*refSurf
= NULL
;
89 DBG("This=%p is_reset=%d\n", This
, (int) is_reset
);
91 assert(!This
->is_recording
);
93 nine_state_set_defaults(This
, &This
->caps
, is_reset
);
95 This
->state
.viewport
.X
= 0;
96 This
->state
.viewport
.Y
= 0;
97 This
->state
.viewport
.Width
= 0;
98 This
->state
.viewport
.Height
= 0;
100 This
->state
.scissor
.minx
= 0;
101 This
->state
.scissor
.miny
= 0;
102 This
->state
.scissor
.maxx
= 0xffff;
103 This
->state
.scissor
.maxy
= 0xffff;
105 if (This
->nswapchains
&& This
->swapchains
[0]->params
.BackBufferCount
)
106 refSurf
= This
->swapchains
[0]->buffers
[0];
109 This
->state
.viewport
.Width
= refSurf
->desc
.Width
;
110 This
->state
.viewport
.Height
= refSurf
->desc
.Height
;
111 This
->state
.scissor
.maxx
= refSurf
->desc
.Width
;
112 This
->state
.scissor
.maxy
= refSurf
->desc
.Height
;
115 if (This
->nswapchains
&& This
->swapchains
[0]->params
.EnableAutoDepthStencil
) {
116 This
->state
.rs
[D3DRS_ZENABLE
] = TRUE
;
117 This
->state
.rs_advertised
[D3DRS_ZENABLE
] = TRUE
;
119 if (This
->state
.rs
[D3DRS_ZENABLE
])
120 NineDevice9_SetDepthStencilSurface(
121 This
, (IDirect3DSurface9
*)This
->swapchains
[0]->zsbuf
);
124 #define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
126 NineDevice9_ctor( struct NineDevice9
*This
,
127 struct NineUnknownParams
*pParams
,
128 struct pipe_screen
*pScreen
,
129 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
131 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
133 ID3DPresentGroup
*pPresentationGroup
,
134 struct d3dadapter9_context
*pCTX
,
136 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
137 int minorVersionNum
)
140 HRESULT hr
= NineUnknown_ctor(&This
->base
, pParams
);
142 DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "
143 "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",
144 This
, pParams
, pScreen
, pCreationParameters
, pCaps
, pPresentationParameters
, pD3D9
,
145 pPresentationGroup
, pCTX
, (int) ex
, pFullscreenDisplayMode
);
147 if (FAILED(hr
)) { return hr
; }
149 list_inithead(&This
->update_buffers
);
150 list_inithead(&This
->update_textures
);
151 list_inithead(&This
->managed_buffers
);
152 list_inithead(&This
->managed_textures
);
154 This
->screen
= pScreen
;
155 This
->screen_sw
= pCTX
->ref
;
158 This
->params
= *pCreationParameters
;
160 This
->present
= pPresentationGroup
;
161 This
->minor_version_num
= minorVersionNum
;
163 IDirect3D9_AddRef(This
->d3d9
);
164 ID3DPresentGroup_AddRef(This
->present
);
166 if (!(This
->params
.BehaviorFlags
& D3DCREATE_FPU_PRESERVE
))
169 if (This
->params
.BehaviorFlags
& D3DCREATE_SOFTWARE_VERTEXPROCESSING
) {
170 DBG("Application asked full Software Vertex Processing.\n");
172 This
->may_swvp
= true;
175 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
) {
176 DBG("Application asked mixed Software Vertex Processing.\n");
177 This
->may_swvp
= true;
179 /* TODO: check if swvp is resetted by device Resets */
181 if (This
->may_swvp
&&
182 (This
->screen
->get_shader_param(This
->screen
, PIPE_SHADER_VERTEX
,
183 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
)
184 < (NINE_MAX_CONST_F_SWVP
/2) * sizeof(float[4]) ||
185 This
->screen
->get_shader_param(This
->screen
, PIPE_SHADER_VERTEX
,
186 PIPE_SHADER_CAP_MAX_CONST_BUFFERS
) < 5)) {
187 /* Note: We just go on, some apps never use the abilities of
188 * swvp, and just set more constants than allowed at init.
189 * Only cards we support that are affected are the r500 */
190 WARN("Card unable to handle Software Vertex Processing. Game may fail\n");
193 /* When may_swvp, SetConstant* limits are different */
195 This
->caps
.MaxVertexShaderConst
= NINE_MAX_CONST_F_SWVP
;
197 This
->pipe
= This
->screen
->context_create(This
->screen
, NULL
, 0);
198 if (!This
->pipe
) { 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
->cso
= cso_create_context(This
->pipe
);
203 if (!This
->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
->pipe
, This
->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
]));
267 /* Initialize a dummy VBO to be used when a vertex declaration does not
268 * specify all the inputs needed by vertex shader, on win default behavior
269 * is to pass 0,0,0,0 to the shader */
271 struct pipe_transfer
*transfer
;
272 struct pipe_resource tmpl
;
276 memset(&tmpl
, 0, sizeof(tmpl
));
277 tmpl
.target
= PIPE_BUFFER
;
278 tmpl
.format
= PIPE_FORMAT_R8_UNORM
;
279 tmpl
.width0
= 16; /* 4 floats */
285 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
286 tmpl
.bind
= PIPE_BIND_VERTEX_BUFFER
;
288 This
->dummy_vbo
= pScreen
->resource_create(pScreen
, &tmpl
);
290 if (!This
->dummy_vbo
)
291 return D3DERR_OUTOFVIDEOMEMORY
;
293 u_box_1d(0, 16, &box
);
294 data
= This
->pipe
->transfer_map(This
->pipe
, This
->dummy_vbo
, 0,
295 PIPE_TRANSFER_WRITE
|
296 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
301 This
->pipe
->transfer_unmap(This
->pipe
, transfer
);
304 This
->cursor
.software
= FALSE
;
305 This
->cursor
.hotspot
.x
= -1;
306 This
->cursor
.hotspot
.y
= -1;
308 struct pipe_resource tmpl
;
309 memset(&tmpl
, 0, sizeof(tmpl
));
310 tmpl
.target
= PIPE_TEXTURE_2D
;
311 tmpl
.format
= PIPE_FORMAT_R8G8B8A8_UNORM
;
318 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
319 tmpl
.bind
= PIPE_BIND_CURSOR
| PIPE_BIND_SAMPLER_VIEW
;
322 This
->cursor
.image
= pScreen
->resource_create(pScreen
, &tmpl
);
323 if (!This
->cursor
.image
)
324 return D3DERR_OUTOFVIDEOMEMORY
;
327 /* Create constant buffers. */
329 unsigned max_const_vs
, max_const_ps
;
331 /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
332 * we have to take in some more slots for int and bool*/
333 max_const_vs
= _min(pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
,
334 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
) /
337 /* ps 3.0: 224 float constants. All cards supported support at least
338 * 256 constants for ps */
339 max_const_ps
= NINE_MAX_CONST_F_PS3
+ (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
341 This
->max_vs_const_f
= max_const_vs
-
342 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
343 This
->max_ps_const_f
= max_const_ps
-
344 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
346 This
->vs_const_size
= max_const_vs
* sizeof(float[4]);
347 This
->ps_const_size
= max_const_ps
* sizeof(float[4]);
348 /* Include space for I,B constants for user constbuf. */
349 if (This
->may_swvp
) {
350 This
->state
.vs_const_f_swvp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
351 if (!This
->state
.vs_const_f_swvp
)
352 return E_OUTOFMEMORY
;
353 This
->state
.vs_lconstf_temp
= CALLOC(NINE_MAX_CONST_F_SWVP
* sizeof(float[4]),1);
354 This
->state
.vs_const_i
= CALLOC(NINE_MAX_CONST_I_SWVP
* sizeof(int[4]), 1);
355 This
->state
.vs_const_b
= CALLOC(NINE_MAX_CONST_B_SWVP
* sizeof(BOOL
), 1);
357 This
->state
.vs_const_f_swvp
= NULL
;
358 This
->state
.vs_lconstf_temp
= CALLOC(This
->vs_const_size
,1);
359 This
->state
.vs_const_i
= CALLOC(NINE_MAX_CONST_I
* sizeof(int[4]), 1);
360 This
->state
.vs_const_b
= CALLOC(NINE_MAX_CONST_B
* sizeof(BOOL
), 1);
362 This
->state
.vs_const_f
= CALLOC(This
->vs_const_size
, 1);
363 This
->state
.ps_const_f
= CALLOC(This
->ps_const_size
, 1);
364 This
->state
.ps_lconstf_temp
= CALLOC(This
->ps_const_size
,1);
365 if (!This
->state
.vs_const_f
|| !This
->state
.ps_const_f
||
366 !This
->state
.vs_lconstf_temp
|| !This
->state
.ps_lconstf_temp
||
367 !This
->state
.vs_const_i
|| !This
->state
.vs_const_b
)
368 return E_OUTOFMEMORY
;
370 if (strstr(pScreen
->get_name(pScreen
), "AMD") ||
371 strstr(pScreen
->get_name(pScreen
), "ATI")) {
372 This
->driver_bugs
.buggy_barycentrics
= TRUE
;
376 /* allocate dummy texture/sampler for when there are missing ones bound */
378 struct pipe_resource tmplt
;
379 struct pipe_sampler_view templ
;
380 struct pipe_sampler_state samp
;
381 memset(&tmplt
, 0, sizeof(tmplt
));
382 memset(&samp
, 0, sizeof(samp
));
384 tmplt
.target
= PIPE_TEXTURE_2D
;
388 tmplt
.last_level
= 0;
389 tmplt
.array_size
= 1;
390 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
392 tmplt
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
393 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
;
394 tmplt
.nr_samples
= 0;
396 This
->dummy_texture
= This
->screen
->resource_create(This
->screen
, &tmplt
);
397 if (!This
->dummy_texture
)
398 return D3DERR_DRIVERINTERNALERROR
;
400 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
401 templ
.u
.tex
.first_layer
= 0;
402 templ
.u
.tex
.last_layer
= 0;
403 templ
.u
.tex
.first_level
= 0;
404 templ
.u
.tex
.last_level
= 0;
405 templ
.swizzle_r
= PIPE_SWIZZLE_0
;
406 templ
.swizzle_g
= PIPE_SWIZZLE_0
;
407 templ
.swizzle_b
= PIPE_SWIZZLE_0
;
408 templ
.swizzle_a
= PIPE_SWIZZLE_1
;
409 templ
.target
= This
->dummy_texture
->target
;
411 This
->dummy_sampler_view
= This
->pipe
->create_sampler_view(This
->pipe
, This
->dummy_texture
, &templ
);
412 if (!This
->dummy_sampler_view
)
413 return D3DERR_DRIVERINTERNALERROR
;
415 samp
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
416 samp
.max_lod
= 15.0f
;
417 samp
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
418 samp
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
419 samp
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
420 samp
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
421 samp
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
422 samp
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
423 samp
.compare_func
= PIPE_FUNC_LEQUAL
;
424 samp
.normalized_coords
= 1;
425 samp
.seamless_cube_map
= 0;
426 This
->dummy_sampler_state
= samp
;
429 /* Allocate upload helper for drivers that suck (from st pov ;). */
431 This
->driver_caps
.user_vbufs
= GET_PCAP(USER_VERTEX_BUFFERS
);
432 This
->driver_caps
.user_ibufs
= GET_PCAP(USER_INDEX_BUFFERS
);
433 This
->driver_caps
.user_cbufs
= GET_PCAP(USER_CONSTANT_BUFFERS
);
434 This
->driver_caps
.user_sw_vbufs
= This
->screen_sw
->get_param(This
->screen_sw
, PIPE_CAP_USER_VERTEX_BUFFERS
);
435 This
->driver_caps
.user_sw_cbufs
= This
->screen_sw
->get_param(This
->screen_sw
, PIPE_CAP_USER_CONSTANT_BUFFERS
);
437 if (!This
->driver_caps
.user_vbufs
)
438 This
->vertex_uploader
= u_upload_create(This
->pipe
, 65536,
439 PIPE_BIND_VERTEX_BUFFER
, PIPE_USAGE_STREAM
);
440 This
->vertex_sw_uploader
= u_upload_create(This
->pipe_sw
, 65536,
441 PIPE_BIND_VERTEX_BUFFER
, PIPE_USAGE_STREAM
);
442 if (!This
->driver_caps
.user_ibufs
)
443 This
->index_uploader
= u_upload_create(This
->pipe
, 128 * 1024,
444 PIPE_BIND_INDEX_BUFFER
, PIPE_USAGE_STREAM
);
445 if (!This
->driver_caps
.user_cbufs
) {
446 This
->constbuf_alignment
= GET_PCAP(CONSTANT_BUFFER_OFFSET_ALIGNMENT
);
447 This
->constbuf_uploader
= u_upload_create(This
->pipe
, This
->vs_const_size
,
448 PIPE_BIND_CONSTANT_BUFFER
, PIPE_USAGE_STREAM
);
451 This
->constbuf_sw_uploader
= u_upload_create(This
->pipe_sw
, 128 * 1024,
452 PIPE_BIND_CONSTANT_BUFFER
, PIPE_USAGE_STREAM
);
454 This
->driver_caps
.window_space_position_support
= GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION
);
455 This
->driver_caps
.vs_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
, PIPE_SHADER_CAP_INTEGERS
);
456 This
->driver_caps
.ps_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_INTEGERS
);
457 This
->driver_caps
.offset_units_unscaled
= GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED
);
459 nine_ff_init(This
); /* initialize fixed function code */
461 NineDevice9_SetDefaultState(This
, FALSE
);
464 struct pipe_poly_stipple stipple
;
465 memset(&stipple
, ~0, sizeof(stipple
));
466 This
->pipe
->set_polygon_stipple(This
->pipe
, &stipple
);
469 This
->update
= &This
->state
;
470 nine_update_state(This
);
472 nine_state_init_sw(This
);
474 ID3DPresentGroup_Release(This
->present
);
481 NineDevice9_dtor( struct NineDevice9
*This
)
485 DBG("This=%p\n", This
);
487 if (This
->pipe
&& This
->cso
)
488 nine_pipe_context_clear(This
);
490 nine_state_destroy_sw(This
);
491 nine_state_clear(&This
->state
, TRUE
);
493 if (This
->vertex_uploader
)
494 u_upload_destroy(This
->vertex_uploader
);
495 if (This
->index_uploader
)
496 u_upload_destroy(This
->index_uploader
);
497 if (This
->constbuf_uploader
)
498 u_upload_destroy(This
->constbuf_uploader
);
499 if (This
->vertex_sw_uploader
)
500 u_upload_destroy(This
->vertex_sw_uploader
);
501 if (This
->constbuf_sw_uploader
)
502 u_upload_destroy(This
->constbuf_sw_uploader
);
504 nine_bind(&This
->record
, NULL
);
506 pipe_sampler_view_reference(&This
->dummy_sampler_view
, NULL
);
507 pipe_resource_reference(&This
->dummy_texture
, NULL
);
508 pipe_resource_reference(&This
->dummy_vbo
, NULL
);
509 FREE(This
->state
.vs_const_f
);
510 FREE(This
->state
.ps_const_f
);
511 FREE(This
->state
.vs_lconstf_temp
);
512 FREE(This
->state
.ps_lconstf_temp
);
513 FREE(This
->state
.vs_const_i
);
514 FREE(This
->state
.vs_const_b
);
515 FREE(This
->state
.vs_const_f_swvp
);
517 if (This
->swapchains
) {
518 for (i
= 0; i
< This
->nswapchains
; ++i
)
519 if (This
->swapchains
[i
])
520 NineUnknown_Unbind(NineUnknown(This
->swapchains
[i
]));
521 FREE(This
->swapchains
);
524 /* Destroy cso first */
525 if (This
->cso
) { cso_destroy_context(This
->cso
); }
526 if (This
->cso_sw
) { cso_destroy_context(This
->cso_sw
); }
527 if (This
->pipe
&& This
->pipe
->destroy
) { This
->pipe
->destroy(This
->pipe
); }
528 if (This
->pipe_sw
&& This
->pipe_sw
->destroy
) { This
->pipe_sw
->destroy(This
->pipe_sw
); }
530 if (This
->present
) { ID3DPresentGroup_Release(This
->present
); }
531 if (This
->d3d9
) { IDirect3D9_Release(This
->d3d9
); }
533 NineUnknown_dtor(&This
->base
);
537 NineDevice9_GetScreen( struct NineDevice9
*This
)
542 struct pipe_context
*
543 NineDevice9_GetPipe( struct NineDevice9
*This
)
549 NineDevice9_GetCSO( struct NineDevice9
*This
)
555 NineDevice9_GetCaps( struct NineDevice9
*This
)
561 NineDevice9_PauseRecording( struct NineDevice9
*This
)
564 This
->update
= &This
->state
;
565 This
->is_recording
= FALSE
;
570 NineDevice9_ResumeRecording( struct NineDevice9
*This
)
573 This
->update
= &This
->record
->state
;
574 This
->is_recording
= TRUE
;
579 NineDevice9_TestCooperativeLevel( struct NineDevice9
*This
)
581 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
582 This
->device_needs_reset
= TRUE
;
583 return D3DERR_DEVICELOST
;
584 } else if (NineSwapChain9_ResolutionMismatch(This
->swapchains
[0])) {
585 This
->device_needs_reset
= TRUE
;
586 return D3DERR_DEVICENOTRESET
;
587 } else if (This
->device_needs_reset
) {
588 return D3DERR_DEVICENOTRESET
;
595 NineDevice9_GetAvailableTextureMem( struct NineDevice9
*This
)
597 return This
->available_texture_mem
;
601 NineDevice9_EvictManagedResources( struct NineDevice9
*This
)
603 struct NineBaseTexture9
*tex
;
604 struct NineBuffer9
*buf
;
606 DBG("This=%p\n", This
);
607 LIST_FOR_EACH_ENTRY(tex
, &This
->managed_textures
, list2
) {
608 NineBaseTexture9_UnLoad(tex
);
610 /* Vertex/index buffers don't take a lot of space and aren't accounted
611 * for d3d memory usage. Instead of actually freeing from memory,
612 * just mark the buffer dirty to trigger a re-upload later. We
613 * could just ignore, but some bad behaving apps could rely on it (if
614 * they write outside the locked regions typically). */
615 LIST_FOR_EACH_ENTRY(buf
, &This
->managed_buffers
, managed
.list2
) {
616 NineBuffer9_SetDirty(buf
);
623 NineDevice9_GetDirect3D( struct NineDevice9
*This
,
624 IDirect3D9
**ppD3D9
)
626 user_assert(ppD3D9
!= NULL
, E_POINTER
);
627 IDirect3D9_AddRef(This
->d3d9
);
628 *ppD3D9
= This
->d3d9
;
633 NineDevice9_GetDeviceCaps( struct NineDevice9
*This
,
636 user_assert(pCaps
!= NULL
, D3DERR_INVALIDCALL
);
642 NineDevice9_GetDisplayMode( struct NineDevice9
*This
,
644 D3DDISPLAYMODE
*pMode
)
646 DBG("This=%p iSwapChain=%u pMode=%p\n", This
, iSwapChain
, pMode
);
648 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
650 return NineSwapChain9_GetDisplayMode(This
->swapchains
[iSwapChain
], pMode
);
654 NineDevice9_GetCreationParameters( struct NineDevice9
*This
,
655 D3DDEVICE_CREATION_PARAMETERS
*pParameters
)
657 user_assert(pParameters
!= NULL
, D3DERR_INVALIDCALL
);
658 *pParameters
= This
->params
;
663 NineDevice9_SetCursorProperties( struct NineDevice9
*This
,
666 IDirect3DSurface9
*pCursorBitmap
)
668 struct NineSurface9
*surf
= NineSurface9(pCursorBitmap
);
669 struct pipe_context
*pipe
= This
->pipe
;
671 struct pipe_transfer
*transfer
;
675 DBG_FLAG(DBG_SWAPCHAIN
, "This=%p XHotSpot=%u YHotSpot=%u "
676 "pCursorBitmap=%p\n", This
, XHotSpot
, YHotSpot
, pCursorBitmap
);
678 user_assert(pCursorBitmap
, D3DERR_INVALIDCALL
);
679 user_assert(surf
->desc
.Format
== D3DFMT_A8R8G8B8
, D3DERR_INVALIDCALL
);
681 if (This
->swapchains
[0]->params
.Windowed
) {
682 This
->cursor
.w
= MIN2(surf
->desc
.Width
, 32);
683 This
->cursor
.h
= MIN2(surf
->desc
.Height
, 32);
684 hw_cursor
= 1; /* always use hw cursor for windowed mode */
686 This
->cursor
.w
= MIN2(surf
->desc
.Width
, This
->cursor
.image
->width0
);
687 This
->cursor
.h
= MIN2(surf
->desc
.Height
, This
->cursor
.image
->height0
);
688 hw_cursor
= This
->cursor
.w
== 32 && This
->cursor
.h
== 32;
691 u_box_origin_2d(This
->cursor
.w
, This
->cursor
.h
, &box
);
693 ptr
= pipe
->transfer_map(pipe
, This
->cursor
.image
, 0,
694 PIPE_TRANSFER_WRITE
|
695 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
698 ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR
);
700 This
->cursor
.hotspot
.x
= XHotSpot
;
701 This
->cursor
.hotspot
.y
= YHotSpot
;
703 /* Copy cursor image to internal storage. */
707 const struct util_format_description
*sfmt
=
708 util_format_description(surf
->base
.info
.format
);
711 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, D3DLOCK_READONLY
);
713 ret_err("Failed to map cursor source image.\n",
714 D3DERR_DRIVERINTERNALERROR
);
716 sfmt
->unpack_rgba_8unorm(ptr
, transfer
->stride
,
717 lock
.pBits
, lock
.Pitch
,
718 This
->cursor
.w
, This
->cursor
.h
);
721 hw_cursor
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
,
723 &This
->cursor
.hotspot
,
724 This
->cursor
.visible
) == D3D_OK
;
726 NineSurface9_UnlockRect(surf
);
728 pipe
->transfer_unmap(pipe
, transfer
);
730 /* hide cursor if we emulate it */
732 ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, FALSE
);
733 This
->cursor
.software
= !hw_cursor
;
739 NineDevice9_SetCursorPosition( struct NineDevice9
*This
,
744 struct NineSwapChain9
*swap
= This
->swapchains
[0];
746 DBG("This=%p X=%d Y=%d Flags=%d\n", This
, X
, Y
, Flags
);
748 This
->cursor
.pos
.x
= X
;
749 This
->cursor
.pos
.y
= Y
;
751 if (!This
->cursor
.software
)
752 This
->cursor
.software
= ID3DPresent_SetCursorPos(swap
->present
, &This
->cursor
.pos
) != D3D_OK
;
756 NineDevice9_ShowCursor( struct NineDevice9
*This
,
759 BOOL old
= This
->cursor
.visible
;
761 DBG("This=%p bShow=%d\n", This
, (int) bShow
);
763 This
->cursor
.visible
= bShow
&& (This
->cursor
.hotspot
.x
!= -1);
764 if (!This
->cursor
.software
)
765 This
->cursor
.software
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, bShow
) != D3D_OK
;
771 NineDevice9_CreateAdditionalSwapChain( struct NineDevice9
*This
,
772 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
773 IDirect3DSwapChain9
**pSwapChain
)
775 struct NineSwapChain9
*swapchain
, *tmplt
= This
->swapchains
[0];
776 ID3DPresent
*present
;
779 DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",
780 This
, pPresentationParameters
, pSwapChain
);
782 user_assert(pPresentationParameters
, D3DERR_INVALIDCALL
);
783 user_assert(tmplt
->params
.Windowed
&& pPresentationParameters
->Windowed
, D3DERR_INVALIDCALL
);
785 /* TODO: this deserves more tests */
786 if (!pPresentationParameters
->hDeviceWindow
)
787 pPresentationParameters
->hDeviceWindow
= This
->params
.hFocusWindow
;
789 hr
= ID3DPresentGroup_CreateAdditionalPresent(This
->present
, pPresentationParameters
, &present
);
794 hr
= NineSwapChain9_new(This
, FALSE
, present
, pPresentationParameters
,
796 tmplt
->params
.hDeviceWindow
,
801 *pSwapChain
= (IDirect3DSwapChain9
*)swapchain
;
806 NineDevice9_GetSwapChain( struct NineDevice9
*This
,
808 IDirect3DSwapChain9
**pSwapChain
)
810 user_assert(pSwapChain
!= NULL
, D3DERR_INVALIDCALL
);
813 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
815 NineUnknown_AddRef(NineUnknown(This
->swapchains
[iSwapChain
]));
816 *pSwapChain
= (IDirect3DSwapChain9
*)This
->swapchains
[iSwapChain
];
822 NineDevice9_GetNumberOfSwapChains( struct NineDevice9
*This
)
824 return This
->nswapchains
;
828 NineDevice9_Reset( struct NineDevice9
*This
,
829 D3DPRESENT_PARAMETERS
*pPresentationParameters
)
834 DBG("This=%p pPresentationParameters=%p\n", This
, pPresentationParameters
);
836 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
837 This
->device_needs_reset
= TRUE
;
838 return D3DERR_DEVICELOST
;
841 for (i
= 0; i
< This
->nswapchains
; ++i
) {
842 D3DPRESENT_PARAMETERS
*params
= &pPresentationParameters
[i
];
843 hr
= NineSwapChain9_Resize(This
->swapchains
[i
], params
, NULL
);
848 nine_pipe_context_clear(This
);
849 nine_state_clear(&This
->state
, TRUE
);
851 NineDevice9_SetDefaultState(This
, TRUE
);
852 NineDevice9_SetRenderTarget(
853 This
, 0, (IDirect3DSurface9
*)This
->swapchains
[0]->buffers
[0]);
854 /* XXX: better use GetBackBuffer here ? */
856 This
->device_needs_reset
= (hr
!= D3D_OK
);
861 NineDevice9_Present( struct NineDevice9
*This
,
862 const RECT
*pSourceRect
,
863 const RECT
*pDestRect
,
864 HWND hDestWindowOverride
,
865 const RGNDATA
*pDirtyRegion
)
870 DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",
871 This
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
);
873 /* XXX is this right? */
874 for (i
= 0; i
< This
->nswapchains
; ++i
) {
875 hr
= NineSwapChain9_Present(This
->swapchains
[i
], pSourceRect
, pDestRect
,
876 hDestWindowOverride
, pDirtyRegion
, 0);
877 if (FAILED(hr
)) { return hr
; }
884 NineDevice9_GetBackBuffer( struct NineDevice9
*This
,
887 D3DBACKBUFFER_TYPE Type
,
888 IDirect3DSurface9
**ppBackBuffer
)
890 user_assert(ppBackBuffer
!= NULL
, D3DERR_INVALIDCALL
);
891 /* return NULL on error */
892 *ppBackBuffer
= NULL
;
893 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
895 return NineSwapChain9_GetBackBuffer(This
->swapchains
[iSwapChain
],
896 iBackBuffer
, Type
, ppBackBuffer
);
900 NineDevice9_GetRasterStatus( struct NineDevice9
*This
,
902 D3DRASTER_STATUS
*pRasterStatus
)
904 user_assert(pRasterStatus
!= NULL
, D3DERR_INVALIDCALL
);
905 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
907 return NineSwapChain9_GetRasterStatus(This
->swapchains
[iSwapChain
],
912 NineDevice9_SetDialogBoxMode( struct NineDevice9
*This
,
913 BOOL bEnableDialogs
)
915 STUB(D3DERR_INVALIDCALL
);
919 NineDevice9_SetGammaRamp( struct NineDevice9
*This
,
922 const D3DGAMMARAMP
*pRamp
)
924 DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This
,
925 iSwapChain
, Flags
, pRamp
);
927 user_warn(iSwapChain
>= This
->nswapchains
);
930 if (pRamp
&& (iSwapChain
< This
->nswapchains
)) {
931 struct NineSwapChain9
*swap
= This
->swapchains
[iSwapChain
];
932 swap
->gamma
= *pRamp
;
933 ID3DPresent_SetGammaRamp(swap
->present
, pRamp
, swap
->params
.hDeviceWindow
);
938 NineDevice9_GetGammaRamp( struct NineDevice9
*This
,
940 D3DGAMMARAMP
*pRamp
)
942 DBG("This=%p iSwapChain=%u pRamp=%p\n", This
, iSwapChain
, pRamp
);
944 user_warn(iSwapChain
>= This
->nswapchains
);
947 if (pRamp
&& (iSwapChain
< This
->nswapchains
))
948 *pRamp
= This
->swapchains
[iSwapChain
]->gamma
;
952 NineDevice9_CreateTexture( struct NineDevice9
*This
,
959 IDirect3DTexture9
**ppTexture
,
960 HANDLE
*pSharedHandle
)
962 struct NineTexture9
*tex
;
965 DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
966 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Levels
,
967 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
968 nine_D3DPOOL_to_str(Pool
), ppTexture
, pSharedHandle
);
970 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DMAP
|
971 D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
972 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
;
976 hr
= NineTexture9_new(This
, Width
, Height
, Levels
, Usage
, Format
, Pool
,
977 &tex
, pSharedHandle
);
979 *ppTexture
= (IDirect3DTexture9
*)tex
;
985 NineDevice9_CreateVolumeTexture( struct NineDevice9
*This
,
993 IDirect3DVolumeTexture9
**ppVolumeTexture
,
994 HANDLE
*pSharedHandle
)
996 struct NineVolumeTexture9
*tex
;
999 DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
1000 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Depth
, Levels
,
1001 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1002 nine_D3DPOOL_to_str(Pool
), ppVolumeTexture
, pSharedHandle
);
1004 Usage
&= D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1005 D3DUSAGE_SOFTWAREPROCESSING
;
1007 *ppVolumeTexture
= NULL
;
1009 hr
= NineVolumeTexture9_new(This
, Width
, Height
, Depth
, Levels
,
1010 Usage
, Format
, Pool
, &tex
, pSharedHandle
);
1012 *ppVolumeTexture
= (IDirect3DVolumeTexture9
*)tex
;
1018 NineDevice9_CreateCubeTexture( struct NineDevice9
*This
,
1024 IDirect3DCubeTexture9
**ppCubeTexture
,
1025 HANDLE
*pSharedHandle
)
1027 struct NineCubeTexture9
*tex
;
1030 DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
1031 "pSharedHandle=%p\n", This
, EdgeLength
, Levels
,
1032 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
1033 nine_D3DPOOL_to_str(Pool
), ppCubeTexture
, pSharedHandle
);
1035 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DYNAMIC
|
1036 D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
1037 D3DUSAGE_SOFTWAREPROCESSING
;
1039 *ppCubeTexture
= NULL
;
1041 hr
= NineCubeTexture9_new(This
, EdgeLength
, Levels
, Usage
, Format
, Pool
,
1042 &tex
, pSharedHandle
);
1044 *ppCubeTexture
= (IDirect3DCubeTexture9
*)tex
;
1050 NineDevice9_CreateVertexBuffer( struct NineDevice9
*This
,
1055 IDirect3DVertexBuffer9
**ppVertexBuffer
,
1056 HANDLE
*pSharedHandle
)
1058 struct NineVertexBuffer9
*buf
;
1060 D3DVERTEXBUFFER_DESC desc
;
1062 DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
1063 This
, Length
, Usage
, FVF
, Pool
, ppVertexBuffer
, pSharedHandle
);
1065 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1067 desc
.Format
= D3DFMT_VERTEXDATA
;
1068 desc
.Type
= D3DRTYPE_VERTEXBUFFER
;
1069 desc
.Usage
= Usage
&
1070 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1071 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1072 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
|
1073 D3DUSAGE_WRITEONLY
);
1078 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1079 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1081 hr
= NineVertexBuffer9_new(This
, &desc
, &buf
);
1083 *ppVertexBuffer
= (IDirect3DVertexBuffer9
*)buf
;
1088 NineDevice9_CreateIndexBuffer( struct NineDevice9
*This
,
1093 IDirect3DIndexBuffer9
**ppIndexBuffer
,
1094 HANDLE
*pSharedHandle
)
1096 struct NineIndexBuffer9
*buf
;
1098 D3DINDEXBUFFER_DESC desc
;
1100 DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
1101 "pSharedHandle=%p\n", This
, Length
, Usage
,
1102 d3dformat_to_string(Format
), Pool
, ppIndexBuffer
, pSharedHandle
);
1104 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1106 desc
.Format
= Format
;
1107 desc
.Type
= D3DRTYPE_INDEXBUFFER
;
1108 desc
.Usage
= Usage
&
1109 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1110 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1111 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_WRITEONLY
);
1115 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1116 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1118 hr
= NineIndexBuffer9_new(This
, &desc
, &buf
);
1120 *ppIndexBuffer
= (IDirect3DIndexBuffer9
*)buf
;
1125 create_zs_or_rt_surface(struct NineDevice9
*This
,
1126 unsigned type
, /* 0 = RT, 1 = ZS, 2 = plain */
1128 UINT Width
, UINT Height
,
1130 D3DMULTISAMPLE_TYPE MultiSample
,
1131 DWORD MultisampleQuality
,
1132 BOOL Discard_or_Lockable
,
1133 IDirect3DSurface9
**ppSurface
,
1134 HANDLE
*pSharedHandle
)
1136 struct NineSurface9
*surface
;
1138 D3DSURFACE_DESC desc
;
1140 DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
1141 "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
1142 This
, type
, nine_D3DPOOL_to_str(Pool
), Width
, Height
,
1143 d3dformat_to_string(Format
), MultiSample
, MultisampleQuality
,
1144 Discard_or_Lockable
, ppSurface
, pSharedHandle
);
1147 DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
1149 user_assert(Width
&& Height
, D3DERR_INVALIDCALL
);
1150 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1152 desc
.Format
= Format
;
1153 desc
.Type
= D3DRTYPE_SURFACE
;
1156 desc
.MultiSampleType
= MultiSample
;
1157 desc
.MultiSampleQuality
= MultisampleQuality
;
1159 desc
.Height
= Height
;
1161 case 0: desc
.Usage
= D3DUSAGE_RENDERTARGET
; break;
1162 case 1: desc
.Usage
= D3DUSAGE_DEPTHSTENCIL
; break;
1163 default: assert(type
== 2); break;
1166 hr
= NineSurface9_new(This
, NULL
, NULL
, NULL
, 0, 0, 0, &desc
, &surface
);
1167 if (SUCCEEDED(hr
)) {
1168 *ppSurface
= (IDirect3DSurface9
*)surface
;
1170 if (surface
->base
.resource
&& Discard_or_Lockable
&& (type
!= 1))
1171 surface
->base
.resource
->flags
|= NINE_RESOURCE_FLAG_LOCKABLE
;
1178 NineDevice9_CreateRenderTarget( struct NineDevice9
*This
,
1182 D3DMULTISAMPLE_TYPE MultiSample
,
1183 DWORD MultisampleQuality
,
1185 IDirect3DSurface9
**ppSurface
,
1186 HANDLE
*pSharedHandle
)
1189 return create_zs_or_rt_surface(This
, 0, D3DPOOL_DEFAULT
,
1190 Width
, Height
, Format
,
1191 MultiSample
, MultisampleQuality
,
1192 Lockable
, ppSurface
, pSharedHandle
);
1196 NineDevice9_CreateDepthStencilSurface( struct NineDevice9
*This
,
1200 D3DMULTISAMPLE_TYPE MultiSample
,
1201 DWORD MultisampleQuality
,
1203 IDirect3DSurface9
**ppSurface
,
1204 HANDLE
*pSharedHandle
)
1207 if (!depth_stencil_format(Format
))
1208 return D3DERR_NOTAVAILABLE
;
1209 return create_zs_or_rt_surface(This
, 1, D3DPOOL_DEFAULT
,
1210 Width
, Height
, Format
,
1211 MultiSample
, MultisampleQuality
,
1212 Discard
, ppSurface
, pSharedHandle
);
1216 NineDevice9_UpdateSurface( struct NineDevice9
*This
,
1217 IDirect3DSurface9
*pSourceSurface
,
1218 const RECT
*pSourceRect
,
1219 IDirect3DSurface9
*pDestinationSurface
,
1220 const POINT
*pDestPoint
)
1222 struct NineSurface9
*dst
= NineSurface9(pDestinationSurface
);
1223 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1224 int copy_width
, copy_height
;
1227 DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
1228 "pSourceRect=%p pDestPoint=%p\n", This
,
1229 pSourceSurface
, pDestinationSurface
, pSourceRect
, pDestPoint
);
1231 DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
1232 pSourceRect
->left
, pSourceRect
->top
,
1233 pSourceRect
->right
, pSourceRect
->bottom
);
1235 DBG("pDestPoint = (%u,%u)\n", pDestPoint
->x
, pDestPoint
->y
);
1237 user_assert(dst
&& src
, D3DERR_INVALIDCALL
);
1239 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1240 user_assert(src
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1242 user_assert(dst
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1243 user_assert(src
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1245 user_assert(!src
->lock_count
, D3DERR_INVALIDCALL
);
1246 user_assert(!dst
->lock_count
, D3DERR_INVALIDCALL
);
1248 user_assert(dst
->desc
.Format
== src
->desc
.Format
, D3DERR_INVALIDCALL
);
1249 user_assert(!depth_stencil_format(dst
->desc
.Format
), D3DERR_INVALIDCALL
);
1252 copy_width
= pSourceRect
->right
- pSourceRect
->left
;
1253 copy_height
= pSourceRect
->bottom
- pSourceRect
->top
;
1255 user_assert(pSourceRect
->left
>= 0 &&
1257 pSourceRect
->right
<= src
->desc
.Width
&&
1258 pSourceRect
->top
>= 0 &&
1260 pSourceRect
->bottom
<= src
->desc
.Height
,
1261 D3DERR_INVALIDCALL
);
1263 copy_width
= src
->desc
.Width
;
1264 copy_height
= src
->desc
.Height
;
1267 destRect
.right
= copy_width
;
1268 destRect
.bottom
= copy_height
;
1271 user_assert(pDestPoint
->x
>= 0 && pDestPoint
->y
>= 0,
1272 D3DERR_INVALIDCALL
);
1273 destRect
.right
+= pDestPoint
->x
;
1274 destRect
.bottom
+= pDestPoint
->y
;
1277 user_assert(destRect
.right
<= dst
->desc
.Width
&&
1278 destRect
.bottom
<= dst
->desc
.Height
,
1279 D3DERR_INVALIDCALL
);
1281 if (compressed_format(dst
->desc
.Format
)) {
1282 const unsigned w
= util_format_get_blockwidth(dst
->base
.info
.format
);
1283 const unsigned h
= util_format_get_blockheight(dst
->base
.info
.format
);
1286 user_assert(!(pDestPoint
->x
% w
) && !(pDestPoint
->y
% h
),
1287 D3DERR_INVALIDCALL
);
1291 user_assert(!(pSourceRect
->left
% w
) && !(pSourceRect
->top
% h
),
1292 D3DERR_INVALIDCALL
);
1294 if (!(copy_width
== src
->desc
.Width
&&
1295 copy_width
== dst
->desc
.Width
&&
1296 copy_height
== src
->desc
.Height
&&
1297 copy_height
== dst
->desc
.Height
)) {
1298 user_assert(!(copy_width
% w
) && !(copy_height
% h
),
1299 D3DERR_INVALIDCALL
);
1303 NineSurface9_CopyMemToDefault(dst
, src
, pDestPoint
, pSourceRect
);
1309 NineDevice9_UpdateTexture( struct NineDevice9
*This
,
1310 IDirect3DBaseTexture9
*pSourceTexture
,
1311 IDirect3DBaseTexture9
*pDestinationTexture
)
1313 struct NineBaseTexture9
*dstb
= NineBaseTexture9(pDestinationTexture
);
1314 struct NineBaseTexture9
*srcb
= NineBaseTexture9(pSourceTexture
);
1316 unsigned last_src_level
, last_dst_level
;
1319 DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This
,
1320 pSourceTexture
, pDestinationTexture
);
1322 user_assert(pSourceTexture
&& pDestinationTexture
, D3DERR_INVALIDCALL
);
1323 user_assert(pSourceTexture
!= pDestinationTexture
, D3DERR_INVALIDCALL
);
1325 user_assert(dstb
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1326 user_assert(srcb
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1327 user_assert(dstb
->base
.type
== srcb
->base
.type
, D3DERR_INVALIDCALL
);
1328 user_assert(!(srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ||
1329 dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
, D3DERR_INVALIDCALL
);
1332 * . Different formats
1333 * . Fewer src levels than dst levels (if the opposite, only matching levels
1334 * are supposed to be copied)
1335 * . Levels do not match
1336 * DDI: Actually the above should pass because of legacy applications
1337 * Do what you want about these, but you shouldn't crash.
1338 * However driver can expect that the top dimension is greater for src than dst.
1339 * Wine tests: Every combination that passes the initial checks should pass.
1340 * . Different formats => conversion driver and format dependent.
1341 * . 1 level, but size not matching => copy is done (and even crash if src bigger
1342 * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied
1343 * or if a subrect is copied).
1344 * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect
1347 * From these, the proposal is:
1348 * . Different formats -> use util_format_translate to translate if possible for surfaces.
1349 * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations
1350 * . First level copied -> the first level such that src is smaller or equal to dst first level
1351 * . number of levels copied -> as long as it fits and textures have levels
1352 * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK)
1355 last_src_level
= (srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ? 0 : srcb
->base
.info
.last_level
;
1356 last_dst_level
= (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ? 0 : dstb
->base
.info
.last_level
;
1358 for (m
= 0; m
<= last_src_level
; ++m
) {
1359 unsigned w
= u_minify(srcb
->base
.info
.width0
, m
);
1360 unsigned h
= u_minify(srcb
->base
.info
.height0
, m
);
1361 unsigned d
= u_minify(srcb
->base
.info
.depth0
, m
);
1363 if (w
<= dstb
->base
.info
.width0
&&
1364 h
<= dstb
->base
.info
.height0
&&
1365 d
<= dstb
->base
.info
.depth0
)
1368 user_assert(m
<= last_src_level
, D3D_OK
);
1370 last_dst_level
= MIN2(srcb
->base
.info
.last_level
- m
, last_dst_level
);
1372 if (dstb
->base
.type
== D3DRTYPE_TEXTURE
) {
1373 struct NineTexture9
*dst
= NineTexture9(dstb
);
1374 struct NineTexture9
*src
= NineTexture9(srcb
);
1376 if (src
->dirty_rect
.width
== 0)
1379 pipe_box_to_rect(&rect
, &src
->dirty_rect
);
1380 for (l
= 0; l
< m
; ++l
)
1381 rect_minify_inclusive(&rect
);
1383 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
) {
1384 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1386 dst
->surfaces
[l
]->desc
.Width
,
1387 dst
->surfaces
[l
]->desc
.Height
);
1388 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
],
1392 rect_minify_inclusive(&rect
);
1394 u_box_origin_2d(0, 0, &src
->dirty_rect
);
1396 if (dstb
->base
.type
== D3DRTYPE_CUBETEXTURE
) {
1397 struct NineCubeTexture9
*dst
= NineCubeTexture9(dstb
);
1398 struct NineCubeTexture9
*src
= NineCubeTexture9(srcb
);
1401 /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
1402 for (z
= 0; z
< 6; ++z
) {
1403 if (src
->dirty_rect
[z
].width
== 0)
1406 pipe_box_to_rect(&rect
, &src
->dirty_rect
[z
]);
1407 for (l
= 0; l
< m
; ++l
)
1408 rect_minify_inclusive(&rect
);
1410 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
) {
1411 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1413 dst
->surfaces
[l
* 6 + z
]->desc
.Width
,
1414 dst
->surfaces
[l
* 6 + z
]->desc
.Height
);
1415 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
* 6 + z
],
1416 src
->surfaces
[m
* 6 + z
],
1419 rect_minify_inclusive(&rect
);
1421 u_box_origin_2d(0, 0, &src
->dirty_rect
[z
]);
1425 if (dstb
->base
.type
== D3DRTYPE_VOLUMETEXTURE
) {
1426 struct NineVolumeTexture9
*dst
= NineVolumeTexture9(dstb
);
1427 struct NineVolumeTexture9
*src
= NineVolumeTexture9(srcb
);
1429 if (src
->dirty_box
.width
== 0)
1431 for (l
= 0; l
<= last_dst_level
; ++l
, ++m
)
1432 NineVolume9_CopyMemToDefault(dst
->volumes
[l
],
1433 src
->volumes
[m
], 0, 0, 0, NULL
);
1434 u_box_3d(0, 0, 0, 0, 0, 0, &src
->dirty_box
);
1436 assert(!"invalid texture type");
1439 if (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) {
1440 dstb
->dirty_mip
= TRUE
;
1441 NineBaseTexture9_GenerateMipSubLevels(dstb
);
1448 NineDevice9_GetRenderTargetData( struct NineDevice9
*This
,
1449 IDirect3DSurface9
*pRenderTarget
,
1450 IDirect3DSurface9
*pDestSurface
)
1452 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1453 struct NineSurface9
*src
= NineSurface9(pRenderTarget
);
1455 DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
1456 This
, pRenderTarget
, pDestSurface
);
1458 user_assert(dst
->desc
.Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1459 user_assert(src
->desc
.Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1461 user_assert(dst
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1462 user_assert(src
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1464 user_assert(src
->desc
.Width
== dst
->desc
.Width
, D3DERR_INVALIDCALL
);
1465 user_assert(src
->desc
.Height
== dst
->desc
.Height
, D3DERR_INVALIDCALL
);
1467 NineSurface9_CopyDefaultToMem(dst
, src
);
1473 NineDevice9_GetFrontBufferData( struct NineDevice9
*This
,
1475 IDirect3DSurface9
*pDestSurface
)
1477 DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This
,
1478 iSwapChain
, pDestSurface
);
1480 user_assert(pDestSurface
!= NULL
, D3DERR_INVALIDCALL
);
1481 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
1483 return NineSwapChain9_GetFrontBufferData(This
->swapchains
[iSwapChain
],
1488 NineDevice9_StretchRect( struct NineDevice9
*This
,
1489 IDirect3DSurface9
*pSourceSurface
,
1490 const RECT
*pSourceRect
,
1491 IDirect3DSurface9
*pDestSurface
,
1492 const RECT
*pDestRect
,
1493 D3DTEXTUREFILTERTYPE Filter
)
1495 struct pipe_screen
*screen
= This
->screen
;
1496 struct pipe_context
*pipe
= This
->pipe
;
1497 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1498 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1499 struct pipe_resource
*dst_res
= NineSurface9_GetResource(dst
);
1500 struct pipe_resource
*src_res
= NineSurface9_GetResource(src
);
1502 struct pipe_blit_info blit
;
1503 boolean scaled
, clamped
, ms
, flip_x
= FALSE
, flip_y
= FALSE
;
1505 DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
1506 "pDestRect=%p Filter=%u\n",
1507 This
, pSourceSurface
, pSourceRect
, pDestSurface
, pDestRect
, Filter
);
1509 DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
1510 pSourceRect
->left
, pSourceRect
->top
,
1511 pSourceRect
->right
, pSourceRect
->bottom
);
1513 DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect
->left
, pDestRect
->top
,
1514 pDestRect
->right
, pDestRect
->bottom
);
1516 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
&&
1517 src
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1518 zs
= util_format_is_depth_or_stencil(dst_res
->format
);
1519 user_assert(!zs
|| !This
->in_scene
, D3DERR_INVALIDCALL
);
1520 user_assert(!zs
|| !pSourceRect
||
1521 (pSourceRect
->left
== 0 &&
1522 pSourceRect
->top
== 0 &&
1523 pSourceRect
->right
== src
->desc
.Width
&&
1524 pSourceRect
->bottom
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1525 user_assert(!zs
|| !pDestRect
||
1526 (pDestRect
->left
== 0 &&
1527 pDestRect
->top
== 0 &&
1528 pDestRect
->right
== dst
->desc
.Width
&&
1529 pDestRect
->bottom
== dst
->desc
.Height
), D3DERR_INVALIDCALL
);
1531 (dst
->desc
.Width
== src
->desc
.Width
&&
1532 dst
->desc
.Height
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1533 user_assert(zs
|| !util_format_is_depth_or_stencil(src_res
->format
),
1534 D3DERR_INVALIDCALL
);
1535 user_assert(!zs
|| dst
->desc
.Format
== src
->desc
.Format
,
1536 D3DERR_INVALIDCALL
);
1537 user_assert(screen
->is_format_supported(screen
, src_res
->format
,
1539 src_res
->nr_samples
,
1540 PIPE_BIND_SAMPLER_VIEW
),
1541 D3DERR_INVALIDCALL
);
1543 /* We might want to permit these, but wine thinks we shouldn't. */
1544 user_assert(!pDestRect
||
1545 (pDestRect
->left
<= pDestRect
->right
&&
1546 pDestRect
->top
<= pDestRect
->bottom
), D3DERR_INVALIDCALL
);
1547 user_assert(!pSourceRect
||
1548 (pSourceRect
->left
<= pSourceRect
->right
&&
1549 pSourceRect
->top
<= pSourceRect
->bottom
), D3DERR_INVALIDCALL
);
1551 memset(&blit
, 0, sizeof(blit
));
1552 blit
.dst
.resource
= dst_res
;
1553 blit
.dst
.level
= dst
->level
;
1554 blit
.dst
.box
.z
= dst
->layer
;
1555 blit
.dst
.box
.depth
= 1;
1556 blit
.dst
.format
= dst_res
->format
;
1558 flip_x
= pDestRect
->left
> pDestRect
->right
;
1560 blit
.dst
.box
.x
= pDestRect
->right
;
1561 blit
.dst
.box
.width
= pDestRect
->left
- pDestRect
->right
;
1563 blit
.dst
.box
.x
= pDestRect
->left
;
1564 blit
.dst
.box
.width
= pDestRect
->right
- pDestRect
->left
;
1566 flip_y
= pDestRect
->top
> pDestRect
->bottom
;
1568 blit
.dst
.box
.y
= pDestRect
->bottom
;
1569 blit
.dst
.box
.height
= pDestRect
->top
- pDestRect
->bottom
;
1571 blit
.dst
.box
.y
= pDestRect
->top
;
1572 blit
.dst
.box
.height
= pDestRect
->bottom
- pDestRect
->top
;
1577 blit
.dst
.box
.width
= dst
->desc
.Width
;
1578 blit
.dst
.box
.height
= dst
->desc
.Height
;
1580 blit
.src
.resource
= src_res
;
1581 blit
.src
.level
= src
->level
;
1582 blit
.src
.box
.z
= src
->layer
;
1583 blit
.src
.box
.depth
= 1;
1584 blit
.src
.format
= src_res
->format
;
1586 if (flip_x
^ (pSourceRect
->left
> pSourceRect
->right
)) {
1587 blit
.src
.box
.x
= pSourceRect
->right
;
1588 blit
.src
.box
.width
= pSourceRect
->left
- pSourceRect
->right
;
1590 blit
.src
.box
.x
= pSourceRect
->left
;
1591 blit
.src
.box
.width
= pSourceRect
->right
- pSourceRect
->left
;
1593 if (flip_y
^ (pSourceRect
->top
> pSourceRect
->bottom
)) {
1594 blit
.src
.box
.y
= pSourceRect
->bottom
;
1595 blit
.src
.box
.height
= pSourceRect
->top
- pSourceRect
->bottom
;
1597 blit
.src
.box
.y
= pSourceRect
->top
;
1598 blit
.src
.box
.height
= pSourceRect
->bottom
- pSourceRect
->top
;
1601 blit
.src
.box
.x
= flip_x
? src
->desc
.Width
: 0;
1602 blit
.src
.box
.y
= flip_y
? src
->desc
.Height
: 0;
1603 blit
.src
.box
.width
= flip_x
? -src
->desc
.Width
: src
->desc
.Width
;
1604 blit
.src
.box
.height
= flip_y
? -src
->desc
.Height
: src
->desc
.Height
;
1606 blit
.mask
= zs
? PIPE_MASK_ZS
: PIPE_MASK_RGBA
;
1607 blit
.filter
= Filter
== D3DTEXF_LINEAR
?
1608 PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
1609 blit
.scissor_enable
= FALSE
;
1610 blit
.alpha_blend
= FALSE
;
1612 /* If both of a src and dst dimension are negative, flip them. */
1613 if (blit
.dst
.box
.width
< 0 && blit
.src
.box
.width
< 0) {
1614 blit
.dst
.box
.width
= -blit
.dst
.box
.width
;
1615 blit
.src
.box
.width
= -blit
.src
.box
.width
;
1617 if (blit
.dst
.box
.height
< 0 && blit
.src
.box
.height
< 0) {
1618 blit
.dst
.box
.height
= -blit
.dst
.box
.height
;
1619 blit
.src
.box
.height
= -blit
.src
.box
.height
;
1622 blit
.dst
.box
.width
!= blit
.src
.box
.width
||
1623 blit
.dst
.box
.height
!= blit
.src
.box
.height
;
1625 user_assert(!scaled
|| dst
!= src
, D3DERR_INVALIDCALL
);
1626 user_assert(!scaled
||
1627 !NineSurface9_IsOffscreenPlain(dst
), D3DERR_INVALIDCALL
);
1628 user_assert(!NineSurface9_IsOffscreenPlain(dst
) ||
1629 NineSurface9_IsOffscreenPlain(src
), D3DERR_INVALIDCALL
);
1630 user_assert(NineSurface9_IsOffscreenPlain(dst
) ||
1631 dst
->desc
.Usage
& (D3DUSAGE_RENDERTARGET
| D3DUSAGE_DEPTHSTENCIL
),
1632 D3DERR_INVALIDCALL
);
1633 user_assert(!scaled
||
1634 (!util_format_is_compressed(dst
->base
.info
.format
) &&
1635 !util_format_is_compressed(src
->base
.info
.format
)),
1636 D3DERR_INVALIDCALL
);
1638 user_warn(src
== dst
&&
1639 u_box_test_intersection_2d(&blit
.src
.box
, &blit
.dst
.box
));
1641 /* Check for clipping/clamping: */
1643 struct pipe_box box
;
1646 xy
= u_box_clip_2d(&box
, &blit
.dst
.box
,
1647 dst
->desc
.Width
, dst
->desc
.Height
);
1651 xy
= u_box_clip_2d(&box
, &blit
.src
.box
,
1652 src
->desc
.Width
, src
->desc
.Height
);
1656 ms
= (dst
->desc
.MultiSampleType
| 1) != (src
->desc
.MultiSampleType
| 1);
1658 if (clamped
|| scaled
|| (blit
.dst
.format
!= blit
.src
.format
) || ms
) {
1659 DBG("using pipe->blit()\n");
1660 /* TODO: software scaling */
1661 user_assert(screen
->is_format_supported(screen
, dst_res
->format
,
1663 dst_res
->nr_samples
,
1664 zs
? PIPE_BIND_DEPTH_STENCIL
:
1665 PIPE_BIND_RENDER_TARGET
),
1666 D3DERR_INVALIDCALL
);
1668 pipe
->blit(pipe
, &blit
);
1670 assert(blit
.dst
.box
.x
>= 0 && blit
.dst
.box
.y
>= 0 &&
1671 blit
.src
.box
.x
>= 0 && blit
.src
.box
.y
>= 0 &&
1672 blit
.dst
.box
.x
+ blit
.dst
.box
.width
<= dst
->desc
.Width
&&
1673 blit
.src
.box
.x
+ blit
.src
.box
.width
<= src
->desc
.Width
&&
1674 blit
.dst
.box
.y
+ blit
.dst
.box
.height
<= dst
->desc
.Height
&&
1675 blit
.src
.box
.y
+ blit
.src
.box
.height
<= src
->desc
.Height
);
1676 /* Or drivers might crash ... */
1677 DBG("Using resource_copy_region.\n");
1678 pipe
->resource_copy_region(pipe
,
1679 blit
.dst
.resource
, blit
.dst
.level
,
1680 blit
.dst
.box
.x
, blit
.dst
.box
.y
, blit
.dst
.box
.z
,
1681 blit
.src
.resource
, blit
.src
.level
,
1685 /* Communicate the container it needs to update sublevels - if apply */
1686 NineSurface9_MarkContainerDirty(dst
);
1692 NineDevice9_ColorFill( struct NineDevice9
*This
,
1693 IDirect3DSurface9
*pSurface
,
1697 struct pipe_context
*pipe
= This
->pipe
;
1698 struct NineSurface9
*surf
= NineSurface9(pSurface
);
1699 struct pipe_surface
*psurf
;
1700 unsigned x
, y
, w
, h
;
1701 union pipe_color_union rgba
;
1704 DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This
,
1705 pSurface
, pRect
, color
);
1707 DBG("pRect=(%u,%u)-(%u,%u)\n", pRect
->left
, pRect
->top
,
1708 pRect
->right
, pRect
->bottom
);
1710 user_assert(surf
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1712 user_assert((surf
->base
.usage
& D3DUSAGE_RENDERTARGET
) ||
1713 NineSurface9_IsOffscreenPlain(surf
), D3DERR_INVALIDCALL
);
1715 user_assert(surf
->desc
.Format
!= D3DFMT_NULL
, D3D_OK
);
1720 w
= pRect
->right
- pRect
->left
;
1721 h
= pRect
->bottom
- pRect
->top
;
1723 if (compressed_format(surf
->desc
.Format
)) {
1724 const unsigned bw
= util_format_get_blockwidth(surf
->base
.info
.format
);
1725 const unsigned bh
= util_format_get_blockheight(surf
->base
.info
.format
);
1727 user_assert(!(x
% bw
) && !(y
% bh
) && !(w
% bw
) && !(h
% bh
),
1728 D3DERR_INVALIDCALL
);
1733 w
= surf
->desc
.Width
;
1734 h
= surf
->desc
.Height
;
1736 d3dcolor_to_pipe_color_union(&rgba
, color
);
1738 fallback
= !(surf
->base
.info
.bind
& PIPE_BIND_RENDER_TARGET
);
1741 psurf
= NineSurface9_GetSurface(surf
, 0);
1747 pipe
->clear_render_target(pipe
, psurf
, &rgba
, x
, y
, w
, h
, false);
1749 D3DLOCKED_RECT lock
;
1750 union util_color uc
;
1752 /* XXX: lock pRect and fix util_fill_rect */
1753 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, 0);
1756 util_pack_color_ub(color
>> 16, color
>> 8, color
>> 0, color
>> 24,
1757 surf
->base
.info
.format
, &uc
);
1758 util_fill_rect(lock
.pBits
, surf
->base
.info
.format
,lock
.Pitch
,
1760 NineSurface9_UnlockRect(surf
);
1767 NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9
*This
,
1772 IDirect3DSurface9
**ppSurface
,
1773 HANDLE
*pSharedHandle
)
1777 DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
1778 "ppSurface=%p pSharedHandle=%p\n", This
,
1779 Width
, Height
, d3dformat_to_string(Format
), Format
, Pool
,
1780 ppSurface
, pSharedHandle
);
1783 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
1784 || Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1785 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1787 /* Can be used with StretchRect and ColorFill. It's also always lockable.
1789 hr
= create_zs_or_rt_surface(This
, 2, Pool
, Width
, Height
,
1791 D3DMULTISAMPLE_NONE
, 0,
1793 ppSurface
, pSharedHandle
);
1795 DBG("Failed to create surface.\n");
1800 NineDevice9_SetRenderTarget( struct NineDevice9
*This
,
1801 DWORD RenderTargetIndex
,
1802 IDirect3DSurface9
*pRenderTarget
)
1804 struct NineSurface9
*rt
= NineSurface9(pRenderTarget
);
1805 const unsigned i
= RenderTargetIndex
;
1807 DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This
,
1808 RenderTargetIndex
, pRenderTarget
);
1810 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1811 user_assert(i
!= 0 || pRenderTarget
, D3DERR_INVALIDCALL
);
1812 user_assert(!pRenderTarget
||
1813 rt
->desc
.Usage
& D3DUSAGE_RENDERTARGET
, D3DERR_INVALIDCALL
);
1816 This
->state
.viewport
.X
= 0;
1817 This
->state
.viewport
.Y
= 0;
1818 This
->state
.viewport
.Width
= rt
->desc
.Width
;
1819 This
->state
.viewport
.Height
= rt
->desc
.Height
;
1820 This
->state
.viewport
.MinZ
= 0.0f
;
1821 This
->state
.viewport
.MaxZ
= 1.0f
;
1823 This
->state
.scissor
.minx
= 0;
1824 This
->state
.scissor
.miny
= 0;
1825 This
->state
.scissor
.maxx
= rt
->desc
.Width
;
1826 This
->state
.scissor
.maxy
= rt
->desc
.Height
;
1828 This
->state
.changed
.group
|= NINE_STATE_VIEWPORT
| NINE_STATE_SCISSOR
| NINE_STATE_MULTISAMPLE
;
1831 if (This
->state
.rt
[i
] != NineSurface9(pRenderTarget
)) {
1832 nine_bind(&This
->state
.rt
[i
], pRenderTarget
);
1833 This
->state
.changed
.group
|= NINE_STATE_FB
;
1839 NineDevice9_GetRenderTarget( struct NineDevice9
*This
,
1840 DWORD RenderTargetIndex
,
1841 IDirect3DSurface9
**ppRenderTarget
)
1843 const unsigned i
= RenderTargetIndex
;
1845 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1846 user_assert(ppRenderTarget
, D3DERR_INVALIDCALL
);
1848 *ppRenderTarget
= (IDirect3DSurface9
*)This
->state
.rt
[i
];
1849 if (!This
->state
.rt
[i
])
1850 return D3DERR_NOTFOUND
;
1852 NineUnknown_AddRef(NineUnknown(This
->state
.rt
[i
]));
1857 NineDevice9_SetDepthStencilSurface( struct NineDevice9
*This
,
1858 IDirect3DSurface9
*pNewZStencil
)
1860 DBG("This=%p pNewZStencil=%p\n", This
, pNewZStencil
);
1862 if (This
->state
.ds
!= NineSurface9(pNewZStencil
)) {
1863 nine_bind(&This
->state
.ds
, pNewZStencil
);
1864 This
->state
.changed
.group
|= NINE_STATE_FB
;
1870 NineDevice9_GetDepthStencilSurface( struct NineDevice9
*This
,
1871 IDirect3DSurface9
**ppZStencilSurface
)
1873 user_assert(ppZStencilSurface
, D3DERR_INVALIDCALL
);
1875 *ppZStencilSurface
= (IDirect3DSurface9
*)This
->state
.ds
;
1876 if (!This
->state
.ds
)
1877 return D3DERR_NOTFOUND
;
1879 NineUnknown_AddRef(NineUnknown(This
->state
.ds
));
1884 NineDevice9_BeginScene( struct NineDevice9
*This
)
1886 DBG("This=%p\n", This
);
1887 user_assert(!This
->in_scene
, D3DERR_INVALIDCALL
);
1888 This
->in_scene
= TRUE
;
1889 /* Do we want to do anything else here ? */
1894 NineDevice9_EndScene( struct NineDevice9
*This
)
1896 DBG("This=%p\n", This
);
1897 user_assert(This
->in_scene
, D3DERR_INVALIDCALL
);
1898 This
->in_scene
= FALSE
;
1903 NineDevice9_Clear( struct NineDevice9
*This
,
1905 const D3DRECT
*pRects
,
1911 const int sRGB
= This
->state
.rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
1912 struct pipe_surface
*cbuf
, *zsbuf
;
1913 struct pipe_context
*pipe
= This
->pipe
;
1914 struct NineSurface9
*zsbuf_surf
= This
->state
.ds
;
1915 struct NineSurface9
*rt
;
1918 union pipe_color_union rgba
;
1919 unsigned rt_mask
= 0;
1922 DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
1923 This
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
1925 user_assert(This
->state
.ds
|| !(Flags
& NINED3DCLEAR_DEPTHSTENCIL
),
1926 D3DERR_INVALIDCALL
);
1927 user_assert(!(Flags
& D3DCLEAR_STENCIL
) ||
1929 util_format_is_depth_and_stencil(zsbuf_surf
->base
.info
.format
)),
1930 D3DERR_INVALIDCALL
);
1932 user_assert((Count
&& pRects
) || (!Count
&& !pRects
), D3DERR_INVALIDCALL
);
1934 user_warn((pRects
&& !Count
) || (!pRects
&& Count
));
1935 if (pRects
&& !Count
)
1941 nine_update_state_framebuffer_clear(This
);
1943 if (Flags
& D3DCLEAR_TARGET
) bufs
|= PIPE_CLEAR_COLOR
;
1944 /* Ignore Z buffer if not bound */
1945 if (This
->state
.fb
.zsbuf
!= NULL
) {
1946 if (Flags
& D3DCLEAR_ZBUFFER
) bufs
|= PIPE_CLEAR_DEPTH
;
1947 if (Flags
& D3DCLEAR_STENCIL
) bufs
|= PIPE_CLEAR_STENCIL
;
1951 d3dcolor_to_pipe_color_union(&rgba
, Color
);
1953 rect
.x1
= This
->state
.viewport
.X
;
1954 rect
.y1
= This
->state
.viewport
.Y
;
1955 rect
.x2
= This
->state
.viewport
.Width
+ rect
.x1
;
1956 rect
.y2
= This
->state
.viewport
.Height
+ rect
.y1
;
1958 /* Both rectangles apply, which is weird, but that's D3D9. */
1959 if (This
->state
.rs
[D3DRS_SCISSORTESTENABLE
]) {
1960 rect
.x1
= MAX2(rect
.x1
, This
->state
.scissor
.minx
);
1961 rect
.y1
= MAX2(rect
.y1
, This
->state
.scissor
.miny
);
1962 rect
.x2
= MIN2(rect
.x2
, This
->state
.scissor
.maxx
);
1963 rect
.y2
= MIN2(rect
.y2
, This
->state
.scissor
.maxy
);
1967 /* Maybe apps like to specify a large rect ? */
1968 if (pRects
[0].x1
<= rect
.x1
&& pRects
[0].x2
>= rect
.x2
&&
1969 pRects
[0].y1
<= rect
.y1
&& pRects
[0].y2
>= rect
.y2
) {
1970 DBG("First rect covers viewport.\n");
1976 if (rect
.x1
>= This
->state
.fb
.width
|| rect
.y1
>= This
->state
.fb
.height
)
1979 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
1980 if (This
->state
.rt
[i
] && This
->state
.rt
[i
]->desc
.Format
!= D3DFMT_NULL
)
1984 /* fast path, clears everything at once */
1986 (!(bufs
& PIPE_CLEAR_COLOR
) || (rt_mask
== This
->state
.rt_mask
)) &&
1987 rect
.x1
== 0 && rect
.y1
== 0 &&
1988 /* Case we clear only render target. Check clear region vs rt. */
1989 ((!(bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
1990 rect
.x2
>= This
->state
.fb
.width
&&
1991 rect
.y2
>= This
->state
.fb
.height
) ||
1992 /* Case we clear depth buffer (and eventually rt too).
1993 * depth buffer size is always >= rt size. Compare to clear region */
1994 ((bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
1995 rect
.x2
>= zsbuf_surf
->desc
.Width
&&
1996 rect
.y2
>= zsbuf_surf
->desc
.Height
))) {
1997 DBG("Clear fast path\n");
1998 pipe
->clear(pipe
, bufs
, &rgba
, Z
, Stencil
);
2007 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2008 rt
= This
->state
.rt
[i
];
2009 if (!rt
|| rt
->desc
.Format
== D3DFMT_NULL
||
2010 !(bufs
& PIPE_CLEAR_COLOR
))
2011 continue; /* save space, compiler should hoist this */
2012 cbuf
= NineSurface9_GetSurface(rt
, sRGB
);
2013 for (r
= 0; r
< Count
; ++r
) {
2014 /* Don't trust users to pass these in the right order. */
2015 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2016 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2017 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2018 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2020 /* Drop negative rectangles (like wine expects). */
2021 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2022 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2025 x1
= MAX2(x1
, rect
.x1
);
2026 y1
= MAX2(y1
, rect
.y1
);
2027 x2
= MIN3(x2
, rect
.x2
, rt
->desc
.Width
);
2028 y2
= MIN3(y2
, rect
.y2
, rt
->desc
.Height
);
2030 DBG("Clearing (%u..%u)x(%u..%u)\n", x1
, x2
, y1
, y2
);
2031 pipe
->clear_render_target(pipe
, cbuf
, &rgba
,
2032 x1
, y1
, x2
- x1
, y2
- y1
, false);
2035 if (!(bufs
& PIPE_CLEAR_DEPTHSTENCIL
))
2038 bufs
&= PIPE_CLEAR_DEPTHSTENCIL
;
2040 for (r
= 0; r
< Count
; ++r
) {
2041 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2042 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2043 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2044 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2046 /* Drop negative rectangles. */
2047 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2048 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2051 x1
= MIN2(x1
, rect
.x1
);
2052 y1
= MIN2(y1
, rect
.y1
);
2053 x2
= MIN3(x2
, rect
.x2
, zsbuf_surf
->desc
.Width
);
2054 y2
= MIN3(y2
, rect
.y2
, zsbuf_surf
->desc
.Height
);
2056 zsbuf
= NineSurface9_GetSurface(zsbuf_surf
, 0);
2058 pipe
->clear_depth_stencil(pipe
, zsbuf
, bufs
, Z
, Stencil
,
2059 x1
, y1
, x2
- x1
, y2
- y1
, false);
2065 NineDevice9_SetTransform( struct NineDevice9
*This
,
2066 D3DTRANSFORMSTATETYPE State
,
2067 const D3DMATRIX
*pMatrix
)
2069 struct nine_state
*state
= This
->update
;
2070 D3DMATRIX
*M
= nine_state_access_transform(state
, State
, TRUE
);
2072 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2074 user_assert(M
, D3DERR_INVALIDCALL
);
2077 state
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
2078 state
->changed
.group
|= NINE_STATE_FF
;
2084 NineDevice9_GetTransform( struct NineDevice9
*This
,
2085 D3DTRANSFORMSTATETYPE State
,
2086 D3DMATRIX
*pMatrix
)
2088 D3DMATRIX
*M
= nine_state_access_transform(&This
->state
, State
, FALSE
);
2089 user_assert(M
, D3DERR_INVALIDCALL
);
2095 NineDevice9_MultiplyTransform( struct NineDevice9
*This
,
2096 D3DTRANSFORMSTATETYPE State
,
2097 const D3DMATRIX
*pMatrix
)
2099 struct nine_state
*state
= This
->update
;
2101 D3DMATRIX
*M
= nine_state_access_transform(state
, State
, TRUE
);
2103 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2105 user_assert(M
, D3DERR_INVALIDCALL
);
2107 nine_d3d_matrix_matrix_mul(&T
, pMatrix
, M
);
2108 return NineDevice9_SetTransform(This
, State
, &T
);
2112 NineDevice9_SetViewport( struct NineDevice9
*This
,
2113 const D3DVIEWPORT9
*pViewport
)
2115 struct nine_state
*state
= This
->update
;
2117 DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
2118 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
,
2119 pViewport
->MinZ
, pViewport
->MaxZ
);
2121 state
->viewport
= *pViewport
;
2122 state
->changed
.group
|= NINE_STATE_VIEWPORT
;
2128 NineDevice9_GetViewport( struct NineDevice9
*This
,
2129 D3DVIEWPORT9
*pViewport
)
2131 *pViewport
= This
->state
.viewport
;
2136 NineDevice9_SetMaterial( struct NineDevice9
*This
,
2137 const D3DMATERIAL9
*pMaterial
)
2139 struct nine_state
*state
= This
->update
;
2141 DBG("This=%p pMaterial=%p\n", This
, pMaterial
);
2143 nine_dump_D3DMATERIAL9(DBG_FF
, pMaterial
);
2145 user_assert(pMaterial
, E_POINTER
);
2147 state
->ff
.material
= *pMaterial
;
2148 state
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
2154 NineDevice9_GetMaterial( struct NineDevice9
*This
,
2155 D3DMATERIAL9
*pMaterial
)
2157 user_assert(pMaterial
, E_POINTER
);
2158 *pMaterial
= This
->state
.ff
.material
;
2163 NineDevice9_SetLight( struct NineDevice9
*This
,
2165 const D3DLIGHT9
*pLight
)
2167 struct nine_state
*state
= This
->update
;
2169 DBG("This=%p Index=%u pLight=%p\n", This
, Index
, pLight
);
2171 nine_dump_D3DLIGHT9(DBG_FF
, pLight
);
2173 user_assert(pLight
, D3DERR_INVALIDCALL
);
2174 user_assert(pLight
->Type
< NINED3DLIGHT_INVALID
, D3DERR_INVALIDCALL
);
2176 user_assert(Index
< NINE_MAX_LIGHTS
, D3DERR_INVALIDCALL
); /* sanity */
2178 if (Index
>= state
->ff
.num_lights
) {
2179 unsigned n
= state
->ff
.num_lights
;
2180 unsigned N
= Index
+ 1;
2182 state
->ff
.light
= REALLOC(state
->ff
.light
, n
* sizeof(D3DLIGHT9
),
2183 N
* sizeof(D3DLIGHT9
));
2184 if (!state
->ff
.light
)
2185 return E_OUTOFMEMORY
;
2186 state
->ff
.num_lights
= N
;
2188 for (; n
< Index
; ++n
) {
2189 memset(&state
->ff
.light
[n
], 0, sizeof(D3DLIGHT9
));
2190 state
->ff
.light
[n
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
2193 state
->ff
.light
[Index
] = *pLight
;
2195 if (pLight
->Type
== D3DLIGHT_SPOT
&& pLight
->Theta
>= pLight
->Phi
) {
2196 DBG("Warning: clamping D3DLIGHT9.Theta\n");
2197 state
->ff
.light
[Index
].Theta
= state
->ff
.light
[Index
].Phi
;
2199 if (pLight
->Type
!= D3DLIGHT_DIRECTIONAL
&&
2200 pLight
->Attenuation0
== 0.0f
&&
2201 pLight
->Attenuation1
== 0.0f
&&
2202 pLight
->Attenuation2
== 0.0f
) {
2203 DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
2206 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2212 NineDevice9_GetLight( struct NineDevice9
*This
,
2216 const struct nine_state
*state
= &This
->state
;
2218 user_assert(pLight
, D3DERR_INVALIDCALL
);
2219 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2220 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2221 D3DERR_INVALIDCALL
);
2223 *pLight
= state
->ff
.light
[Index
];
2229 NineDevice9_LightEnable( struct NineDevice9
*This
,
2233 struct nine_state
*state
= This
->update
;
2236 DBG("This=%p Index=%u Enable=%i\n", This
, Index
, Enable
);
2238 if (Index
>= state
->ff
.num_lights
||
2239 state
->ff
.light
[Index
].Type
== NINED3DLIGHT_INVALID
) {
2240 /* This should create a default light. */
2242 memset(&light
, 0, sizeof(light
));
2243 light
.Type
= D3DLIGHT_DIRECTIONAL
;
2244 light
.Diffuse
.r
= 1.0f
;
2245 light
.Diffuse
.g
= 1.0f
;
2246 light
.Diffuse
.b
= 1.0f
;
2247 light
.Direction
.z
= 1.0f
;
2248 NineDevice9_SetLight(This
, Index
, &light
);
2250 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2252 for (i
= 0; i
< state
->ff
.num_lights_active
; ++i
) {
2253 if (state
->ff
.active_light
[i
] == Index
)
2258 if (i
< state
->ff
.num_lights_active
)
2260 /* XXX wine thinks this should still succeed:
2262 user_assert(i
< NINE_MAX_LIGHTS_ACTIVE
, D3DERR_INVALIDCALL
);
2264 state
->ff
.active_light
[i
] = Index
;
2265 state
->ff
.num_lights_active
++;
2267 if (i
== state
->ff
.num_lights_active
)
2269 --state
->ff
.num_lights_active
;
2270 for (; i
< state
->ff
.num_lights_active
; ++i
)
2271 state
->ff
.active_light
[i
] = state
->ff
.active_light
[i
+ 1];
2273 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2279 NineDevice9_GetLightEnable( struct NineDevice9
*This
,
2283 const struct nine_state
*state
= &This
->state
;
2286 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2287 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2288 D3DERR_INVALIDCALL
);
2290 for (i
= 0; i
< state
->ff
.num_lights_active
; ++i
)
2291 if (state
->ff
.active_light
[i
] == Index
)
2294 *pEnable
= i
!= state
->ff
.num_lights_active
? 128 : 0; // Taken from wine
2300 NineDevice9_SetClipPlane( struct NineDevice9
*This
,
2302 const float *pPlane
)
2304 struct nine_state
*state
= This
->update
;
2306 user_assert(pPlane
, D3DERR_INVALIDCALL
);
2308 DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This
, Index
,
2309 pPlane
[0], pPlane
[1],
2310 pPlane
[2], pPlane
[3]);
2312 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2314 memcpy(&state
->clip
.ucp
[Index
][0], pPlane
, sizeof(state
->clip
.ucp
[0]));
2315 state
->changed
.ucp
|= 1 << Index
;
2321 NineDevice9_GetClipPlane( struct NineDevice9
*This
,
2325 const struct nine_state
*state
= &This
->state
;
2327 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2329 memcpy(pPlane
, &state
->clip
.ucp
[Index
][0], sizeof(state
->clip
.ucp
[0]));
2333 #define RESZ_CODE 0x7fa05000
2336 NineDevice9_ResolveZ( struct NineDevice9
*This
)
2338 struct nine_state
*state
= &This
->state
;
2339 const struct util_format_description
*desc
;
2340 struct NineSurface9
*source
= state
->ds
;
2341 struct NineBaseTexture9
*destination
= state
->texture
[0];
2342 struct pipe_resource
*src
, *dst
;
2343 struct pipe_blit_info blit
;
2345 DBG("RESZ resolve\n");
2347 user_assert(source
&& destination
&&
2348 destination
->base
.type
== D3DRTYPE_TEXTURE
, D3DERR_INVALIDCALL
);
2350 src
= source
->base
.resource
;
2351 dst
= destination
->base
.resource
;
2353 user_assert(src
&& dst
, D3DERR_INVALIDCALL
);
2355 /* check dst is depth format. we know already for src */
2356 desc
= util_format_description(dst
->format
);
2357 user_assert(desc
->colorspace
== UTIL_FORMAT_COLORSPACE_ZS
, D3DERR_INVALIDCALL
);
2359 memset(&blit
, 0, sizeof(blit
));
2360 blit
.src
.resource
= src
;
2362 blit
.src
.format
= src
->format
;
2364 blit
.src
.box
.depth
= 1;
2367 blit
.src
.box
.width
= src
->width0
;
2368 blit
.src
.box
.height
= src
->height0
;
2370 blit
.dst
.resource
= dst
;
2372 blit
.dst
.format
= dst
->format
;
2374 blit
.dst
.box
.depth
= 1;
2377 blit
.dst
.box
.width
= dst
->width0
;
2378 blit
.dst
.box
.height
= dst
->height0
;
2380 blit
.mask
= PIPE_MASK_ZS
;
2381 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
2382 blit
.scissor_enable
= FALSE
;
2384 This
->pipe
->blit(This
->pipe
, &blit
);
2388 #define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1')
2389 #define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0')
2392 NineDevice9_SetRenderState( struct NineDevice9
*This
,
2393 D3DRENDERSTATETYPE State
,
2396 struct nine_state
*state
= This
->update
;
2398 DBG("This=%p State=%u(%s) Value=%08x\n", This
,
2399 State
, nine_d3drs_to_string(State
), Value
);
2401 user_assert(State
< D3DRS_COUNT
, D3DERR_INVALIDCALL
);
2403 if (state
->rs_advertised
[State
] == Value
&& likely(!This
->is_recording
))
2406 state
->rs_advertised
[State
] = Value
;
2408 /* Amd hacks (equivalent to GL extensions) */
2409 if (unlikely(State
== D3DRS_POINTSIZE
)) {
2410 if (Value
== RESZ_CODE
)
2411 return NineDevice9_ResolveZ(This
);
2413 if (Value
== ALPHA_TO_COVERAGE_ENABLE
||
2414 Value
== ALPHA_TO_COVERAGE_DISABLE
) {
2415 state
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== ALPHA_TO_COVERAGE_ENABLE
);
2416 state
->changed
.group
|= NINE_STATE_BLEND
;
2422 if (unlikely(State
== D3DRS_ADAPTIVETESS_Y
)) {
2423 if (Value
== D3DFMT_ATOC
|| (Value
== D3DFMT_UNKNOWN
&& state
->rs
[NINED3DRS_ALPHACOVERAGE
])) {
2424 state
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== D3DFMT_ATOC
) ? 3 : 0;
2425 state
->rs
[NINED3DRS_ALPHACOVERAGE
] &= state
->rs
[D3DRS_ALPHATESTENABLE
] ? 3 : 2;
2426 state
->changed
.group
|= NINE_STATE_BLEND
;
2430 if (unlikely(State
== D3DRS_ALPHATESTENABLE
&& (state
->rs
[NINED3DRS_ALPHACOVERAGE
] & 2))) {
2431 DWORD alphacoverage_prev
= state
->rs
[NINED3DRS_ALPHACOVERAGE
];
2432 state
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
? 3 : 2);
2433 if (state
->rs
[NINED3DRS_ALPHACOVERAGE
] != alphacoverage_prev
)
2434 state
->changed
.group
|= NINE_STATE_BLEND
;
2437 state
->rs
[State
] = nine_fix_render_state_value(State
, Value
);
2438 state
->changed
.rs
[State
/ 32] |= 1 << (State
% 32);
2439 state
->changed
.group
|= nine_render_state_group
[State
];
2445 NineDevice9_GetRenderState( struct NineDevice9
*This
,
2446 D3DRENDERSTATETYPE State
,
2449 user_assert(State
< D3DRS_COUNT
, D3DERR_INVALIDCALL
);
2451 *pValue
= This
->state
.rs_advertised
[State
];
2456 NineDevice9_CreateStateBlock( struct NineDevice9
*This
,
2457 D3DSTATEBLOCKTYPE Type
,
2458 IDirect3DStateBlock9
**ppSB
)
2460 struct NineStateBlock9
*nsb
;
2461 struct nine_state
*dst
;
2463 enum nine_stateblock_type type
;
2466 DBG("This=%p Type=%u ppSB=%p\n", This
, Type
, ppSB
);
2468 user_assert(Type
== D3DSBT_ALL
||
2469 Type
== D3DSBT_VERTEXSTATE
||
2470 Type
== D3DSBT_PIXELSTATE
, D3DERR_INVALIDCALL
);
2473 case D3DSBT_VERTEXSTATE
: type
= NINESBT_VERTEXSTATE
; break;
2474 case D3DSBT_PIXELSTATE
: type
= NINESBT_PIXELSTATE
; break;
2480 hr
= NineStateBlock9_new(This
, &nsb
, type
);
2483 *ppSB
= (IDirect3DStateBlock9
*)nsb
;
2486 dst
->changed
.group
=
2487 NINE_STATE_TEXTURE
|
2490 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_VERTEXSTATE
) {
2491 dst
->changed
.group
|=
2492 NINE_STATE_FF_LIGHTING
|
2493 NINE_STATE_VS
| NINE_STATE_VS_CONST
|
2495 /* TODO: texture/sampler state */
2496 memcpy(dst
->changed
.rs
,
2497 nine_render_states_vertex
, sizeof(dst
->changed
.rs
));
2498 nine_ranges_insert(&dst
->changed
.vs_const_f
, 0, This
->may_swvp
? NINE_MAX_CONST_F_SWVP
: This
->max_vs_const_f
,
2500 nine_ranges_insert(&dst
->changed
.vs_const_i
, 0, This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
,
2502 nine_ranges_insert(&dst
->changed
.vs_const_b
, 0, This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
,
2504 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2505 dst
->changed
.sampler
[s
] |= 1 << D3DSAMP_DMAPOFFSET
;
2506 if (This
->state
.ff
.num_lights
) {
2507 dst
->ff
.num_lights
= This
->state
.ff
.num_lights
;
2508 /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
2509 * all currently existing lights will be captured
2511 dst
->ff
.light
= CALLOC(This
->state
.ff
.num_lights
,
2513 if (!dst
->ff
.light
) {
2514 nine_bind(ppSB
, NULL
);
2515 return E_OUTOFMEMORY
;
2519 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_PIXELSTATE
) {
2520 dst
->changed
.group
|=
2521 NINE_STATE_PS
| NINE_STATE_PS_CONST
;
2522 /* TODO: texture/sampler state */
2523 memcpy(dst
->changed
.rs
,
2524 nine_render_states_pixel
, sizeof(dst
->changed
.rs
));
2525 nine_ranges_insert(&dst
->changed
.ps_const_f
, 0, This
->max_ps_const_f
,
2527 dst
->changed
.ps_const_i
= 0xffff;
2528 dst
->changed
.ps_const_b
= 0xffff;
2529 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2530 dst
->changed
.sampler
[s
] |= 0x1ffe;
2532 if (Type
== D3DSBT_ALL
) {
2533 dst
->changed
.group
|=
2534 NINE_STATE_VIEWPORT
|
2535 NINE_STATE_SCISSOR
|
2536 NINE_STATE_RASTERIZER
|
2540 NINE_STATE_MATERIAL
|
2541 NINE_STATE_BLEND_COLOR
|
2542 NINE_STATE_SAMPLE_MASK
;
2543 memset(dst
->changed
.rs
, ~0, (D3DRS_COUNT
/ 32) * sizeof(uint32_t));
2544 dst
->changed
.rs
[D3DRS_LAST
/ 32] |= (1 << (D3DRS_COUNT
% 32)) - 1;
2545 dst
->changed
.vtxbuf
= (1ULL << This
->caps
.MaxStreams
) - 1;
2546 dst
->changed
.stream_freq
= dst
->changed
.vtxbuf
;
2547 dst
->changed
.ucp
= (1 << PIPE_MAX_CLIP_PLANES
) - 1;
2548 dst
->changed
.texture
= (1 << NINE_MAX_SAMPLERS
) - 1;
2550 NineStateBlock9_Capture(NineStateBlock9(*ppSB
));
2552 /* TODO: fixed function state */
2558 NineDevice9_BeginStateBlock( struct NineDevice9
*This
)
2562 DBG("This=%p\n", This
);
2564 user_assert(!This
->record
, D3DERR_INVALIDCALL
);
2566 hr
= NineStateBlock9_new(This
, &This
->record
, NINESBT_CUSTOM
);
2569 NineUnknown_ConvertRefToBind(NineUnknown(This
->record
));
2571 This
->update
= &This
->record
->state
;
2572 This
->is_recording
= TRUE
;
2578 NineDevice9_EndStateBlock( struct NineDevice9
*This
,
2579 IDirect3DStateBlock9
**ppSB
)
2581 DBG("This=%p ppSB=%p\n", This
, ppSB
);
2583 user_assert(This
->record
, D3DERR_INVALIDCALL
);
2585 This
->update
= &This
->state
;
2586 This
->is_recording
= FALSE
;
2588 NineUnknown_AddRef(NineUnknown(This
->record
));
2589 *ppSB
= (IDirect3DStateBlock9
*)This
->record
;
2590 NineUnknown_Unbind(NineUnknown(This
->record
));
2591 This
->record
= NULL
;
2597 NineDevice9_SetClipStatus( struct NineDevice9
*This
,
2598 const D3DCLIPSTATUS9
*pClipStatus
)
2600 STUB(D3DERR_INVALIDCALL
);
2604 NineDevice9_GetClipStatus( struct NineDevice9
*This
,
2605 D3DCLIPSTATUS9
*pClipStatus
)
2607 STUB(D3DERR_INVALIDCALL
);
2611 NineDevice9_GetTexture( struct NineDevice9
*This
,
2613 IDirect3DBaseTexture9
**ppTexture
)
2615 user_assert(Stage
< This
->caps
.MaxSimultaneousTextures
||
2616 Stage
== D3DDMAPSAMPLER
||
2617 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2618 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2619 user_assert(ppTexture
, D3DERR_INVALIDCALL
);
2621 if (Stage
>= D3DDMAPSAMPLER
)
2622 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2624 *ppTexture
= (IDirect3DBaseTexture9
*)This
->state
.texture
[Stage
];
2626 if (This
->state
.texture
[Stage
])
2627 NineUnknown_AddRef(NineUnknown(This
->state
.texture
[Stage
]));
2632 NineDevice9_SetTexture( struct NineDevice9
*This
,
2634 IDirect3DBaseTexture9
*pTexture
)
2636 struct nine_state
*state
= This
->update
;
2637 struct NineBaseTexture9
*tex
= NineBaseTexture9(pTexture
);
2639 DBG("This=%p Stage=%u pTexture=%p\n", This
, Stage
, pTexture
);
2641 user_assert(Stage
< This
->caps
.MaxSimultaneousTextures
||
2642 Stage
== D3DDMAPSAMPLER
||
2643 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2644 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2645 user_assert(!tex
|| (tex
->base
.pool
!= D3DPOOL_SCRATCH
&&
2646 tex
->base
.pool
!= D3DPOOL_SYSTEMMEM
), D3DERR_INVALIDCALL
);
2648 if (Stage
>= D3DDMAPSAMPLER
)
2649 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2651 if (!This
->is_recording
) {
2652 struct NineBaseTexture9
*old
= state
->texture
[Stage
];
2656 state
->samplers_shadow
&= ~(1 << Stage
);
2658 state
->samplers_shadow
|= tex
->shadow
<< Stage
;
2660 if ((tex
->managed
.dirty
| tex
->dirty_mip
) && LIST_IS_EMPTY(&tex
->list
))
2661 list_add(&tex
->list
, &This
->update_textures
);
2668 nine_bind(&state
->texture
[Stage
], pTexture
);
2670 state
->changed
.texture
|= 1 << Stage
;
2671 state
->changed
.group
|= NINE_STATE_TEXTURE
;
2677 NineDevice9_GetTextureStageState( struct NineDevice9
*This
,
2679 D3DTEXTURESTAGESTATETYPE Type
,
2682 const struct nine_state
*state
= &This
->state
;
2684 user_assert(Stage
< ARRAY_SIZE(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2685 user_assert(Type
< ARRAY_SIZE(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2687 *pValue
= state
->ff
.tex_stage
[Stage
][Type
];
2693 NineDevice9_SetTextureStageState( struct NineDevice9
*This
,
2695 D3DTEXTURESTAGESTATETYPE Type
,
2698 struct nine_state
*state
= This
->update
;
2699 int bumpmap_index
= -1;
2701 DBG("Stage=%u Type=%u Value=%08x\n", Stage
, Type
, Value
);
2702 nine_dump_D3DTSS_value(DBG_FF
, Type
, Value
);
2704 user_assert(Stage
< ARRAY_SIZE(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2705 user_assert(Type
< ARRAY_SIZE(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2707 state
->ff
.tex_stage
[Stage
][Type
] = Value
;
2709 case D3DTSS_BUMPENVMAT00
:
2710 bumpmap_index
= 4 * Stage
;
2712 case D3DTSS_BUMPENVMAT01
:
2713 bumpmap_index
= 4 * Stage
+ 1;
2715 case D3DTSS_BUMPENVMAT10
:
2716 bumpmap_index
= 4 * Stage
+ 2;
2718 case D3DTSS_BUMPENVMAT11
:
2719 bumpmap_index
= 4 * Stage
+ 3;
2721 case D3DTSS_BUMPENVLSCALE
:
2722 bumpmap_index
= 4 * 8 + 2 * Stage
;
2724 case D3DTSS_BUMPENVLOFFSET
:
2725 bumpmap_index
= 4 * 8 + 2 * Stage
+ 1;
2727 case D3DTSS_TEXTURETRANSFORMFLAGS
:
2728 state
->changed
.group
|= NINE_STATE_PS1X_SHADER
;
2734 if (bumpmap_index
>= 0) {
2735 state
->bumpmap_vars
[bumpmap_index
] = Value
;
2736 state
->changed
.group
|= NINE_STATE_PS_CONST
;
2739 state
->changed
.group
|= NINE_STATE_FF_PSSTAGES
;
2740 state
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
2746 NineDevice9_GetSamplerState( struct NineDevice9
*This
,
2748 D3DSAMPLERSTATETYPE Type
,
2751 user_assert(Sampler
< This
->caps
.MaxSimultaneousTextures
||
2752 Sampler
== D3DDMAPSAMPLER
||
2753 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2754 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2756 if (Sampler
>= D3DDMAPSAMPLER
)
2757 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2759 *pValue
= This
->state
.samp
[Sampler
][Type
];
2764 NineDevice9_SetSamplerState( struct NineDevice9
*This
,
2766 D3DSAMPLERSTATETYPE Type
,
2769 struct nine_state
*state
= This
->update
;
2771 DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This
,
2772 Sampler
, nine_D3DSAMP_to_str(Type
), Value
);
2774 user_assert(Sampler
< This
->caps
.MaxSimultaneousTextures
||
2775 Sampler
== D3DDMAPSAMPLER
||
2776 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2777 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2779 if (Sampler
>= D3DDMAPSAMPLER
)
2780 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2782 if (state
->samp
[Sampler
][Type
] != Value
|| unlikely(This
->is_recording
)) {
2783 state
->samp
[Sampler
][Type
] = Value
;
2784 state
->changed
.group
|= NINE_STATE_SAMPLER
;
2785 state
->changed
.sampler
[Sampler
] |= 1 << Type
;
2792 NineDevice9_ValidateDevice( struct NineDevice9
*This
,
2795 const struct nine_state
*state
= &This
->state
;
2797 unsigned w
= 0, h
= 0;
2799 DBG("This=%p pNumPasses=%p\n", This
, pNumPasses
);
2801 for (i
= 0; i
< ARRAY_SIZE(state
->samp
); ++i
) {
2802 if (state
->samp
[i
][D3DSAMP_MINFILTER
] == D3DTEXF_NONE
||
2803 state
->samp
[i
][D3DSAMP_MAGFILTER
] == D3DTEXF_NONE
)
2804 return D3DERR_UNSUPPORTEDTEXTUREFILTER
;
2807 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2811 w
= state
->rt
[i
]->desc
.Width
;
2812 h
= state
->rt
[i
]->desc
.Height
;
2814 if (state
->rt
[i
]->desc
.Width
!= w
|| state
->rt
[i
]->desc
.Height
!= h
) {
2815 return D3DERR_CONFLICTINGRENDERSTATE
;
2819 (state
->rs
[D3DRS_ZENABLE
] || state
->rs
[D3DRS_STENCILENABLE
])) {
2821 (state
->ds
->desc
.Width
!= w
|| state
->ds
->desc
.Height
!= h
))
2822 return D3DERR_CONFLICTINGRENDERSTATE
;
2832 NineDevice9_SetPaletteEntries( struct NineDevice9
*This
,
2834 const PALETTEENTRY
*pEntries
)
2836 STUB(D3D_OK
); /* like wine */
2840 NineDevice9_GetPaletteEntries( struct NineDevice9
*This
,
2842 PALETTEENTRY
*pEntries
)
2844 STUB(D3DERR_INVALIDCALL
);
2848 NineDevice9_SetCurrentTexturePalette( struct NineDevice9
*This
,
2849 UINT PaletteNumber
)
2851 STUB(D3D_OK
); /* like wine */
2855 NineDevice9_GetCurrentTexturePalette( struct NineDevice9
*This
,
2856 UINT
*PaletteNumber
)
2858 STUB(D3DERR_INVALIDCALL
);
2862 NineDevice9_SetScissorRect( struct NineDevice9
*This
,
2865 struct nine_state
*state
= This
->update
;
2867 DBG("x=(%u..%u) y=(%u..%u)\n",
2868 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
2870 state
->scissor
.minx
= pRect
->left
;
2871 state
->scissor
.miny
= pRect
->top
;
2872 state
->scissor
.maxx
= pRect
->right
;
2873 state
->scissor
.maxy
= pRect
->bottom
;
2875 state
->changed
.group
|= NINE_STATE_SCISSOR
;
2881 NineDevice9_GetScissorRect( struct NineDevice9
*This
,
2884 pRect
->left
= This
->state
.scissor
.minx
;
2885 pRect
->top
= This
->state
.scissor
.miny
;
2886 pRect
->right
= This
->state
.scissor
.maxx
;
2887 pRect
->bottom
= This
->state
.scissor
.maxy
;
2893 NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9
*This
,
2896 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
) {
2897 This
->swvp
= bSoftware
;
2898 This
->state
.changed
.group
|= NINE_STATE_SWVP
;
2901 return D3DERR_INVALIDCALL
; /* msdn. TODO: check in practice */
2905 NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9
*This
)
2911 NineDevice9_SetNPatchMode( struct NineDevice9
*This
,
2914 return D3D_OK
; /* Nothing to do because we don't advertise NPatch support */
2918 NineDevice9_GetNPatchMode( struct NineDevice9
*This
)
2924 init_draw_info(struct pipe_draw_info
*info
,
2925 struct NineDevice9
*dev
, D3DPRIMITIVETYPE type
, UINT count
)
2927 info
->mode
= d3dprimitivetype_to_pipe_prim(type
);
2928 info
->count
= prim_count_to_vertex_count(type
, count
);
2929 info
->start_instance
= 0;
2930 info
->instance_count
= 1;
2931 if (dev
->state
.stream_instancedata_mask
& dev
->state
.stream_usage_mask
)
2932 info
->instance_count
= MAX2(dev
->state
.stream_freq
[0] & 0x7FFFFF, 1);
2933 info
->primitive_restart
= FALSE
;
2934 info
->restart_index
= 0;
2935 info
->count_from_stream_output
= NULL
;
2936 info
->indirect
= NULL
;
2937 info
->indirect_params
= NULL
;
2941 NineDevice9_DrawPrimitive( struct NineDevice9
*This
,
2942 D3DPRIMITIVETYPE PrimitiveType
,
2944 UINT PrimitiveCount
)
2946 struct pipe_draw_info info
;
2948 DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
2949 This
, PrimitiveType
, StartVertex
, PrimitiveCount
);
2951 nine_update_state(This
);
2953 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
2954 info
.indexed
= FALSE
;
2955 info
.start
= StartVertex
;
2956 info
.index_bias
= 0;
2957 info
.min_index
= info
.start
;
2958 info
.max_index
= info
.count
- 1;
2960 This
->pipe
->draw_vbo(This
->pipe
, &info
);
2966 NineDevice9_DrawIndexedPrimitive( struct NineDevice9
*This
,
2967 D3DPRIMITIVETYPE PrimitiveType
,
2968 INT BaseVertexIndex
,
2969 UINT MinVertexIndex
,
2972 UINT PrimitiveCount
)
2974 struct pipe_draw_info info
;
2976 DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
2977 "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
2978 This
, PrimitiveType
, BaseVertexIndex
, MinVertexIndex
, NumVertices
,
2979 StartIndex
, PrimitiveCount
);
2981 user_assert(This
->state
.idxbuf
, D3DERR_INVALIDCALL
);
2982 user_assert(This
->state
.vdecl
, D3DERR_INVALIDCALL
);
2984 nine_update_state(This
);
2986 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
2987 info
.indexed
= TRUE
;
2988 info
.start
= StartIndex
;
2989 info
.index_bias
= BaseVertexIndex
;
2990 /* These don't include index bias: */
2991 info
.min_index
= MinVertexIndex
;
2992 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2994 This
->pipe
->draw_vbo(This
->pipe
, &info
);
3000 NineDevice9_DrawPrimitiveUP( struct NineDevice9
*This
,
3001 D3DPRIMITIVETYPE PrimitiveType
,
3002 UINT PrimitiveCount
,
3003 const void *pVertexStreamZeroData
,
3004 UINT VertexStreamZeroStride
)
3006 struct pipe_vertex_buffer vtxbuf
;
3007 struct pipe_draw_info info
;
3009 DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
3010 This
, PrimitiveType
, PrimitiveCount
,
3011 pVertexStreamZeroData
, VertexStreamZeroStride
);
3013 user_assert(pVertexStreamZeroData
&& VertexStreamZeroStride
,
3014 D3DERR_INVALIDCALL
);
3016 nine_update_state(This
);
3018 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
3019 info
.indexed
= FALSE
;
3021 info
.index_bias
= 0;
3023 info
.max_index
= info
.count
- 1;
3025 vtxbuf
.stride
= VertexStreamZeroStride
;
3026 vtxbuf
.buffer_offset
= 0;
3027 vtxbuf
.buffer
= NULL
;
3028 vtxbuf
.user_buffer
= pVertexStreamZeroData
;
3030 if (!This
->driver_caps
.user_vbufs
) {
3031 u_upload_data(This
->vertex_uploader
,
3033 (info
.max_index
+ 1) * VertexStreamZeroStride
, /* XXX */
3036 &vtxbuf
.buffer_offset
,
3038 u_upload_unmap(This
->vertex_uploader
);
3039 vtxbuf
.user_buffer
= NULL
;
3042 This
->pipe
->set_vertex_buffers(This
->pipe
, 0, 1, &vtxbuf
);
3044 This
->pipe
->draw_vbo(This
->pipe
, &info
);
3046 NineDevice9_PauseRecording(This
);
3047 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
3048 NineDevice9_ResumeRecording(This
);
3050 pipe_resource_reference(&vtxbuf
.buffer
, NULL
);
3056 NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9
*This
,
3057 D3DPRIMITIVETYPE PrimitiveType
,
3058 UINT MinVertexIndex
,
3060 UINT PrimitiveCount
,
3061 const void *pIndexData
,
3062 D3DFORMAT IndexDataFormat
,
3063 const void *pVertexStreamZeroData
,
3064 UINT VertexStreamZeroStride
)
3066 struct pipe_draw_info info
;
3067 struct pipe_vertex_buffer vbuf
;
3068 struct pipe_index_buffer ibuf
;
3070 DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
3071 "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
3072 "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
3073 This
, PrimitiveType
, MinVertexIndex
, NumVertices
, PrimitiveCount
,
3074 pIndexData
, IndexDataFormat
,
3075 pVertexStreamZeroData
, VertexStreamZeroStride
);
3077 user_assert(pIndexData
&& pVertexStreamZeroData
, D3DERR_INVALIDCALL
);
3078 user_assert(VertexStreamZeroStride
, D3DERR_INVALIDCALL
);
3079 user_assert(IndexDataFormat
== D3DFMT_INDEX16
||
3080 IndexDataFormat
== D3DFMT_INDEX32
, D3DERR_INVALIDCALL
);
3082 nine_update_state(This
);
3084 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
3085 info
.indexed
= TRUE
;
3087 info
.index_bias
= 0;
3088 info
.min_index
= MinVertexIndex
;
3089 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
3091 vbuf
.stride
= VertexStreamZeroStride
;
3092 vbuf
.buffer_offset
= 0;
3094 vbuf
.user_buffer
= pVertexStreamZeroData
;
3096 ibuf
.index_size
= (IndexDataFormat
== D3DFMT_INDEX16
) ? 2 : 4;
3099 ibuf
.user_buffer
= pIndexData
;
3101 if (!This
->driver_caps
.user_vbufs
) {
3102 const unsigned base
= info
.min_index
* VertexStreamZeroStride
;
3103 u_upload_data(This
->vertex_uploader
,
3106 info
.min_index
+ 1) * VertexStreamZeroStride
, /* XXX */
3108 (const uint8_t *)vbuf
.user_buffer
+ base
,
3109 &vbuf
.buffer_offset
,
3111 u_upload_unmap(This
->vertex_uploader
);
3112 /* Won't be used: */
3113 vbuf
.buffer_offset
-= base
;
3114 vbuf
.user_buffer
= NULL
;
3116 if (!This
->driver_caps
.user_ibufs
) {
3117 u_upload_data(This
->index_uploader
,
3119 info
.count
* ibuf
.index_size
,
3124 u_upload_unmap(This
->index_uploader
);
3125 ibuf
.user_buffer
= NULL
;
3128 This
->pipe
->set_vertex_buffers(This
->pipe
, 0, 1, &vbuf
);
3129 This
->pipe
->set_index_buffer(This
->pipe
, &ibuf
);
3131 This
->pipe
->draw_vbo(This
->pipe
, &info
);
3133 pipe_resource_reference(&vbuf
.buffer
, NULL
);
3134 pipe_resource_reference(&ibuf
.buffer
, NULL
);
3136 NineDevice9_PauseRecording(This
);
3137 NineDevice9_SetIndices(This
, NULL
);
3138 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
3139 NineDevice9_ResumeRecording(This
);
3145 NineDevice9_ProcessVertices( struct NineDevice9
*This
,
3149 IDirect3DVertexBuffer9
*pDestBuffer
,
3150 IDirect3DVertexDeclaration9
*pVertexDecl
,
3153 struct pipe_screen
*screen_sw
= This
->screen_sw
;
3154 struct pipe_context
*pipe_sw
= This
->pipe_sw
;
3155 struct NineVertexDeclaration9
*vdecl
= NineVertexDeclaration9(pVertexDecl
);
3156 struct NineVertexBuffer9
*dst
= NineVertexBuffer9(pDestBuffer
);
3157 struct NineVertexShader9
*vs
;
3158 struct pipe_resource
*resource
;
3159 struct pipe_transfer
*transfer
= NULL
;
3160 struct pipe_stream_output_info so
;
3161 struct pipe_stream_output_target
*target
;
3162 struct pipe_draw_info draw
;
3163 struct pipe_box box
;
3164 unsigned offsets
[1] = {0};
3166 unsigned buffer_size
;
3169 DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
3170 "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
3171 This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
,
3172 pVertexDecl
, Flags
);
3174 if (!screen_sw
->get_param(screen_sw
, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS
)) {
3175 DBG("ProcessVertices not supported\n");
3176 return D3DERR_INVALIDCALL
;
3180 vs
= This
->state
.programmable_vs
? This
->state
.vs
: This
->ff
.vs
;
3181 /* Note: version is 0 for ff */
3182 user_assert(vdecl
|| (vs
->byte_code
.version
< 0x30 && dst
->desc
.FVF
),
3183 D3DERR_INVALIDCALL
);
3185 DWORD FVF
= dst
->desc
.FVF
;
3186 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3188 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3192 util_hash_table_set(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3193 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3197 /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags
3198 * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular
3199 * if not set, everything from src will be used, and dst
3200 * must match exactly the ff vs outputs.
3201 * TODO: Handle all the checks, etc for ff */
3202 user_assert(vdecl
->position_t
|| This
->state
.programmable_vs
,
3203 D3DERR_INVALIDCALL
);
3205 /* TODO: Support vs < 3 and ff */
3206 user_assert(vs
->byte_code
.version
== 0x30,
3207 D3DERR_INVALIDCALL
);
3208 /* TODO: Not hardcode the constant buffers for swvp */
3209 user_assert(This
->may_swvp
,
3210 D3DERR_INVALIDCALL
);
3212 nine_state_prepare_draw_sw(This
, vdecl
, SrcStartIndex
, VertexCount
, &so
);
3214 buffer_size
= VertexCount
* so
.stride
[0] * 4;
3216 struct pipe_resource templ
;
3218 memset(&templ
, 0, sizeof(templ
));
3219 templ
.target
= PIPE_BUFFER
;
3220 templ
.format
= PIPE_FORMAT_R8_UNORM
;
3221 templ
.width0
= buffer_size
;
3223 templ
.bind
= PIPE_BIND_STREAM_OUTPUT
;
3224 templ
.usage
= PIPE_USAGE_STREAM
;
3225 templ
.height0
= templ
.depth0
= templ
.array_size
= 1;
3226 templ
.last_level
= templ
.nr_samples
= 0;
3228 resource
= screen_sw
->resource_create(screen_sw
, &templ
);
3230 return E_OUTOFMEMORY
;
3232 target
= pipe_sw
->create_stream_output_target(pipe_sw
, resource
,
3235 pipe_resource_reference(&resource
, NULL
);
3236 return D3DERR_DRIVERINTERNALERROR
;
3239 init_draw_info(&draw
, This
, D3DPT_POINTLIST
, VertexCount
);
3240 draw
.instance_count
= 1;
3241 draw
.indexed
= FALSE
;
3243 draw
.index_bias
= 0;
3245 draw
.max_index
= VertexCount
- 1;
3248 pipe_sw
->set_stream_output_targets(pipe_sw
, 1, &target
, offsets
);
3250 pipe_sw
->draw_vbo(pipe_sw
, &draw
);
3252 pipe_sw
->set_stream_output_targets(pipe_sw
, 0, NULL
, 0);
3253 pipe_sw
->stream_output_target_destroy(pipe_sw
, target
);
3255 u_box_1d(0, VertexCount
* so
.stride
[0] * 4, &box
);
3256 map
= pipe_sw
->transfer_map(pipe_sw
, resource
, 0, PIPE_TRANSFER_READ
, &box
,
3259 hr
= D3DERR_DRIVERINTERNALERROR
;
3263 hr
= NineVertexDeclaration9_ConvertStreamOutput(vdecl
,
3264 dst
, DestIndex
, VertexCount
,
3267 pipe_sw
->transfer_unmap(pipe_sw
, transfer
);
3270 nine_state_after_draw_sw(This
);
3271 pipe_resource_reference(&resource
, NULL
);
3276 NineDevice9_CreateVertexDeclaration( struct NineDevice9
*This
,
3277 const D3DVERTEXELEMENT9
*pVertexElements
,
3278 IDirect3DVertexDeclaration9
**ppDecl
)
3280 struct NineVertexDeclaration9
*vdecl
;
3282 DBG("This=%p pVertexElements=%p ppDecl=%p\n",
3283 This
, pVertexElements
, ppDecl
);
3285 HRESULT hr
= NineVertexDeclaration9_new(This
, pVertexElements
, &vdecl
);
3287 *ppDecl
= (IDirect3DVertexDeclaration9
*)vdecl
;
3293 NineDevice9_SetVertexDeclaration( struct NineDevice9
*This
,
3294 IDirect3DVertexDeclaration9
*pDecl
)
3296 struct nine_state
*state
= This
->update
;
3297 BOOL was_programmable_vs
= This
->state
.programmable_vs
;
3299 DBG("This=%p pDecl=%p\n", This
, pDecl
);
3301 if (likely(!This
->is_recording
) && state
->vdecl
== NineVertexDeclaration9(pDecl
))
3304 nine_bind(&state
->vdecl
, pDecl
);
3306 This
->state
.programmable_vs
= This
->state
.vs
&& !(This
->state
.vdecl
&& This
->state
.vdecl
->position_t
);
3307 if (likely(!This
->is_recording
) && was_programmable_vs
!= This
->state
.programmable_vs
) {
3308 state
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
3309 state
->changed
.group
|= NINE_STATE_VS
;
3312 state
->changed
.group
|= NINE_STATE_VDECL
;
3318 NineDevice9_GetVertexDeclaration( struct NineDevice9
*This
,
3319 IDirect3DVertexDeclaration9
**ppDecl
)
3321 user_assert(ppDecl
, D3DERR_INVALIDCALL
);
3323 *ppDecl
= (IDirect3DVertexDeclaration9
*)This
->state
.vdecl
;
3325 NineUnknown_AddRef(NineUnknown(*ppDecl
));
3330 NineDevice9_SetFVF( struct NineDevice9
*This
,
3333 struct NineVertexDeclaration9
*vdecl
;
3336 DBG("FVF = %08x\n", FVF
);
3338 return D3D_OK
; /* like wine */
3340 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3342 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3346 util_hash_table_set(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3347 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3349 return NineDevice9_SetVertexDeclaration(
3350 This
, (IDirect3DVertexDeclaration9
*)vdecl
);
3354 NineDevice9_GetFVF( struct NineDevice9
*This
,
3357 *pFVF
= This
->state
.vdecl
? This
->state
.vdecl
->fvf
: 0;
3362 NineDevice9_CreateVertexShader( struct NineDevice9
*This
,
3363 const DWORD
*pFunction
,
3364 IDirect3DVertexShader9
**ppShader
)
3366 struct NineVertexShader9
*vs
;
3369 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3371 hr
= NineVertexShader9_new(This
, &vs
, pFunction
, NULL
);
3374 *ppShader
= (IDirect3DVertexShader9
*)vs
;
3379 NineDevice9_SetVertexShader( struct NineDevice9
*This
,
3380 IDirect3DVertexShader9
*pShader
)
3382 struct nine_state
*state
= This
->update
;
3383 BOOL was_programmable_vs
= This
->state
.programmable_vs
;
3385 DBG("This=%p pShader=%p\n", This
, pShader
);
3387 if (!This
->is_recording
&& state
->vs
== (struct NineVertexShader9
*)pShader
)
3390 nine_bind(&state
->vs
, pShader
);
3392 This
->state
.programmable_vs
= This
->state
.vs
&& !(This
->state
.vdecl
&& This
->state
.vdecl
->position_t
);
3394 /* ff -> non-ff: commit back non-ff constants */
3395 if (!was_programmable_vs
&& This
->state
.programmable_vs
)
3396 state
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
3398 state
->changed
.group
|= NINE_STATE_VS
;
3404 NineDevice9_GetVertexShader( struct NineDevice9
*This
,
3405 IDirect3DVertexShader9
**ppShader
)
3407 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3408 nine_reference_set(ppShader
, This
->state
.vs
);
3413 NineDevice9_SetVertexShaderConstantF( struct NineDevice9
*This
,
3415 const float *pConstantData
,
3416 UINT Vector4fCount
)
3418 struct nine_state
*state
= This
->update
;
3419 float *vs_const_f
= This
->may_swvp
? state
->vs_const_f_swvp
: state
->vs_const_f
;
3421 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3422 This
, StartRegister
, pConstantData
, Vector4fCount
);
3424 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3425 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3429 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3431 if (!This
->is_recording
) {
3432 if (!memcmp(&vs_const_f
[StartRegister
* 4], pConstantData
,
3433 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0])))
3437 memcpy(&vs_const_f
[StartRegister
* 4],
3439 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3441 nine_ranges_insert(&state
->changed
.vs_const_f
,
3442 StartRegister
, StartRegister
+ Vector4fCount
,
3445 if (This
->may_swvp
) {
3446 Vector4fCount
= MIN2(StartRegister
+ Vector4fCount
, NINE_MAX_CONST_F
) - StartRegister
;
3447 if (StartRegister
< NINE_MAX_CONST_F
)
3448 memcpy(&state
->vs_const_f
[StartRegister
* 4],
3450 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3453 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3459 NineDevice9_GetVertexShaderConstantF( struct NineDevice9
*This
,
3461 float *pConstantData
,
3462 UINT Vector4fCount
)
3464 const struct nine_state
*state
= &This
->state
;
3465 float *vs_const_f
= This
->may_swvp
? state
->vs_const_f_swvp
: state
->vs_const_f
;
3467 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3468 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3469 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3471 memcpy(pConstantData
,
3472 &vs_const_f
[StartRegister
* 4],
3473 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3479 NineDevice9_SetVertexShaderConstantI( struct NineDevice9
*This
,
3481 const int *pConstantData
,
3482 UINT Vector4iCount
)
3484 struct nine_state
*state
= This
->update
;
3487 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3488 This
, StartRegister
, pConstantData
, Vector4iCount
);
3490 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3491 D3DERR_INVALIDCALL
);
3492 user_assert(StartRegister
+ Vector4iCount
<= (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3493 D3DERR_INVALIDCALL
);
3494 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3496 if (This
->driver_caps
.vs_integer
) {
3497 if (!This
->is_recording
) {
3498 if (!memcmp(&state
->vs_const_i
[4 * StartRegister
], pConstantData
,
3499 Vector4iCount
* sizeof(int[4])))
3502 memcpy(&state
->vs_const_i
[4 * StartRegister
],
3504 Vector4iCount
* sizeof(int[4]));
3506 for (i
= 0; i
< Vector4iCount
; i
++) {
3507 state
->vs_const_i
[4 * (StartRegister
+ i
)] = fui((float)(pConstantData
[4 * i
]));
3508 state
->vs_const_i
[4 * (StartRegister
+ i
) + 1] = fui((float)(pConstantData
[4 * i
+ 1]));
3509 state
->vs_const_i
[4 * (StartRegister
+ i
) + 2] = fui((float)(pConstantData
[4 * i
+ 2]));
3510 state
->vs_const_i
[4 * (StartRegister
+ i
) + 3] = fui((float)(pConstantData
[4 * i
+ 3]));
3514 nine_ranges_insert(&state
->changed
.vs_const_i
,
3515 StartRegister
, StartRegister
+ Vector4iCount
,
3517 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3523 NineDevice9_GetVertexShaderConstantI( struct NineDevice9
*This
,
3526 UINT Vector4iCount
)
3528 const struct nine_state
*state
= &This
->state
;
3531 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3532 D3DERR_INVALIDCALL
);
3533 user_assert(StartRegister
+ Vector4iCount
<= (This
->may_swvp
? NINE_MAX_CONST_I_SWVP
: NINE_MAX_CONST_I
),
3534 D3DERR_INVALIDCALL
);
3535 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3537 if (This
->driver_caps
.vs_integer
) {
3538 memcpy(pConstantData
,
3539 &state
->vs_const_i
[4 * StartRegister
],
3540 Vector4iCount
* sizeof(int[4]));
3542 for (i
= 0; i
< Vector4iCount
; i
++) {
3543 pConstantData
[4 * i
] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
)]);
3544 pConstantData
[4 * i
+ 1] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 1]);
3545 pConstantData
[4 * i
+ 2] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 2]);
3546 pConstantData
[4 * i
+ 3] = (int32_t) uif(state
->vs_const_i
[4 * (StartRegister
+ i
) + 3]);
3554 NineDevice9_SetVertexShaderConstantB( struct NineDevice9
*This
,
3556 const BOOL
*pConstantData
,
3559 struct nine_state
*state
= This
->update
;
3561 uint32_t bool_true
= This
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
3563 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3564 This
, StartRegister
, pConstantData
, BoolCount
);
3566 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3567 D3DERR_INVALIDCALL
);
3568 user_assert(StartRegister
+ BoolCount
<= (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3569 D3DERR_INVALIDCALL
);
3570 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3572 if (!This
->is_recording
) {
3573 bool noChange
= true;
3574 for (i
= 0; i
< BoolCount
; i
++) {
3575 if (!!state
->vs_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3582 for (i
= 0; i
< BoolCount
; i
++)
3583 state
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3585 nine_ranges_insert(&state
->changed
.vs_const_b
,
3586 StartRegister
, StartRegister
+ BoolCount
,
3588 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3594 NineDevice9_GetVertexShaderConstantB( struct NineDevice9
*This
,
3596 BOOL
*pConstantData
,
3599 const struct nine_state
*state
= &This
->state
;
3602 user_assert(StartRegister
< (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3603 D3DERR_INVALIDCALL
);
3604 user_assert(StartRegister
+ BoolCount
<= (This
->may_swvp
? NINE_MAX_CONST_B_SWVP
: NINE_MAX_CONST_B
),
3605 D3DERR_INVALIDCALL
);
3606 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3608 for (i
= 0; i
< BoolCount
; i
++)
3609 pConstantData
[i
] = state
->vs_const_b
[StartRegister
+ i
] != 0 ? TRUE
: FALSE
;
3615 NineDevice9_SetStreamSource( struct NineDevice9
*This
,
3617 IDirect3DVertexBuffer9
*pStreamData
,
3621 struct nine_state
*state
= This
->update
;
3622 struct NineVertexBuffer9
*pVBuf9
= NineVertexBuffer9(pStreamData
);
3623 const unsigned i
= StreamNumber
;
3625 DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",
3626 This
, StreamNumber
, pStreamData
, OffsetInBytes
, Stride
);
3628 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3629 user_assert(Stride
<= This
->caps
.MaxStreamStride
, D3DERR_INVALIDCALL
);
3631 if (likely(!This
->is_recording
)) {
3632 if (state
->stream
[i
] == NineVertexBuffer9(pStreamData
) &&
3633 state
->vtxbuf
[i
].stride
== Stride
&&
3634 state
->vtxbuf
[i
].buffer_offset
== OffsetInBytes
)
3637 nine_bind(&state
->stream
[i
], pStreamData
);
3639 state
->changed
.vtxbuf
|= 1 << StreamNumber
;
3642 state
->vtxbuf
[i
].stride
= Stride
;
3643 state
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
3645 pipe_resource_reference(&state
->vtxbuf
[i
].buffer
,
3646 pStreamData
? NineVertexBuffer9_GetResource(pVBuf9
) : NULL
);
3652 NineDevice9_GetStreamSource( struct NineDevice9
*This
,
3654 IDirect3DVertexBuffer9
**ppStreamData
,
3655 UINT
*pOffsetInBytes
,
3658 const struct nine_state
*state
= &This
->state
;
3659 const unsigned i
= StreamNumber
;
3661 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3662 user_assert(ppStreamData
, D3DERR_INVALIDCALL
);
3664 nine_reference_set(ppStreamData
, state
->stream
[i
]);
3665 *pStride
= state
->vtxbuf
[i
].stride
;
3666 *pOffsetInBytes
= state
->vtxbuf
[i
].buffer_offset
;
3672 NineDevice9_SetStreamSourceFreq( struct NineDevice9
*This
,
3676 struct nine_state
*state
= This
->update
;
3677 /* const UINT freq = Setting & 0x7FFFFF; */
3679 DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This
,
3680 StreamNumber
, Setting
);
3682 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3683 user_assert(StreamNumber
!= 0 || !(Setting
& D3DSTREAMSOURCE_INSTANCEDATA
),
3684 D3DERR_INVALIDCALL
);
3685 user_assert(!((Setting
& D3DSTREAMSOURCE_INSTANCEDATA
) &&
3686 (Setting
& D3DSTREAMSOURCE_INDEXEDDATA
)), D3DERR_INVALIDCALL
);
3687 user_assert(Setting
, D3DERR_INVALIDCALL
);
3689 if (likely(!This
->is_recording
) && state
->stream_freq
[StreamNumber
] == Setting
)
3692 state
->stream_freq
[StreamNumber
] = Setting
;
3694 if (Setting
& D3DSTREAMSOURCE_INSTANCEDATA
)
3695 state
->stream_instancedata_mask
|= 1 << StreamNumber
;
3697 state
->stream_instancedata_mask
&= ~(1 << StreamNumber
);
3699 state
->changed
.stream_freq
|= 1 << StreamNumber
; /* Used for stateblocks */
3700 if (StreamNumber
!= 0)
3701 state
->changed
.group
|= NINE_STATE_STREAMFREQ
;
3706 NineDevice9_GetStreamSourceFreq( struct NineDevice9
*This
,
3710 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3711 *pSetting
= This
->state
.stream_freq
[StreamNumber
];
3716 NineDevice9_SetIndices( struct NineDevice9
*This
,
3717 IDirect3DIndexBuffer9
*pIndexData
)
3719 struct nine_state
*state
= This
->update
;
3721 DBG("This=%p pIndexData=%p\n", This
, pIndexData
);
3723 if (likely(!This
->is_recording
))
3724 if (state
->idxbuf
== NineIndexBuffer9(pIndexData
))
3726 nine_bind(&state
->idxbuf
, pIndexData
);
3728 state
->changed
.group
|= NINE_STATE_IDXBUF
;
3733 /* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
3734 * here because it's an argument passed to the Draw calls.
3737 NineDevice9_GetIndices( struct NineDevice9
*This
,
3738 IDirect3DIndexBuffer9
**ppIndexData
)
3740 user_assert(ppIndexData
, D3DERR_INVALIDCALL
);
3741 nine_reference_set(ppIndexData
, This
->state
.idxbuf
);
3746 NineDevice9_CreatePixelShader( struct NineDevice9
*This
,
3747 const DWORD
*pFunction
,
3748 IDirect3DPixelShader9
**ppShader
)
3750 struct NinePixelShader9
*ps
;
3753 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3755 hr
= NinePixelShader9_new(This
, &ps
, pFunction
, NULL
);
3758 *ppShader
= (IDirect3DPixelShader9
*)ps
;
3763 NineDevice9_SetPixelShader( struct NineDevice9
*This
,
3764 IDirect3DPixelShader9
*pShader
)
3766 struct nine_state
*state
= This
->update
;
3767 unsigned old_mask
= state
->ps
? state
->ps
->rt_mask
: 1;
3770 DBG("This=%p pShader=%p\n", This
, pShader
);
3772 if (!This
->is_recording
&& state
->ps
== (struct NinePixelShader9
*)pShader
)
3775 /* ff -> non-ff: commit back non-ff constants */
3776 if (!state
->ps
&& pShader
)
3777 state
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
3779 nine_bind(&state
->ps
, pShader
);
3781 state
->changed
.group
|= NINE_STATE_PS
;
3783 mask
= state
->ps
? state
->ps
->rt_mask
: 1;
3784 /* We need to update cbufs if the pixel shader would
3785 * write to different render targets */
3786 if (mask
!= old_mask
)
3787 state
->changed
.group
|= NINE_STATE_FB
;
3793 NineDevice9_GetPixelShader( struct NineDevice9
*This
,
3794 IDirect3DPixelShader9
**ppShader
)
3796 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3797 nine_reference_set(ppShader
, This
->state
.ps
);
3802 NineDevice9_SetPixelShaderConstantF( struct NineDevice9
*This
,
3804 const float *pConstantData
,
3805 UINT Vector4fCount
)
3807 struct nine_state
*state
= This
->update
;
3809 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3810 This
, StartRegister
, pConstantData
, Vector4fCount
);
3812 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3813 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3817 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3819 if (!This
->is_recording
) {
3820 if (!memcmp(&state
->ps_const_f
[StartRegister
* 4], pConstantData
,
3821 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0])))
3825 memcpy(&state
->ps_const_f
[StartRegister
* 4],
3827 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3829 nine_ranges_insert(&state
->changed
.ps_const_f
,
3830 StartRegister
, StartRegister
+ Vector4fCount
,
3833 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3839 NineDevice9_GetPixelShaderConstantF( struct NineDevice9
*This
,
3841 float *pConstantData
,
3842 UINT Vector4fCount
)
3844 const struct nine_state
*state
= &This
->state
;
3846 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3847 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3848 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3850 memcpy(pConstantData
,
3851 &state
->ps_const_f
[StartRegister
* 4],
3852 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3858 NineDevice9_SetPixelShaderConstantI( struct NineDevice9
*This
,
3860 const int *pConstantData
,
3861 UINT Vector4iCount
)
3863 struct nine_state
*state
= This
->update
;
3866 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3867 This
, StartRegister
, pConstantData
, Vector4iCount
);
3869 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3870 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3871 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3873 if (This
->driver_caps
.ps_integer
) {
3874 if (!This
->is_recording
) {
3875 if (!memcmp(&state
->ps_const_i
[StartRegister
][0], pConstantData
,
3876 Vector4iCount
* sizeof(state
->ps_const_i
[0])))
3879 memcpy(&state
->ps_const_i
[StartRegister
][0],
3881 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3883 for (i
= 0; i
< Vector4iCount
; i
++) {
3884 state
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
3885 state
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
3886 state
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
3887 state
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
3890 state
->changed
.ps_const_i
|= ((1 << Vector4iCount
) - 1) << StartRegister
;
3891 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3897 NineDevice9_GetPixelShaderConstantI( struct NineDevice9
*This
,
3900 UINT Vector4iCount
)
3902 const struct nine_state
*state
= &This
->state
;
3905 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3906 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3907 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3909 if (This
->driver_caps
.ps_integer
) {
3910 memcpy(pConstantData
,
3911 &state
->ps_const_i
[StartRegister
][0],
3912 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3914 for (i
= 0; i
< Vector4iCount
; i
++) {
3915 pConstantData
[4*i
] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][0]);
3916 pConstantData
[4*i
+1] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][1]);
3917 pConstantData
[4*i
+2] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][2]);
3918 pConstantData
[4*i
+3] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][3]);
3926 NineDevice9_SetPixelShaderConstantB( struct NineDevice9
*This
,
3928 const BOOL
*pConstantData
,
3931 struct nine_state
*state
= This
->update
;
3933 uint32_t bool_true
= This
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
3935 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3936 This
, StartRegister
, pConstantData
, BoolCount
);
3938 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3939 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3940 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3942 if (!This
->is_recording
) {
3943 bool noChange
= true;
3944 for (i
= 0; i
< BoolCount
; i
++) {
3945 if (!!state
->ps_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3952 for (i
= 0; i
< BoolCount
; i
++)
3953 state
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3955 state
->changed
.ps_const_b
|= ((1 << BoolCount
) - 1) << StartRegister
;
3956 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3962 NineDevice9_GetPixelShaderConstantB( struct NineDevice9
*This
,
3964 BOOL
*pConstantData
,
3967 const struct nine_state
*state
= &This
->state
;
3970 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3971 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3972 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3974 for (i
= 0; i
< BoolCount
; i
++)
3975 pConstantData
[i
] = state
->ps_const_b
[StartRegister
+ i
] ? TRUE
: FALSE
;
3981 NineDevice9_DrawRectPatch( struct NineDevice9
*This
,
3983 const float *pNumSegs
,
3984 const D3DRECTPATCH_INFO
*pRectPatchInfo
)
3986 STUB(D3DERR_INVALIDCALL
);
3990 NineDevice9_DrawTriPatch( struct NineDevice9
*This
,
3992 const float *pNumSegs
,
3993 const D3DTRIPATCH_INFO
*pTriPatchInfo
)
3995 STUB(D3DERR_INVALIDCALL
);
3999 NineDevice9_DeletePatch( struct NineDevice9
*This
,
4002 STUB(D3DERR_INVALIDCALL
);
4006 NineDevice9_CreateQuery( struct NineDevice9
*This
,
4008 IDirect3DQuery9
**ppQuery
)
4010 struct NineQuery9
*query
;
4013 DBG("This=%p Type=%d ppQuery=%p\n", This
, Type
, ppQuery
);
4015 hr
= nine_is_query_supported(This
->screen
, Type
);
4016 if (!ppQuery
|| hr
!= D3D_OK
)
4019 hr
= NineQuery9_new(This
, &query
, Type
);
4022 *ppQuery
= (IDirect3DQuery9
*)query
;
4026 IDirect3DDevice9Vtbl NineDevice9_vtable
= {
4027 (void *)NineUnknown_QueryInterface
,
4028 (void *)NineUnknown_AddRef
,
4029 (void *)NineUnknown_Release
,
4030 (void *)NineDevice9_TestCooperativeLevel
,
4031 (void *)NineDevice9_GetAvailableTextureMem
,
4032 (void *)NineDevice9_EvictManagedResources
,
4033 (void *)NineDevice9_GetDirect3D
,
4034 (void *)NineDevice9_GetDeviceCaps
,
4035 (void *)NineDevice9_GetDisplayMode
,
4036 (void *)NineDevice9_GetCreationParameters
,
4037 (void *)NineDevice9_SetCursorProperties
,
4038 (void *)NineDevice9_SetCursorPosition
,
4039 (void *)NineDevice9_ShowCursor
,
4040 (void *)NineDevice9_CreateAdditionalSwapChain
,
4041 (void *)NineDevice9_GetSwapChain
,
4042 (void *)NineDevice9_GetNumberOfSwapChains
,
4043 (void *)NineDevice9_Reset
,
4044 (void *)NineDevice9_Present
,
4045 (void *)NineDevice9_GetBackBuffer
,
4046 (void *)NineDevice9_GetRasterStatus
,
4047 (void *)NineDevice9_SetDialogBoxMode
,
4048 (void *)NineDevice9_SetGammaRamp
,
4049 (void *)NineDevice9_GetGammaRamp
,
4050 (void *)NineDevice9_CreateTexture
,
4051 (void *)NineDevice9_CreateVolumeTexture
,
4052 (void *)NineDevice9_CreateCubeTexture
,
4053 (void *)NineDevice9_CreateVertexBuffer
,
4054 (void *)NineDevice9_CreateIndexBuffer
,
4055 (void *)NineDevice9_CreateRenderTarget
,
4056 (void *)NineDevice9_CreateDepthStencilSurface
,
4057 (void *)NineDevice9_UpdateSurface
,
4058 (void *)NineDevice9_UpdateTexture
,
4059 (void *)NineDevice9_GetRenderTargetData
,
4060 (void *)NineDevice9_GetFrontBufferData
,
4061 (void *)NineDevice9_StretchRect
,
4062 (void *)NineDevice9_ColorFill
,
4063 (void *)NineDevice9_CreateOffscreenPlainSurface
,
4064 (void *)NineDevice9_SetRenderTarget
,
4065 (void *)NineDevice9_GetRenderTarget
,
4066 (void *)NineDevice9_SetDepthStencilSurface
,
4067 (void *)NineDevice9_GetDepthStencilSurface
,
4068 (void *)NineDevice9_BeginScene
,
4069 (void *)NineDevice9_EndScene
,
4070 (void *)NineDevice9_Clear
,
4071 (void *)NineDevice9_SetTransform
,
4072 (void *)NineDevice9_GetTransform
,
4073 (void *)NineDevice9_MultiplyTransform
,
4074 (void *)NineDevice9_SetViewport
,
4075 (void *)NineDevice9_GetViewport
,
4076 (void *)NineDevice9_SetMaterial
,
4077 (void *)NineDevice9_GetMaterial
,
4078 (void *)NineDevice9_SetLight
,
4079 (void *)NineDevice9_GetLight
,
4080 (void *)NineDevice9_LightEnable
,
4081 (void *)NineDevice9_GetLightEnable
,
4082 (void *)NineDevice9_SetClipPlane
,
4083 (void *)NineDevice9_GetClipPlane
,
4084 (void *)NineDevice9_SetRenderState
,
4085 (void *)NineDevice9_GetRenderState
,
4086 (void *)NineDevice9_CreateStateBlock
,
4087 (void *)NineDevice9_BeginStateBlock
,
4088 (void *)NineDevice9_EndStateBlock
,
4089 (void *)NineDevice9_SetClipStatus
,
4090 (void *)NineDevice9_GetClipStatus
,
4091 (void *)NineDevice9_GetTexture
,
4092 (void *)NineDevice9_SetTexture
,
4093 (void *)NineDevice9_GetTextureStageState
,
4094 (void *)NineDevice9_SetTextureStageState
,
4095 (void *)NineDevice9_GetSamplerState
,
4096 (void *)NineDevice9_SetSamplerState
,
4097 (void *)NineDevice9_ValidateDevice
,
4098 (void *)NineDevice9_SetPaletteEntries
,
4099 (void *)NineDevice9_GetPaletteEntries
,
4100 (void *)NineDevice9_SetCurrentTexturePalette
,
4101 (void *)NineDevice9_GetCurrentTexturePalette
,
4102 (void *)NineDevice9_SetScissorRect
,
4103 (void *)NineDevice9_GetScissorRect
,
4104 (void *)NineDevice9_SetSoftwareVertexProcessing
,
4105 (void *)NineDevice9_GetSoftwareVertexProcessing
,
4106 (void *)NineDevice9_SetNPatchMode
,
4107 (void *)NineDevice9_GetNPatchMode
,
4108 (void *)NineDevice9_DrawPrimitive
,
4109 (void *)NineDevice9_DrawIndexedPrimitive
,
4110 (void *)NineDevice9_DrawPrimitiveUP
,
4111 (void *)NineDevice9_DrawIndexedPrimitiveUP
,
4112 (void *)NineDevice9_ProcessVertices
,
4113 (void *)NineDevice9_CreateVertexDeclaration
,
4114 (void *)NineDevice9_SetVertexDeclaration
,
4115 (void *)NineDevice9_GetVertexDeclaration
,
4116 (void *)NineDevice9_SetFVF
,
4117 (void *)NineDevice9_GetFVF
,
4118 (void *)NineDevice9_CreateVertexShader
,
4119 (void *)NineDevice9_SetVertexShader
,
4120 (void *)NineDevice9_GetVertexShader
,
4121 (void *)NineDevice9_SetVertexShaderConstantF
,
4122 (void *)NineDevice9_GetVertexShaderConstantF
,
4123 (void *)NineDevice9_SetVertexShaderConstantI
,
4124 (void *)NineDevice9_GetVertexShaderConstantI
,
4125 (void *)NineDevice9_SetVertexShaderConstantB
,
4126 (void *)NineDevice9_GetVertexShaderConstantB
,
4127 (void *)NineDevice9_SetStreamSource
,
4128 (void *)NineDevice9_GetStreamSource
,
4129 (void *)NineDevice9_SetStreamSourceFreq
,
4130 (void *)NineDevice9_GetStreamSourceFreq
,
4131 (void *)NineDevice9_SetIndices
,
4132 (void *)NineDevice9_GetIndices
,
4133 (void *)NineDevice9_CreatePixelShader
,
4134 (void *)NineDevice9_SetPixelShader
,
4135 (void *)NineDevice9_GetPixelShader
,
4136 (void *)NineDevice9_SetPixelShaderConstantF
,
4137 (void *)NineDevice9_GetPixelShaderConstantF
,
4138 (void *)NineDevice9_SetPixelShaderConstantI
,
4139 (void *)NineDevice9_GetPixelShaderConstantI
,
4140 (void *)NineDevice9_SetPixelShaderConstantB
,
4141 (void *)NineDevice9_GetPixelShaderConstantB
,
4142 (void *)NineDevice9_DrawRectPatch
,
4143 (void *)NineDevice9_DrawTriPatch
,
4144 (void *)NineDevice9_DeletePatch
,
4145 (void *)NineDevice9_CreateQuery
4148 static const GUID
*NineDevice9_IIDs
[] = {
4149 &IID_IDirect3DDevice9
,
4155 NineDevice9_new( struct pipe_screen
*pScreen
,
4156 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
4158 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
4160 ID3DPresentGroup
*pPresentationGroup
,
4161 struct d3dadapter9_context
*pCTX
,
4163 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
4164 struct NineDevice9
**ppOut
,
4165 int minorVersionNum
)
4168 lock
= !!(pCreationParameters
->BehaviorFlags
& D3DCREATE_MULTITHREADED
);
4170 NINE_NEW(Device9
, ppOut
, lock
, /* args */
4171 pScreen
, pCreationParameters
, pCaps
,
4172 pPresentationParameters
, pD3D9
, pPresentationGroup
, pCTX
,
4173 ex
, pFullscreenDisplayMode
, minorVersionNum
);