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 #include <fpu_control.h>
62 static void nine_setup_fpu()
67 /* clear the control word */
69 /* d3d9 doc/wine tests: mask all exceptions, use single-precision
70 * and round to nearest */
71 c
|= _FPU_MASK_IM
| _FPU_MASK_DM
| _FPU_MASK_ZM
| _FPU_MASK_OM
|
72 _FPU_MASK_UM
| _FPU_MASK_PM
| _FPU_SINGLE
| _FPU_RC_NEAREST
;
78 static void nine_setup_fpu(void)
80 WARN_ONCE("FPU setup not supported on non-x86 platforms\n");
86 NineDevice9_SetDefaultState( struct NineDevice9
*This
, boolean is_reset
)
88 struct NineSurface9
*refSurf
= NULL
;
90 DBG("This=%p is_reset=%d\n", This
, (int) is_reset
);
92 assert(!This
->is_recording
);
94 nine_state_set_defaults(This
, &This
->caps
, is_reset
);
96 This
->state
.viewport
.X
= 0;
97 This
->state
.viewport
.Y
= 0;
98 This
->state
.viewport
.Width
= 0;
99 This
->state
.viewport
.Height
= 0;
101 This
->state
.scissor
.minx
= 0;
102 This
->state
.scissor
.miny
= 0;
103 This
->state
.scissor
.maxx
= 0xffff;
104 This
->state
.scissor
.maxy
= 0xffff;
106 if (This
->nswapchains
&& This
->swapchains
[0]->params
.BackBufferCount
)
107 refSurf
= This
->swapchains
[0]->buffers
[0];
110 This
->state
.viewport
.Width
= refSurf
->desc
.Width
;
111 This
->state
.viewport
.Height
= refSurf
->desc
.Height
;
112 This
->state
.scissor
.maxx
= refSurf
->desc
.Width
;
113 This
->state
.scissor
.maxy
= refSurf
->desc
.Height
;
116 if (This
->nswapchains
&& This
->swapchains
[0]->params
.EnableAutoDepthStencil
) {
117 This
->state
.rs
[D3DRS_ZENABLE
] = TRUE
;
118 This
->state
.rs_advertised
[D3DRS_ZENABLE
] = TRUE
;
120 if (This
->state
.rs
[D3DRS_ZENABLE
])
121 NineDevice9_SetDepthStencilSurface(
122 This
, (IDirect3DSurface9
*)This
->swapchains
[0]->zsbuf
);
125 #define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
127 NineDevice9_ctor( struct NineDevice9
*This
,
128 struct NineUnknownParams
*pParams
,
129 struct pipe_screen
*pScreen
,
130 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
132 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
134 ID3DPresentGroup
*pPresentationGroup
,
135 struct d3dadapter9_context
*pCTX
,
137 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
138 int minorVersionNum
)
141 HRESULT hr
= NineUnknown_ctor(&This
->base
, pParams
);
143 DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "
144 "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",
145 This
, pParams
, pScreen
, pCreationParameters
, pCaps
, pPresentationParameters
, pD3D9
,
146 pPresentationGroup
, pCTX
, (int) ex
, pFullscreenDisplayMode
);
148 if (FAILED(hr
)) { return hr
; }
150 list_inithead(&This
->update_textures
);
151 list_inithead(&This
->managed_textures
);
153 This
->screen
= pScreen
;
156 This
->params
= *pCreationParameters
;
158 This
->present
= pPresentationGroup
;
159 This
->minor_version_num
= minorVersionNum
;
161 IDirect3D9_AddRef(This
->d3d9
);
162 ID3DPresentGroup_AddRef(This
->present
);
164 if (!(This
->params
.BehaviorFlags
& D3DCREATE_FPU_PRESERVE
))
167 if (This
->params
.BehaviorFlags
& D3DCREATE_SOFTWARE_VERTEXPROCESSING
)
168 DBG("Application asked full Software Vertex Processing. Ignoring.\n");
169 if (This
->params
.BehaviorFlags
& D3DCREATE_MIXED_VERTEXPROCESSING
)
170 DBG("Application asked mixed Software Vertex Processing. Ignoring.\n");
172 This
->pipe
= This
->screen
->context_create(This
->screen
, NULL
, 0);
173 if (!This
->pipe
) { return E_OUTOFMEMORY
; } /* guess */
175 This
->cso
= cso_create_context(This
->pipe
);
176 if (!This
->cso
) { return E_OUTOFMEMORY
; } /* also a guess */
178 /* Create first, it messes up our state. */
179 This
->hud
= hud_create(This
->pipe
, This
->cso
); /* NULL result is fine */
181 /* Available memory counter. Updated only for allocations with this device
182 * instance. This is the Win 7 behavior.
183 * Win XP shares this counter across multiple devices. */
184 This
->available_texture_mem
= This
->screen
->get_param(This
->screen
, PIPE_CAP_VIDEO_MEMORY
);
185 if (This
->available_texture_mem
< 4096)
186 This
->available_texture_mem
<<= 20;
188 This
->available_texture_mem
= UINT_MAX
;
189 /* We cap texture memory usage to 80% of what is reported free initially
190 * This helps get closer Win behaviour. For example VertexBuffer allocation
191 * still succeeds when texture allocation fails. */
192 This
->available_texture_limit
= This
->available_texture_mem
* 20LL / 100LL;
194 /* create implicit swapchains */
195 This
->nswapchains
= ID3DPresentGroup_GetMultiheadCount(This
->present
);
196 This
->swapchains
= CALLOC(This
->nswapchains
,
197 sizeof(struct NineSwapChain9
*));
198 if (!This
->swapchains
) { return E_OUTOFMEMORY
; }
200 for (i
= 0; i
< This
->nswapchains
; ++i
) {
201 ID3DPresent
*present
;
203 hr
= ID3DPresentGroup_GetPresent(This
->present
, i
, &present
);
208 D3DDISPLAYMODEEX
*mode
= NULL
;
209 struct NineSwapChain9Ex
**ret
=
210 (struct NineSwapChain9Ex
**)&This
->swapchains
[i
];
212 if (pFullscreenDisplayMode
) mode
= &(pFullscreenDisplayMode
[i
]);
213 /* when this is a Device9Ex, it should create SwapChain9Exs */
214 hr
= NineSwapChain9Ex_new(This
, TRUE
, present
,
215 &pPresentationParameters
[i
], pCTX
,
216 This
->params
.hFocusWindow
, mode
, ret
);
218 hr
= NineSwapChain9_new(This
, TRUE
, present
,
219 &pPresentationParameters
[i
], pCTX
,
220 This
->params
.hFocusWindow
,
221 &This
->swapchains
[i
]);
224 ID3DPresent_Release(present
);
227 NineUnknown_ConvertRefToBind(NineUnknown(This
->swapchains
[i
]));
229 hr
= NineSwapChain9_GetBackBuffer(This
->swapchains
[i
], 0,
230 D3DBACKBUFFER_TYPE_MONO
,
231 (IDirect3DSurface9
**)
235 NineUnknown_ConvertRefToBind(NineUnknown(This
->state
.rt
[i
]));
238 /* Initialize a dummy VBO to be used when a a vertex declaration does not
239 * specify all the inputs needed by vertex shader, on win default behavior
240 * is to pass 0,0,0,0 to the shader */
242 struct pipe_transfer
*transfer
;
243 struct pipe_resource tmpl
;
247 tmpl
.target
= PIPE_BUFFER
;
248 tmpl
.format
= PIPE_FORMAT_R8_UNORM
;
249 tmpl
.width0
= 16; /* 4 floats */
255 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
256 tmpl
.bind
= PIPE_BIND_VERTEX_BUFFER
| PIPE_BIND_TRANSFER_WRITE
;
258 This
->dummy_vbo
= pScreen
->resource_create(pScreen
, &tmpl
);
260 if (!This
->dummy_vbo
)
261 return D3DERR_OUTOFVIDEOMEMORY
;
263 u_box_1d(0, 16, &box
);
264 data
= This
->pipe
->transfer_map(This
->pipe
, This
->dummy_vbo
, 0,
265 PIPE_TRANSFER_WRITE
|
266 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
271 This
->pipe
->transfer_unmap(This
->pipe
, transfer
);
274 This
->cursor
.software
= FALSE
;
275 This
->cursor
.hotspot
.x
= -1;
276 This
->cursor
.hotspot
.y
= -1;
278 struct pipe_resource tmpl
;
279 tmpl
.target
= PIPE_TEXTURE_2D
;
280 tmpl
.format
= PIPE_FORMAT_R8G8B8A8_UNORM
;
287 tmpl
.usage
= PIPE_USAGE_DEFAULT
;
288 tmpl
.bind
= PIPE_BIND_CURSOR
| PIPE_BIND_SAMPLER_VIEW
;
291 This
->cursor
.image
= pScreen
->resource_create(pScreen
, &tmpl
);
292 if (!This
->cursor
.image
)
293 return D3DERR_OUTOFVIDEOMEMORY
;
296 /* Create constant buffers. */
298 struct pipe_resource tmpl
;
299 unsigned max_const_vs
, max_const_ps
;
301 /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
302 * we have to take in some more slots for int and bool*/
303 max_const_vs
= _min(pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
,
304 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE
) /
307 /* ps 3.0: 224 float constants. All cards supported support at least
308 * 256 constants for ps */
309 max_const_ps
= NINE_MAX_CONST_F_PS3
+ (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
311 This
->max_vs_const_f
= max_const_vs
-
312 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
313 This
->max_ps_const_f
= max_const_ps
-
314 (NINE_MAX_CONST_I
+ NINE_MAX_CONST_B
/ 4);
316 This
->vs_const_size
= max_const_vs
* sizeof(float[4]);
317 This
->ps_const_size
= max_const_ps
* sizeof(float[4]);
318 /* Include space for I,B constants for user constbuf. */
319 This
->state
.vs_const_f
= CALLOC(This
->vs_const_size
, 1);
320 This
->state
.ps_const_f
= CALLOC(This
->ps_const_size
, 1);
321 This
->state
.vs_lconstf_temp
= CALLOC(This
->vs_const_size
,1);
322 This
->state
.ps_lconstf_temp
= CALLOC(This
->ps_const_size
,1);
323 if (!This
->state
.vs_const_f
|| !This
->state
.ps_const_f
||
324 !This
->state
.vs_lconstf_temp
|| !This
->state
.ps_lconstf_temp
)
325 return E_OUTOFMEMORY
;
327 if (strstr(pScreen
->get_name(pScreen
), "AMD") ||
328 strstr(pScreen
->get_name(pScreen
), "ATI")) {
329 This
->driver_bugs
.buggy_barycentrics
= TRUE
;
332 /* Disable NV path for now, needs some fixes */
333 This
->prefer_user_constbuf
= TRUE
;
335 tmpl
.target
= PIPE_BUFFER
;
336 tmpl
.format
= PIPE_FORMAT_R8_UNORM
;
342 tmpl
.usage
= PIPE_USAGE_DYNAMIC
;
343 tmpl
.bind
= PIPE_BIND_CONSTANT_BUFFER
;
346 tmpl
.width0
= This
->vs_const_size
;
347 This
->constbuf_vs
= pScreen
->resource_create(pScreen
, &tmpl
);
349 tmpl
.width0
= This
->ps_const_size
;
350 This
->constbuf_ps
= pScreen
->resource_create(pScreen
, &tmpl
);
352 if (!This
->constbuf_vs
|| !This
->constbuf_ps
)
353 return E_OUTOFMEMORY
;
356 /* allocate dummy texture/sampler for when there are missing ones bound */
358 struct pipe_resource tmplt
;
359 struct pipe_sampler_view templ
;
360 struct pipe_sampler_state samp
;
361 memset(&samp
, 0, sizeof(samp
));
363 tmplt
.target
= PIPE_TEXTURE_2D
;
367 tmplt
.last_level
= 0;
368 tmplt
.array_size
= 1;
369 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
371 tmplt
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
372 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
;
373 tmplt
.nr_samples
= 0;
375 This
->dummy_texture
= This
->screen
->resource_create(This
->screen
, &tmplt
);
376 if (!This
->dummy_texture
)
377 return D3DERR_DRIVERINTERNALERROR
;
379 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
380 templ
.u
.tex
.first_layer
= 0;
381 templ
.u
.tex
.last_layer
= 0;
382 templ
.u
.tex
.first_level
= 0;
383 templ
.u
.tex
.last_level
= 0;
384 templ
.swizzle_r
= PIPE_SWIZZLE_ZERO
;
385 templ
.swizzle_g
= PIPE_SWIZZLE_ZERO
;
386 templ
.swizzle_b
= PIPE_SWIZZLE_ZERO
;
387 templ
.swizzle_a
= PIPE_SWIZZLE_ONE
;
388 templ
.target
= This
->dummy_texture
->target
;
390 This
->dummy_sampler_view
= This
->pipe
->create_sampler_view(This
->pipe
, This
->dummy_texture
, &templ
);
391 if (!This
->dummy_sampler_view
)
392 return D3DERR_DRIVERINTERNALERROR
;
394 samp
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
395 samp
.max_lod
= 15.0f
;
396 samp
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
397 samp
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
398 samp
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
399 samp
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
400 samp
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
401 samp
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
402 samp
.compare_func
= PIPE_FUNC_LEQUAL
;
403 samp
.normalized_coords
= 1;
404 samp
.seamless_cube_map
= 1;
405 This
->dummy_sampler_state
= samp
;
408 /* Allocate upload helper for drivers that suck (from st pov ;). */
410 This
->driver_caps
.user_vbufs
= GET_PCAP(USER_VERTEX_BUFFERS
);
411 This
->driver_caps
.user_ibufs
= GET_PCAP(USER_INDEX_BUFFERS
);
412 This
->driver_caps
.user_cbufs
= GET_PCAP(USER_CONSTANT_BUFFERS
);
414 if (!This
->driver_caps
.user_vbufs
)
415 This
->vertex_uploader
= u_upload_create(This
->pipe
, 65536,
416 PIPE_BIND_VERTEX_BUFFER
, PIPE_USAGE_STREAM
);
417 if (!This
->driver_caps
.user_ibufs
)
418 This
->index_uploader
= u_upload_create(This
->pipe
, 128 * 1024,
419 PIPE_BIND_INDEX_BUFFER
, PIPE_USAGE_STREAM
);
420 if (!This
->driver_caps
.user_cbufs
) {
421 This
->constbuf_alignment
= GET_PCAP(CONSTANT_BUFFER_OFFSET_ALIGNMENT
);
422 This
->constbuf_uploader
= u_upload_create(This
->pipe
, This
->vs_const_size
,
423 PIPE_BIND_CONSTANT_BUFFER
, PIPE_USAGE_STREAM
);
426 This
->driver_caps
.window_space_position_support
= GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION
);
427 This
->driver_caps
.vs_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_VERTEX
, PIPE_SHADER_CAP_INTEGERS
);
428 This
->driver_caps
.ps_integer
= pScreen
->get_shader_param(pScreen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_INTEGERS
);
430 nine_ff_init(This
); /* initialize fixed function code */
432 NineDevice9_SetDefaultState(This
, FALSE
);
435 struct pipe_poly_stipple stipple
;
436 memset(&stipple
, ~0, sizeof(stipple
));
437 This
->pipe
->set_polygon_stipple(This
->pipe
, &stipple
);
440 This
->update
= &This
->state
;
441 nine_update_state(This
);
443 ID3DPresentGroup_Release(This
->present
);
450 NineDevice9_dtor( struct NineDevice9
*This
)
454 DBG("This=%p\n", This
);
456 if (This
->pipe
&& This
->cso
)
457 nine_pipe_context_clear(This
);
459 nine_state_clear(&This
->state
, TRUE
);
461 if (This
->vertex_uploader
)
462 u_upload_destroy(This
->vertex_uploader
);
463 if (This
->index_uploader
)
464 u_upload_destroy(This
->index_uploader
);
465 if (This
->constbuf_uploader
)
466 u_upload_destroy(This
->constbuf_uploader
);
468 nine_bind(&This
->record
, NULL
);
470 pipe_sampler_view_reference(&This
->dummy_sampler_view
, NULL
);
471 pipe_resource_reference(&This
->dummy_texture
, NULL
);
472 pipe_resource_reference(&This
->constbuf_vs
, NULL
);
473 pipe_resource_reference(&This
->constbuf_ps
, NULL
);
474 pipe_resource_reference(&This
->dummy_vbo
, NULL
);
475 FREE(This
->state
.vs_const_f
);
476 FREE(This
->state
.ps_const_f
);
477 FREE(This
->state
.vs_lconstf_temp
);
478 FREE(This
->state
.ps_lconstf_temp
);
480 if (This
->swapchains
) {
481 for (i
= 0; i
< This
->nswapchains
; ++i
)
482 if (This
->swapchains
[i
])
483 NineUnknown_Unbind(NineUnknown(This
->swapchains
[i
]));
484 FREE(This
->swapchains
);
490 cso_destroy_context(This
->cso
);
492 if (This
->pipe
->destroy
) { This
->pipe
->destroy(This
->pipe
); }
495 if (This
->present
) { ID3DPresentGroup_Release(This
->present
); }
496 if (This
->d3d9
) { IDirect3D9_Release(This
->d3d9
); }
498 NineUnknown_dtor(&This
->base
);
502 NineDevice9_GetScreen( struct NineDevice9
*This
)
507 struct pipe_context
*
508 NineDevice9_GetPipe( struct NineDevice9
*This
)
514 NineDevice9_GetCSO( struct NineDevice9
*This
)
520 NineDevice9_GetCaps( struct NineDevice9
*This
)
526 NineDevice9_PauseRecording( struct NineDevice9
*This
)
529 This
->update
= &This
->state
;
530 This
->is_recording
= FALSE
;
535 NineDevice9_ResumeRecording( struct NineDevice9
*This
)
538 This
->update
= &This
->record
->state
;
539 This
->is_recording
= TRUE
;
544 NineDevice9_TestCooperativeLevel( struct NineDevice9
*This
)
546 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
547 This
->device_needs_reset
= TRUE
;
548 return D3DERR_DEVICELOST
;
549 } else if (This
->device_needs_reset
) {
550 return D3DERR_DEVICENOTRESET
;
557 NineDevice9_GetAvailableTextureMem( struct NineDevice9
*This
)
559 return This
->available_texture_mem
;
563 NineDevice9_EvictManagedResources( struct NineDevice9
*This
)
565 struct NineBaseTexture9
*tex
;
567 DBG("This=%p\n", This
);
568 LIST_FOR_EACH_ENTRY(tex
, &This
->managed_textures
, list2
) {
569 NineBaseTexture9_UnLoad(tex
);
576 NineDevice9_GetDirect3D( struct NineDevice9
*This
,
577 IDirect3D9
**ppD3D9
)
579 user_assert(ppD3D9
!= NULL
, E_POINTER
);
580 IDirect3D9_AddRef(This
->d3d9
);
581 *ppD3D9
= This
->d3d9
;
586 NineDevice9_GetDeviceCaps( struct NineDevice9
*This
,
589 user_assert(pCaps
!= NULL
, D3DERR_INVALIDCALL
);
595 NineDevice9_GetDisplayMode( struct NineDevice9
*This
,
597 D3DDISPLAYMODE
*pMode
)
599 DBG("This=%p iSwapChain=%u pMode=%p\n", This
, iSwapChain
, pMode
);
601 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
603 return NineSwapChain9_GetDisplayMode(This
->swapchains
[iSwapChain
], pMode
);
607 NineDevice9_GetCreationParameters( struct NineDevice9
*This
,
608 D3DDEVICE_CREATION_PARAMETERS
*pParameters
)
610 user_assert(pParameters
!= NULL
, D3DERR_INVALIDCALL
);
611 *pParameters
= This
->params
;
616 NineDevice9_SetCursorProperties( struct NineDevice9
*This
,
619 IDirect3DSurface9
*pCursorBitmap
)
621 struct NineSurface9
*surf
= NineSurface9(pCursorBitmap
);
622 struct pipe_context
*pipe
= This
->pipe
;
624 struct pipe_transfer
*transfer
;
628 DBG_FLAG(DBG_SWAPCHAIN
, "This=%p XHotSpot=%u YHotSpot=%u "
629 "pCursorBitmap=%p\n", This
, XHotSpot
, YHotSpot
, pCursorBitmap
);
631 user_assert(pCursorBitmap
, D3DERR_INVALIDCALL
);
632 user_assert(surf
->desc
.Format
== D3DFMT_A8R8G8B8
, D3DERR_INVALIDCALL
);
634 if (This
->swapchains
[0]->params
.Windowed
) {
635 This
->cursor
.w
= MIN2(surf
->desc
.Width
, 32);
636 This
->cursor
.h
= MIN2(surf
->desc
.Height
, 32);
637 hw_cursor
= 1; /* always use hw cursor for windowed mode */
639 This
->cursor
.w
= MIN2(surf
->desc
.Width
, This
->cursor
.image
->width0
);
640 This
->cursor
.h
= MIN2(surf
->desc
.Height
, This
->cursor
.image
->height0
);
641 hw_cursor
= This
->cursor
.w
== 32 && This
->cursor
.h
== 32;
644 u_box_origin_2d(This
->cursor
.w
, This
->cursor
.h
, &box
);
646 ptr
= pipe
->transfer_map(pipe
, This
->cursor
.image
, 0,
647 PIPE_TRANSFER_WRITE
|
648 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
651 ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR
);
653 This
->cursor
.hotspot
.x
= XHotSpot
;
654 This
->cursor
.hotspot
.y
= YHotSpot
;
656 /* Copy cursor image to internal storage. */
660 const struct util_format_description
*sfmt
=
661 util_format_description(surf
->base
.info
.format
);
664 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, D3DLOCK_READONLY
);
666 ret_err("Failed to map cursor source image.\n",
667 D3DERR_DRIVERINTERNALERROR
);
669 sfmt
->unpack_rgba_8unorm(ptr
, transfer
->stride
,
670 lock
.pBits
, lock
.Pitch
,
671 This
->cursor
.w
, This
->cursor
.h
);
674 hw_cursor
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
,
676 &This
->cursor
.hotspot
,
677 This
->cursor
.visible
) == D3D_OK
;
679 NineSurface9_UnlockRect(surf
);
681 pipe
->transfer_unmap(pipe
, transfer
);
683 /* hide cursor if we emulate it */
685 ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, FALSE
);
686 This
->cursor
.software
= !hw_cursor
;
692 NineDevice9_SetCursorPosition( struct NineDevice9
*This
,
697 struct NineSwapChain9
*swap
= This
->swapchains
[0];
699 DBG("This=%p X=%d Y=%d Flags=%d\n", This
, X
, Y
, Flags
);
701 This
->cursor
.pos
.x
= X
;
702 This
->cursor
.pos
.y
= Y
;
704 if (!This
->cursor
.software
)
705 This
->cursor
.software
= ID3DPresent_SetCursorPos(swap
->present
, &This
->cursor
.pos
) != D3D_OK
;
709 NineDevice9_ShowCursor( struct NineDevice9
*This
,
712 BOOL old
= This
->cursor
.visible
;
714 DBG("This=%p bShow=%d\n", This
, (int) bShow
);
716 This
->cursor
.visible
= bShow
&& (This
->cursor
.hotspot
.x
!= -1);
717 if (!This
->cursor
.software
)
718 This
->cursor
.software
= ID3DPresent_SetCursor(This
->swapchains
[0]->present
, NULL
, NULL
, bShow
) != D3D_OK
;
724 NineDevice9_CreateAdditionalSwapChain( struct NineDevice9
*This
,
725 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
726 IDirect3DSwapChain9
**pSwapChain
)
728 struct NineSwapChain9
*swapchain
, *tmplt
= This
->swapchains
[0];
729 ID3DPresent
*present
;
732 DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",
733 This
, pPresentationParameters
, pSwapChain
);
735 user_assert(pPresentationParameters
, D3DERR_INVALIDCALL
);
736 user_assert(tmplt
->params
.Windowed
&& pPresentationParameters
->Windowed
, D3DERR_INVALIDCALL
);
738 /* TODO: this deserves more tests */
739 if (!pPresentationParameters
->hDeviceWindow
)
740 pPresentationParameters
->hDeviceWindow
= This
->params
.hFocusWindow
;
742 hr
= ID3DPresentGroup_CreateAdditionalPresent(This
->present
, pPresentationParameters
, &present
);
747 hr
= NineSwapChain9_new(This
, FALSE
, present
, pPresentationParameters
,
749 tmplt
->params
.hDeviceWindow
,
754 *pSwapChain
= (IDirect3DSwapChain9
*)swapchain
;
759 NineDevice9_GetSwapChain( struct NineDevice9
*This
,
761 IDirect3DSwapChain9
**pSwapChain
)
763 user_assert(pSwapChain
!= NULL
, D3DERR_INVALIDCALL
);
766 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
768 NineUnknown_AddRef(NineUnknown(This
->swapchains
[iSwapChain
]));
769 *pSwapChain
= (IDirect3DSwapChain9
*)This
->swapchains
[iSwapChain
];
775 NineDevice9_GetNumberOfSwapChains( struct NineDevice9
*This
)
777 return This
->nswapchains
;
781 NineDevice9_Reset( struct NineDevice9
*This
,
782 D3DPRESENT_PARAMETERS
*pPresentationParameters
)
787 DBG("This=%p pPresentationParameters=%p\n", This
, pPresentationParameters
);
789 if (NineSwapChain9_GetOccluded(This
->swapchains
[0])) {
790 This
->device_needs_reset
= TRUE
;
791 return D3DERR_DEVICELOST
;
794 for (i
= 0; i
< This
->nswapchains
; ++i
) {
795 D3DPRESENT_PARAMETERS
*params
= &pPresentationParameters
[i
];
796 hr
= NineSwapChain9_Resize(This
->swapchains
[i
], params
, NULL
);
801 nine_pipe_context_clear(This
);
802 nine_state_clear(&This
->state
, TRUE
);
804 NineDevice9_SetDefaultState(This
, TRUE
);
805 NineDevice9_SetRenderTarget(
806 This
, 0, (IDirect3DSurface9
*)This
->swapchains
[0]->buffers
[0]);
807 /* XXX: better use GetBackBuffer here ? */
809 This
->device_needs_reset
= (hr
!= D3D_OK
);
814 NineDevice9_Present( struct NineDevice9
*This
,
815 const RECT
*pSourceRect
,
816 const RECT
*pDestRect
,
817 HWND hDestWindowOverride
,
818 const RGNDATA
*pDirtyRegion
)
823 DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",
824 This
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
);
826 /* XXX is this right? */
827 for (i
= 0; i
< This
->nswapchains
; ++i
) {
828 hr
= NineSwapChain9_Present(This
->swapchains
[i
], pSourceRect
, pDestRect
,
829 hDestWindowOverride
, pDirtyRegion
, 0);
830 if (FAILED(hr
)) { return hr
; }
837 NineDevice9_GetBackBuffer( struct NineDevice9
*This
,
840 D3DBACKBUFFER_TYPE Type
,
841 IDirect3DSurface9
**ppBackBuffer
)
843 user_assert(ppBackBuffer
!= NULL
, D3DERR_INVALIDCALL
);
844 /* return NULL on error */
845 *ppBackBuffer
= NULL
;
846 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
848 return NineSwapChain9_GetBackBuffer(This
->swapchains
[iSwapChain
],
849 iBackBuffer
, Type
, ppBackBuffer
);
853 NineDevice9_GetRasterStatus( struct NineDevice9
*This
,
855 D3DRASTER_STATUS
*pRasterStatus
)
857 user_assert(pRasterStatus
!= NULL
, D3DERR_INVALIDCALL
);
858 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
860 return NineSwapChain9_GetRasterStatus(This
->swapchains
[iSwapChain
],
865 NineDevice9_SetDialogBoxMode( struct NineDevice9
*This
,
866 BOOL bEnableDialogs
)
868 STUB(D3DERR_INVALIDCALL
);
872 NineDevice9_SetGammaRamp( struct NineDevice9
*This
,
875 const D3DGAMMARAMP
*pRamp
)
877 DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This
,
878 iSwapChain
, Flags
, pRamp
);
880 user_warn(iSwapChain
>= This
->nswapchains
);
883 if (pRamp
&& (iSwapChain
< This
->nswapchains
)) {
884 struct NineSwapChain9
*swap
= This
->swapchains
[iSwapChain
];
885 swap
->gamma
= *pRamp
;
886 ID3DPresent_SetGammaRamp(swap
->present
, pRamp
, swap
->params
.hDeviceWindow
);
891 NineDevice9_GetGammaRamp( struct NineDevice9
*This
,
893 D3DGAMMARAMP
*pRamp
)
895 DBG("This=%p iSwapChain=%u pRamp=%p\n", This
, iSwapChain
, pRamp
);
897 user_warn(iSwapChain
>= This
->nswapchains
);
900 if (pRamp
&& (iSwapChain
< This
->nswapchains
))
901 *pRamp
= This
->swapchains
[iSwapChain
]->gamma
;
905 NineDevice9_CreateTexture( struct NineDevice9
*This
,
912 IDirect3DTexture9
**ppTexture
,
913 HANDLE
*pSharedHandle
)
915 struct NineTexture9
*tex
;
918 DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
919 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Levels
,
920 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
921 nine_D3DPOOL_to_str(Pool
), ppTexture
, pSharedHandle
);
923 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DMAP
|
924 D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
925 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
;
929 hr
= NineTexture9_new(This
, Width
, Height
, Levels
, Usage
, Format
, Pool
,
930 &tex
, pSharedHandle
);
932 *ppTexture
= (IDirect3DTexture9
*)tex
;
938 NineDevice9_CreateVolumeTexture( struct NineDevice9
*This
,
946 IDirect3DVolumeTexture9
**ppVolumeTexture
,
947 HANDLE
*pSharedHandle
)
949 struct NineVolumeTexture9
*tex
;
952 DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
953 "ppOut=%p pSharedHandle=%p\n", This
, Width
, Height
, Depth
, Levels
,
954 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
955 nine_D3DPOOL_to_str(Pool
), ppVolumeTexture
, pSharedHandle
);
957 Usage
&= D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
958 D3DUSAGE_SOFTWAREPROCESSING
;
960 *ppVolumeTexture
= NULL
;
962 hr
= NineVolumeTexture9_new(This
, Width
, Height
, Depth
, Levels
,
963 Usage
, Format
, Pool
, &tex
, pSharedHandle
);
965 *ppVolumeTexture
= (IDirect3DVolumeTexture9
*)tex
;
971 NineDevice9_CreateCubeTexture( struct NineDevice9
*This
,
977 IDirect3DCubeTexture9
**ppCubeTexture
,
978 HANDLE
*pSharedHandle
)
980 struct NineCubeTexture9
*tex
;
983 DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
984 "pSharedHandle=%p\n", This
, EdgeLength
, Levels
,
985 nine_D3DUSAGE_to_str(Usage
), d3dformat_to_string(Format
),
986 nine_D3DPOOL_to_str(Pool
), ppCubeTexture
, pSharedHandle
);
988 Usage
&= D3DUSAGE_AUTOGENMIPMAP
| D3DUSAGE_DEPTHSTENCIL
| D3DUSAGE_DYNAMIC
|
989 D3DUSAGE_NONSECURE
| D3DUSAGE_RENDERTARGET
|
990 D3DUSAGE_SOFTWAREPROCESSING
;
992 *ppCubeTexture
= NULL
;
994 hr
= NineCubeTexture9_new(This
, EdgeLength
, Levels
, Usage
, Format
, Pool
,
995 &tex
, pSharedHandle
);
997 *ppCubeTexture
= (IDirect3DCubeTexture9
*)tex
;
1003 NineDevice9_CreateVertexBuffer( struct NineDevice9
*This
,
1008 IDirect3DVertexBuffer9
**ppVertexBuffer
,
1009 HANDLE
*pSharedHandle
)
1011 struct NineVertexBuffer9
*buf
;
1013 D3DVERTEXBUFFER_DESC desc
;
1015 DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
1016 This
, Length
, Usage
, FVF
, Pool
, ppVertexBuffer
, pSharedHandle
);
1018 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1020 desc
.Format
= D3DFMT_VERTEXDATA
;
1021 desc
.Type
= D3DRTYPE_VERTEXBUFFER
;
1022 desc
.Usage
= Usage
&
1023 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1024 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1025 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_TEXTAPI
|
1026 D3DUSAGE_WRITEONLY
);
1031 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1032 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1034 hr
= NineVertexBuffer9_new(This
, &desc
, &buf
);
1036 *ppVertexBuffer
= (IDirect3DVertexBuffer9
*)buf
;
1041 NineDevice9_CreateIndexBuffer( struct NineDevice9
*This
,
1046 IDirect3DIndexBuffer9
**ppIndexBuffer
,
1047 HANDLE
*pSharedHandle
)
1049 struct NineIndexBuffer9
*buf
;
1051 D3DINDEXBUFFER_DESC desc
;
1053 DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
1054 "pSharedHandle=%p\n", This
, Length
, Usage
,
1055 d3dformat_to_string(Format
), Pool
, ppIndexBuffer
, pSharedHandle
);
1057 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_NOTAVAILABLE
);
1059 desc
.Format
= Format
;
1060 desc
.Type
= D3DRTYPE_INDEXBUFFER
;
1061 desc
.Usage
= Usage
&
1062 (D3DUSAGE_DONOTCLIP
| D3DUSAGE_DYNAMIC
| D3DUSAGE_NONSECURE
|
1063 D3DUSAGE_NPATCHES
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
|
1064 D3DUSAGE_SOFTWAREPROCESSING
| D3DUSAGE_WRITEONLY
);
1068 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1069 user_assert(desc
.Usage
== Usage
, D3DERR_INVALIDCALL
);
1071 hr
= NineIndexBuffer9_new(This
, &desc
, &buf
);
1073 *ppIndexBuffer
= (IDirect3DIndexBuffer9
*)buf
;
1078 create_zs_or_rt_surface(struct NineDevice9
*This
,
1079 unsigned type
, /* 0 = RT, 1 = ZS, 2 = plain */
1081 UINT Width
, UINT Height
,
1083 D3DMULTISAMPLE_TYPE MultiSample
,
1084 DWORD MultisampleQuality
,
1085 BOOL Discard_or_Lockable
,
1086 IDirect3DSurface9
**ppSurface
,
1087 HANDLE
*pSharedHandle
)
1089 struct NineSurface9
*surface
;
1090 struct pipe_screen
*screen
= This
->screen
;
1091 struct pipe_resource
*resource
= NULL
;
1093 D3DSURFACE_DESC desc
;
1094 struct pipe_resource templ
;
1096 DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
1097 "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
1098 This
, type
, nine_D3DPOOL_to_str(Pool
), Width
, Height
,
1099 d3dformat_to_string(Format
), MultiSample
, MultisampleQuality
,
1100 Discard_or_Lockable
, ppSurface
, pSharedHandle
);
1103 DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
1105 user_assert(Width
&& Height
, D3DERR_INVALIDCALL
);
1106 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1108 templ
.target
= PIPE_TEXTURE_2D
;
1109 templ
.width0
= Width
;
1110 templ
.height0
= Height
;
1112 templ
.array_size
= 1;
1113 templ
.last_level
= 0;
1114 templ
.nr_samples
= (unsigned)MultiSample
;
1115 templ
.usage
= PIPE_USAGE_DEFAULT
;
1117 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
; /* StretchRect */
1119 case 0: templ
.bind
|= PIPE_BIND_RENDER_TARGET
; break;
1120 case 1: templ
.bind
= d3d9_get_pipe_depth_format_bindings(Format
); break;
1125 templ
.format
= d3d9_to_pipe_format_checked(screen
, Format
, templ
.target
,
1126 templ
.nr_samples
, templ
.bind
,
1127 FALSE
, Pool
== D3DPOOL_SCRATCH
);
1129 if (templ
.format
== PIPE_FORMAT_NONE
&& Format
!= D3DFMT_NULL
)
1130 return D3DERR_INVALIDCALL
;
1132 desc
.Format
= Format
;
1133 desc
.Type
= D3DRTYPE_SURFACE
;
1136 desc
.MultiSampleType
= MultiSample
;
1137 desc
.MultiSampleQuality
= MultisampleQuality
;
1139 desc
.Height
= Height
;
1141 case 0: desc
.Usage
= D3DUSAGE_RENDERTARGET
; break;
1142 case 1: desc
.Usage
= D3DUSAGE_DEPTHSTENCIL
; break;
1146 if (compressed_format(Format
)) {
1147 const unsigned w
= util_format_get_blockwidth(templ
.format
);
1148 const unsigned h
= util_format_get_blockheight(templ
.format
);
1150 user_assert(!(Width
% w
) && !(Height
% h
), D3DERR_INVALIDCALL
);
1153 if (Pool
== D3DPOOL_DEFAULT
&& Format
!= D3DFMT_NULL
) {
1154 /* resource_create doesn't return an error code, so check format here */
1155 user_assert(templ
.format
!= PIPE_FORMAT_NONE
, D3DERR_INVALIDCALL
);
1156 resource
= screen
->resource_create(screen
, &templ
);
1157 user_assert(resource
, D3DERR_OUTOFVIDEOMEMORY
);
1158 if (Discard_or_Lockable
&& (desc
.Usage
& D3DUSAGE_RENDERTARGET
))
1159 resource
->flags
|= NINE_RESOURCE_FLAG_LOCKABLE
;
1163 hr
= NineSurface9_new(This
, NULL
, resource
, NULL
, 0, 0, 0, &desc
, &surface
);
1164 pipe_resource_reference(&resource
, NULL
);
1167 *ppSurface
= (IDirect3DSurface9
*)surface
;
1172 NineDevice9_CreateRenderTarget( struct NineDevice9
*This
,
1176 D3DMULTISAMPLE_TYPE MultiSample
,
1177 DWORD MultisampleQuality
,
1179 IDirect3DSurface9
**ppSurface
,
1180 HANDLE
*pSharedHandle
)
1183 return create_zs_or_rt_surface(This
, 0, D3DPOOL_DEFAULT
,
1184 Width
, Height
, Format
,
1185 MultiSample
, MultisampleQuality
,
1186 Lockable
, ppSurface
, pSharedHandle
);
1190 NineDevice9_CreateDepthStencilSurface( struct NineDevice9
*This
,
1194 D3DMULTISAMPLE_TYPE MultiSample
,
1195 DWORD MultisampleQuality
,
1197 IDirect3DSurface9
**ppSurface
,
1198 HANDLE
*pSharedHandle
)
1201 if (!depth_stencil_format(Format
))
1202 return D3DERR_NOTAVAILABLE
;
1203 return create_zs_or_rt_surface(This
, 1, D3DPOOL_DEFAULT
,
1204 Width
, Height
, Format
,
1205 MultiSample
, MultisampleQuality
,
1206 Discard
, ppSurface
, pSharedHandle
);
1210 NineDevice9_UpdateSurface( struct NineDevice9
*This
,
1211 IDirect3DSurface9
*pSourceSurface
,
1212 const RECT
*pSourceRect
,
1213 IDirect3DSurface9
*pDestinationSurface
,
1214 const POINT
*pDestPoint
)
1216 struct NineSurface9
*dst
= NineSurface9(pDestinationSurface
);
1217 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1218 int copy_width
, copy_height
;
1221 DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
1222 "pSourceRect=%p pDestPoint=%p\n", This
,
1223 pSourceSurface
, pDestinationSurface
, pSourceRect
, pDestPoint
);
1225 DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
1226 pSourceRect
->left
, pSourceRect
->top
,
1227 pSourceRect
->right
, pSourceRect
->bottom
);
1229 DBG("pDestPoint = (%u,%u)\n", pDestPoint
->x
, pDestPoint
->y
);
1231 user_assert(dst
&& src
, D3DERR_INVALIDCALL
);
1233 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1234 user_assert(src
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1236 user_assert(dst
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1237 user_assert(src
->desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, D3DERR_INVALIDCALL
);
1239 user_assert(!src
->lock_count
, D3DERR_INVALIDCALL
);
1240 user_assert(!dst
->lock_count
, D3DERR_INVALIDCALL
);
1242 user_assert(dst
->desc
.Format
== src
->desc
.Format
, D3DERR_INVALIDCALL
);
1243 user_assert(!depth_stencil_format(dst
->desc
.Format
), D3DERR_INVALIDCALL
);
1246 copy_width
= pSourceRect
->right
- pSourceRect
->left
;
1247 copy_height
= pSourceRect
->bottom
- pSourceRect
->top
;
1249 user_assert(pSourceRect
->left
>= 0 &&
1251 pSourceRect
->right
<= src
->desc
.Width
&&
1252 pSourceRect
->top
>= 0 &&
1254 pSourceRect
->bottom
<= src
->desc
.Height
,
1255 D3DERR_INVALIDCALL
);
1257 copy_width
= src
->desc
.Width
;
1258 copy_height
= src
->desc
.Height
;
1261 destRect
.right
= copy_width
;
1262 destRect
.bottom
= copy_height
;
1265 user_assert(pDestPoint
->x
>= 0 && pDestPoint
->y
>= 0,
1266 D3DERR_INVALIDCALL
);
1267 destRect
.right
+= pDestPoint
->x
;
1268 destRect
.bottom
+= pDestPoint
->y
;
1271 user_assert(destRect
.right
<= dst
->desc
.Width
&&
1272 destRect
.bottom
<= dst
->desc
.Height
,
1273 D3DERR_INVALIDCALL
);
1275 if (compressed_format(dst
->desc
.Format
)) {
1276 const unsigned w
= util_format_get_blockwidth(dst
->base
.info
.format
);
1277 const unsigned h
= util_format_get_blockheight(dst
->base
.info
.format
);
1280 user_assert(!(pDestPoint
->x
% w
) && !(pDestPoint
->y
% h
),
1281 D3DERR_INVALIDCALL
);
1285 user_assert(!(pSourceRect
->left
% w
) && !(pSourceRect
->top
% h
),
1286 D3DERR_INVALIDCALL
);
1288 if (!(copy_width
== src
->desc
.Width
&&
1289 copy_width
== dst
->desc
.Width
&&
1290 copy_height
== src
->desc
.Height
&&
1291 copy_height
== dst
->desc
.Height
)) {
1292 user_assert(!(copy_width
% w
) && !(copy_height
% h
),
1293 D3DERR_INVALIDCALL
);
1297 NineSurface9_CopyMemToDefault(dst
, src
, pDestPoint
, pSourceRect
);
1303 NineDevice9_UpdateTexture( struct NineDevice9
*This
,
1304 IDirect3DBaseTexture9
*pSourceTexture
,
1305 IDirect3DBaseTexture9
*pDestinationTexture
)
1307 struct NineBaseTexture9
*dstb
= NineBaseTexture9(pDestinationTexture
);
1308 struct NineBaseTexture9
*srcb
= NineBaseTexture9(pSourceTexture
);
1310 unsigned last_level
= dstb
->base
.info
.last_level
;
1313 DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This
,
1314 pSourceTexture
, pDestinationTexture
);
1316 user_assert(pSourceTexture
!= pDestinationTexture
, D3DERR_INVALIDCALL
);
1318 user_assert(dstb
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1319 user_assert(srcb
->base
.pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1321 if (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) {
1322 /* Only the first level is updated, the others regenerated. */
1324 /* if the source has D3DUSAGE_AUTOGENMIPMAP, we have to ignore
1325 * the sublevels, thus level 0 has to match */
1326 user_assert(!(srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) ||
1327 (srcb
->base
.info
.width0
== dstb
->base
.info
.width0
&&
1328 srcb
->base
.info
.height0
== dstb
->base
.info
.height0
&&
1329 srcb
->base
.info
.depth0
== dstb
->base
.info
.depth0
),
1330 D3DERR_INVALIDCALL
);
1332 user_assert(!(srcb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
), D3DERR_INVALIDCALL
);
1335 user_assert(dstb
->base
.type
== srcb
->base
.type
, D3DERR_INVALIDCALL
);
1337 /* Find src level that matches dst level 0: */
1338 user_assert(srcb
->base
.info
.width0
>= dstb
->base
.info
.width0
&&
1339 srcb
->base
.info
.height0
>= dstb
->base
.info
.height0
&&
1340 srcb
->base
.info
.depth0
>= dstb
->base
.info
.depth0
,
1341 D3DERR_INVALIDCALL
);
1342 for (m
= 0; m
<= srcb
->base
.info
.last_level
; ++m
) {
1343 unsigned w
= u_minify(srcb
->base
.info
.width0
, m
);
1344 unsigned h
= u_minify(srcb
->base
.info
.height0
, m
);
1345 unsigned d
= u_minify(srcb
->base
.info
.depth0
, m
);
1347 if (w
== dstb
->base
.info
.width0
&&
1348 h
== dstb
->base
.info
.height0
&&
1349 d
== dstb
->base
.info
.depth0
)
1352 user_assert(m
<= srcb
->base
.info
.last_level
, D3DERR_INVALIDCALL
);
1354 last_level
= MIN2(last_level
, srcb
->base
.info
.last_level
- m
);
1356 if (dstb
->base
.type
== D3DRTYPE_TEXTURE
) {
1357 struct NineTexture9
*dst
= NineTexture9(dstb
);
1358 struct NineTexture9
*src
= NineTexture9(srcb
);
1360 if (src
->dirty_rect
.width
== 0)
1363 pipe_box_to_rect(&rect
, &src
->dirty_rect
);
1364 for (l
= 0; l
< m
; ++l
)
1365 rect_minify_inclusive(&rect
);
1367 for (l
= 0; l
<= last_level
; ++l
, ++m
) {
1368 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1370 dst
->surfaces
[l
]->desc
.Width
,
1371 dst
->surfaces
[l
]->desc
.Height
);
1372 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
],
1376 rect_minify_inclusive(&rect
);
1378 u_box_origin_2d(0, 0, &src
->dirty_rect
);
1380 if (dstb
->base
.type
== D3DRTYPE_CUBETEXTURE
) {
1381 struct NineCubeTexture9
*dst
= NineCubeTexture9(dstb
);
1382 struct NineCubeTexture9
*src
= NineCubeTexture9(srcb
);
1385 /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
1386 for (z
= 0; z
< 6; ++z
) {
1387 if (src
->dirty_rect
[z
].width
== 0)
1390 pipe_box_to_rect(&rect
, &src
->dirty_rect
[z
]);
1391 for (l
= 0; l
< m
; ++l
)
1392 rect_minify_inclusive(&rect
);
1394 for (l
= 0; l
<= last_level
; ++l
, ++m
) {
1395 fit_rect_format_inclusive(dst
->base
.base
.info
.format
,
1397 dst
->surfaces
[l
* 6 + z
]->desc
.Width
,
1398 dst
->surfaces
[l
* 6 + z
]->desc
.Height
);
1399 NineSurface9_CopyMemToDefault(dst
->surfaces
[l
* 6 + z
],
1400 src
->surfaces
[m
* 6 + z
],
1403 rect_minify_inclusive(&rect
);
1405 u_box_origin_2d(0, 0, &src
->dirty_rect
[z
]);
1409 if (dstb
->base
.type
== D3DRTYPE_VOLUMETEXTURE
) {
1410 struct NineVolumeTexture9
*dst
= NineVolumeTexture9(dstb
);
1411 struct NineVolumeTexture9
*src
= NineVolumeTexture9(srcb
);
1413 if (src
->dirty_box
.width
== 0)
1415 for (l
= 0; l
<= last_level
; ++l
, ++m
)
1416 NineVolume9_CopyMemToDefault(dst
->volumes
[l
],
1417 src
->volumes
[m
], 0, 0, 0, NULL
);
1418 u_box_3d(0, 0, 0, 0, 0, 0, &src
->dirty_box
);
1420 assert(!"invalid texture type");
1423 if (dstb
->base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) {
1424 dstb
->dirty_mip
= TRUE
;
1425 NineBaseTexture9_GenerateMipSubLevels(dstb
);
1432 NineDevice9_GetRenderTargetData( struct NineDevice9
*This
,
1433 IDirect3DSurface9
*pRenderTarget
,
1434 IDirect3DSurface9
*pDestSurface
)
1436 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1437 struct NineSurface9
*src
= NineSurface9(pRenderTarget
);
1439 DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
1440 This
, pRenderTarget
, pDestSurface
);
1442 user_assert(dst
->desc
.Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1443 user_assert(src
->desc
.Pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1445 user_assert(dst
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1446 user_assert(src
->desc
.MultiSampleType
< 2, D3DERR_INVALIDCALL
);
1448 user_assert(src
->desc
.Width
== dst
->desc
.Width
, D3DERR_INVALIDCALL
);
1449 user_assert(src
->desc
.Height
== dst
->desc
.Height
, D3DERR_INVALIDCALL
);
1451 NineSurface9_CopyDefaultToMem(dst
, src
);
1457 NineDevice9_GetFrontBufferData( struct NineDevice9
*This
,
1459 IDirect3DSurface9
*pDestSurface
)
1461 DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This
,
1462 iSwapChain
, pDestSurface
);
1464 user_assert(pDestSurface
!= NULL
, D3DERR_INVALIDCALL
);
1465 user_assert(iSwapChain
< This
->nswapchains
, D3DERR_INVALIDCALL
);
1467 return NineSwapChain9_GetFrontBufferData(This
->swapchains
[iSwapChain
],
1472 NineDevice9_StretchRect( struct NineDevice9
*This
,
1473 IDirect3DSurface9
*pSourceSurface
,
1474 const RECT
*pSourceRect
,
1475 IDirect3DSurface9
*pDestSurface
,
1476 const RECT
*pDestRect
,
1477 D3DTEXTUREFILTERTYPE Filter
)
1479 struct pipe_screen
*screen
= This
->screen
;
1480 struct pipe_context
*pipe
= This
->pipe
;
1481 struct NineSurface9
*dst
= NineSurface9(pDestSurface
);
1482 struct NineSurface9
*src
= NineSurface9(pSourceSurface
);
1483 struct pipe_resource
*dst_res
= NineSurface9_GetResource(dst
);
1484 struct pipe_resource
*src_res
= NineSurface9_GetResource(src
);
1486 struct pipe_blit_info blit
;
1487 boolean scaled
, clamped
, ms
, flip_x
= FALSE
, flip_y
= FALSE
;
1489 DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
1490 "pDestRect=%p Filter=%u\n",
1491 This
, pSourceSurface
, pSourceRect
, pDestSurface
, pDestRect
, Filter
);
1493 DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
1494 pSourceRect
->left
, pSourceRect
->top
,
1495 pSourceRect
->right
, pSourceRect
->bottom
);
1497 DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect
->left
, pDestRect
->top
,
1498 pDestRect
->right
, pDestRect
->bottom
);
1500 user_assert(dst
->base
.pool
== D3DPOOL_DEFAULT
&&
1501 src
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1502 zs
= util_format_is_depth_or_stencil(dst_res
->format
);
1503 user_assert(!zs
|| !This
->in_scene
, D3DERR_INVALIDCALL
);
1504 user_assert(!zs
|| !pSourceRect
||
1505 (pSourceRect
->left
== 0 &&
1506 pSourceRect
->top
== 0 &&
1507 pSourceRect
->right
== src
->desc
.Width
&&
1508 pSourceRect
->bottom
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1509 user_assert(!zs
|| !pDestRect
||
1510 (pDestRect
->left
== 0 &&
1511 pDestRect
->top
== 0 &&
1512 pDestRect
->right
== dst
->desc
.Width
&&
1513 pDestRect
->bottom
== dst
->desc
.Height
), D3DERR_INVALIDCALL
);
1515 (dst
->desc
.Width
== src
->desc
.Width
&&
1516 dst
->desc
.Height
== src
->desc
.Height
), D3DERR_INVALIDCALL
);
1517 user_assert(zs
|| !util_format_is_depth_or_stencil(src_res
->format
),
1518 D3DERR_INVALIDCALL
);
1519 user_assert(!zs
|| dst
->desc
.Format
== src
->desc
.Format
,
1520 D3DERR_INVALIDCALL
);
1521 user_assert(screen
->is_format_supported(screen
, src_res
->format
,
1523 src_res
->nr_samples
,
1524 PIPE_BIND_SAMPLER_VIEW
),
1525 D3DERR_INVALIDCALL
);
1527 /* We might want to permit these, but wine thinks we shouldn't. */
1528 user_assert(!pDestRect
||
1529 (pDestRect
->left
<= pDestRect
->right
&&
1530 pDestRect
->top
<= pDestRect
->bottom
), D3DERR_INVALIDCALL
);
1531 user_assert(!pSourceRect
||
1532 (pSourceRect
->left
<= pSourceRect
->right
&&
1533 pSourceRect
->top
<= pSourceRect
->bottom
), D3DERR_INVALIDCALL
);
1535 memset(&blit
, 0, sizeof(blit
));
1536 blit
.dst
.resource
= dst_res
;
1537 blit
.dst
.level
= dst
->level
;
1538 blit
.dst
.box
.z
= dst
->layer
;
1539 blit
.dst
.box
.depth
= 1;
1540 blit
.dst
.format
= dst_res
->format
;
1542 flip_x
= pDestRect
->left
> pDestRect
->right
;
1544 blit
.dst
.box
.x
= pDestRect
->right
;
1545 blit
.dst
.box
.width
= pDestRect
->left
- pDestRect
->right
;
1547 blit
.dst
.box
.x
= pDestRect
->left
;
1548 blit
.dst
.box
.width
= pDestRect
->right
- pDestRect
->left
;
1550 flip_y
= pDestRect
->top
> pDestRect
->bottom
;
1552 blit
.dst
.box
.y
= pDestRect
->bottom
;
1553 blit
.dst
.box
.height
= pDestRect
->top
- pDestRect
->bottom
;
1555 blit
.dst
.box
.y
= pDestRect
->top
;
1556 blit
.dst
.box
.height
= pDestRect
->bottom
- pDestRect
->top
;
1561 blit
.dst
.box
.width
= dst
->desc
.Width
;
1562 blit
.dst
.box
.height
= dst
->desc
.Height
;
1564 blit
.src
.resource
= src_res
;
1565 blit
.src
.level
= src
->level
;
1566 blit
.src
.box
.z
= src
->layer
;
1567 blit
.src
.box
.depth
= 1;
1568 blit
.src
.format
= src_res
->format
;
1570 if (flip_x
^ (pSourceRect
->left
> pSourceRect
->right
)) {
1571 blit
.src
.box
.x
= pSourceRect
->right
;
1572 blit
.src
.box
.width
= pSourceRect
->left
- pSourceRect
->right
;
1574 blit
.src
.box
.x
= pSourceRect
->left
;
1575 blit
.src
.box
.width
= pSourceRect
->right
- pSourceRect
->left
;
1577 if (flip_y
^ (pSourceRect
->top
> pSourceRect
->bottom
)) {
1578 blit
.src
.box
.y
= pSourceRect
->bottom
;
1579 blit
.src
.box
.height
= pSourceRect
->top
- pSourceRect
->bottom
;
1581 blit
.src
.box
.y
= pSourceRect
->top
;
1582 blit
.src
.box
.height
= pSourceRect
->bottom
- pSourceRect
->top
;
1585 blit
.src
.box
.x
= flip_x
? src
->desc
.Width
: 0;
1586 blit
.src
.box
.y
= flip_y
? src
->desc
.Height
: 0;
1587 blit
.src
.box
.width
= flip_x
? -src
->desc
.Width
: src
->desc
.Width
;
1588 blit
.src
.box
.height
= flip_y
? -src
->desc
.Height
: src
->desc
.Height
;
1590 blit
.mask
= zs
? PIPE_MASK_ZS
: PIPE_MASK_RGBA
;
1591 blit
.filter
= Filter
== D3DTEXF_LINEAR
?
1592 PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
1593 blit
.scissor_enable
= FALSE
;
1594 blit
.alpha_blend
= FALSE
;
1596 /* If both of a src and dst dimension are negative, flip them. */
1597 if (blit
.dst
.box
.width
< 0 && blit
.src
.box
.width
< 0) {
1598 blit
.dst
.box
.width
= -blit
.dst
.box
.width
;
1599 blit
.src
.box
.width
= -blit
.src
.box
.width
;
1601 if (blit
.dst
.box
.height
< 0 && blit
.src
.box
.height
< 0) {
1602 blit
.dst
.box
.height
= -blit
.dst
.box
.height
;
1603 blit
.src
.box
.height
= -blit
.src
.box
.height
;
1606 blit
.dst
.box
.width
!= blit
.src
.box
.width
||
1607 blit
.dst
.box
.height
!= blit
.src
.box
.height
;
1609 user_assert(!scaled
|| dst
!= src
, D3DERR_INVALIDCALL
);
1610 user_assert(!scaled
||
1611 !NineSurface9_IsOffscreenPlain(dst
), D3DERR_INVALIDCALL
);
1612 user_assert(!NineSurface9_IsOffscreenPlain(dst
) ||
1613 NineSurface9_IsOffscreenPlain(src
), D3DERR_INVALIDCALL
);
1614 user_assert(NineSurface9_IsOffscreenPlain(dst
) ||
1615 dst
->desc
.Usage
& (D3DUSAGE_RENDERTARGET
| D3DUSAGE_DEPTHSTENCIL
),
1616 D3DERR_INVALIDCALL
);
1617 user_assert(!scaled
||
1618 (!util_format_is_compressed(dst
->base
.info
.format
) &&
1619 !util_format_is_compressed(src
->base
.info
.format
)),
1620 D3DERR_INVALIDCALL
);
1622 user_warn(src
== dst
&&
1623 u_box_test_intersection_2d(&blit
.src
.box
, &blit
.dst
.box
));
1625 /* Check for clipping/clamping: */
1627 struct pipe_box box
;
1630 xy
= u_box_clip_2d(&box
, &blit
.dst
.box
,
1631 dst
->desc
.Width
, dst
->desc
.Height
);
1635 xy
= u_box_clip_2d(&box
, &blit
.src
.box
,
1636 src
->desc
.Width
, src
->desc
.Height
);
1640 ms
= (dst
->desc
.MultiSampleType
| 1) != (src
->desc
.MultiSampleType
| 1);
1642 if (clamped
|| scaled
|| (blit
.dst
.format
!= blit
.src
.format
) || ms
) {
1643 DBG("using pipe->blit()\n");
1644 /* TODO: software scaling */
1645 user_assert(screen
->is_format_supported(screen
, dst_res
->format
,
1647 dst_res
->nr_samples
,
1648 zs
? PIPE_BIND_DEPTH_STENCIL
:
1649 PIPE_BIND_RENDER_TARGET
),
1650 D3DERR_INVALIDCALL
);
1652 pipe
->blit(pipe
, &blit
);
1654 assert(blit
.dst
.box
.x
>= 0 && blit
.dst
.box
.y
>= 0 &&
1655 blit
.src
.box
.x
>= 0 && blit
.src
.box
.y
>= 0 &&
1656 blit
.dst
.box
.x
+ blit
.dst
.box
.width
<= dst
->desc
.Width
&&
1657 blit
.src
.box
.x
+ blit
.src
.box
.width
<= src
->desc
.Width
&&
1658 blit
.dst
.box
.y
+ blit
.dst
.box
.height
<= dst
->desc
.Height
&&
1659 blit
.src
.box
.y
+ blit
.src
.box
.height
<= src
->desc
.Height
);
1660 /* Or drivers might crash ... */
1661 DBG("Using resource_copy_region.\n");
1662 pipe
->resource_copy_region(pipe
,
1663 blit
.dst
.resource
, blit
.dst
.level
,
1664 blit
.dst
.box
.x
, blit
.dst
.box
.y
, blit
.dst
.box
.z
,
1665 blit
.src
.resource
, blit
.src
.level
,
1669 /* Communicate the container it needs to update sublevels - if apply */
1670 NineSurface9_MarkContainerDirty(dst
);
1676 NineDevice9_ColorFill( struct NineDevice9
*This
,
1677 IDirect3DSurface9
*pSurface
,
1681 struct pipe_context
*pipe
= This
->pipe
;
1682 struct NineSurface9
*surf
= NineSurface9(pSurface
);
1683 struct pipe_surface
*psurf
;
1684 unsigned x
, y
, w
, h
;
1685 union pipe_color_union rgba
;
1688 DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This
,
1689 pSurface
, pRect
, color
);
1691 DBG("pRect=(%u,%u)-(%u,%u)\n", pRect
->left
, pRect
->top
,
1692 pRect
->right
, pRect
->bottom
);
1694 user_assert(surf
->base
.pool
== D3DPOOL_DEFAULT
, D3DERR_INVALIDCALL
);
1696 user_assert((surf
->base
.usage
& D3DUSAGE_RENDERTARGET
) ||
1697 NineSurface9_IsOffscreenPlain(surf
), D3DERR_INVALIDCALL
);
1699 user_assert(surf
->desc
.Format
!= D3DFMT_NULL
, D3D_OK
);
1704 w
= pRect
->right
- pRect
->left
;
1705 h
= pRect
->bottom
- pRect
->top
;
1709 w
= surf
->desc
.Width
;
1710 h
= surf
->desc
.Height
;
1712 d3dcolor_to_pipe_color_union(&rgba
, color
);
1714 fallback
= !(surf
->base
.info
.bind
& PIPE_BIND_RENDER_TARGET
);
1717 psurf
= NineSurface9_GetSurface(surf
, 0);
1723 pipe
->clear_render_target(pipe
, psurf
, &rgba
, x
, y
, w
, h
);
1725 D3DLOCKED_RECT lock
;
1726 union util_color uc
;
1728 /* XXX: lock pRect and fix util_fill_rect */
1729 hr
= NineSurface9_LockRect(surf
, &lock
, NULL
, 0);
1732 util_pack_color_ub(color
>> 16, color
>> 8, color
>> 0, color
>> 24,
1733 surf
->base
.info
.format
, &uc
);
1734 util_fill_rect(lock
.pBits
, surf
->base
.info
.format
,lock
.Pitch
,
1736 NineSurface9_UnlockRect(surf
);
1743 NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9
*This
,
1748 IDirect3DSurface9
**ppSurface
,
1749 HANDLE
*pSharedHandle
)
1753 DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
1754 "ppSurface=%p pSharedHandle=%p\n", This
,
1755 Width
, Height
, d3dformat_to_string(Format
), Format
, Pool
,
1756 ppSurface
, pSharedHandle
);
1759 user_assert(!pSharedHandle
|| Pool
== D3DPOOL_DEFAULT
1760 || Pool
== D3DPOOL_SYSTEMMEM
, D3DERR_INVALIDCALL
);
1761 user_assert(Pool
!= D3DPOOL_MANAGED
, D3DERR_INVALIDCALL
);
1763 /* Can be used with StretchRect and ColorFill. It's also always lockable.
1765 hr
= create_zs_or_rt_surface(This
, 2, Pool
, Width
, Height
,
1767 D3DMULTISAMPLE_NONE
, 0,
1769 ppSurface
, pSharedHandle
);
1771 DBG("Failed to create surface.\n");
1776 NineDevice9_SetRenderTarget( struct NineDevice9
*This
,
1777 DWORD RenderTargetIndex
,
1778 IDirect3DSurface9
*pRenderTarget
)
1780 struct NineSurface9
*rt
= NineSurface9(pRenderTarget
);
1781 const unsigned i
= RenderTargetIndex
;
1783 DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This
,
1784 RenderTargetIndex
, pRenderTarget
);
1786 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1787 user_assert(i
!= 0 || pRenderTarget
, D3DERR_INVALIDCALL
);
1788 user_assert(!pRenderTarget
||
1789 rt
->desc
.Usage
& D3DUSAGE_RENDERTARGET
, D3DERR_INVALIDCALL
);
1792 This
->state
.viewport
.X
= 0;
1793 This
->state
.viewport
.Y
= 0;
1794 This
->state
.viewport
.Width
= rt
->desc
.Width
;
1795 This
->state
.viewport
.Height
= rt
->desc
.Height
;
1796 This
->state
.viewport
.MinZ
= 0.0f
;
1797 This
->state
.viewport
.MaxZ
= 1.0f
;
1799 This
->state
.scissor
.minx
= 0;
1800 This
->state
.scissor
.miny
= 0;
1801 This
->state
.scissor
.maxx
= rt
->desc
.Width
;
1802 This
->state
.scissor
.maxy
= rt
->desc
.Height
;
1804 This
->state
.changed
.group
|= NINE_STATE_VIEWPORT
| NINE_STATE_SCISSOR
;
1807 if (This
->state
.rt
[i
] != NineSurface9(pRenderTarget
)) {
1808 nine_bind(&This
->state
.rt
[i
], pRenderTarget
);
1809 This
->state
.changed
.group
|= NINE_STATE_FB
;
1815 NineDevice9_GetRenderTarget( struct NineDevice9
*This
,
1816 DWORD RenderTargetIndex
,
1817 IDirect3DSurface9
**ppRenderTarget
)
1819 const unsigned i
= RenderTargetIndex
;
1821 user_assert(i
< This
->caps
.NumSimultaneousRTs
, D3DERR_INVALIDCALL
);
1822 user_assert(ppRenderTarget
, D3DERR_INVALIDCALL
);
1824 *ppRenderTarget
= (IDirect3DSurface9
*)This
->state
.rt
[i
];
1825 if (!This
->state
.rt
[i
])
1826 return D3DERR_NOTFOUND
;
1828 NineUnknown_AddRef(NineUnknown(This
->state
.rt
[i
]));
1833 NineDevice9_SetDepthStencilSurface( struct NineDevice9
*This
,
1834 IDirect3DSurface9
*pNewZStencil
)
1836 DBG("This=%p pNewZStencil=%p\n", This
, pNewZStencil
);
1838 if (This
->state
.ds
!= NineSurface9(pNewZStencil
)) {
1839 nine_bind(&This
->state
.ds
, pNewZStencil
);
1840 This
->state
.changed
.group
|= NINE_STATE_FB
;
1846 NineDevice9_GetDepthStencilSurface( struct NineDevice9
*This
,
1847 IDirect3DSurface9
**ppZStencilSurface
)
1849 user_assert(ppZStencilSurface
, D3DERR_INVALIDCALL
);
1851 *ppZStencilSurface
= (IDirect3DSurface9
*)This
->state
.ds
;
1852 if (!This
->state
.ds
)
1853 return D3DERR_NOTFOUND
;
1855 NineUnknown_AddRef(NineUnknown(This
->state
.ds
));
1860 NineDevice9_BeginScene( struct NineDevice9
*This
)
1862 DBG("This=%p\n", This
);
1863 user_assert(!This
->in_scene
, D3DERR_INVALIDCALL
);
1864 This
->in_scene
= TRUE
;
1865 /* Do we want to do anything else here ? */
1870 NineDevice9_EndScene( struct NineDevice9
*This
)
1872 DBG("This=%p\n", This
);
1873 user_assert(This
->in_scene
, D3DERR_INVALIDCALL
);
1874 This
->in_scene
= FALSE
;
1879 NineDevice9_Clear( struct NineDevice9
*This
,
1881 const D3DRECT
*pRects
,
1887 const int sRGB
= This
->state
.rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
1888 struct pipe_surface
*cbuf
, *zsbuf
;
1889 struct pipe_context
*pipe
= This
->pipe
;
1890 struct NineSurface9
*zsbuf_surf
= This
->state
.ds
;
1891 struct NineSurface9
*rt
;
1894 union pipe_color_union rgba
;
1895 unsigned rt_mask
= 0;
1898 DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
1899 This
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
1901 user_assert(This
->state
.ds
|| !(Flags
& NINED3DCLEAR_DEPTHSTENCIL
),
1902 D3DERR_INVALIDCALL
);
1903 user_assert(!(Flags
& D3DCLEAR_STENCIL
) ||
1905 util_format_is_depth_and_stencil(zsbuf_surf
->base
.info
.format
)),
1906 D3DERR_INVALIDCALL
);
1908 user_assert((Count
&& pRects
) || (!Count
&& !pRects
), D3DERR_INVALIDCALL
);
1910 user_warn((pRects
&& !Count
) || (!pRects
&& Count
));
1911 if (pRects
&& !Count
)
1917 nine_update_state_framebuffer_clear(This
);
1919 if (Flags
& D3DCLEAR_TARGET
) bufs
|= PIPE_CLEAR_COLOR
;
1920 /* Ignore Z buffer if not bound */
1921 if (This
->state
.fb
.zsbuf
!= NULL
) {
1922 if (Flags
& D3DCLEAR_ZBUFFER
) bufs
|= PIPE_CLEAR_DEPTH
;
1923 if (Flags
& D3DCLEAR_STENCIL
) bufs
|= PIPE_CLEAR_STENCIL
;
1927 d3dcolor_to_pipe_color_union(&rgba
, Color
);
1929 rect
.x1
= This
->state
.viewport
.X
;
1930 rect
.y1
= This
->state
.viewport
.Y
;
1931 rect
.x2
= This
->state
.viewport
.Width
+ rect
.x1
;
1932 rect
.y2
= This
->state
.viewport
.Height
+ rect
.y1
;
1934 /* Both rectangles apply, which is weird, but that's D3D9. */
1935 if (This
->state
.rs
[D3DRS_SCISSORTESTENABLE
]) {
1936 rect
.x1
= MAX2(rect
.x1
, This
->state
.scissor
.minx
);
1937 rect
.y1
= MAX2(rect
.y1
, This
->state
.scissor
.miny
);
1938 rect
.x2
= MIN2(rect
.x2
, This
->state
.scissor
.maxx
);
1939 rect
.y2
= MIN2(rect
.y2
, This
->state
.scissor
.maxy
);
1943 /* Maybe apps like to specify a large rect ? */
1944 if (pRects
[0].x1
<= rect
.x1
&& pRects
[0].x2
>= rect
.x2
&&
1945 pRects
[0].y1
<= rect
.y1
&& pRects
[0].y2
>= rect
.y2
) {
1946 DBG("First rect covers viewport.\n");
1952 if (rect
.x1
>= This
->state
.fb
.width
|| rect
.y1
>= This
->state
.fb
.height
)
1955 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
1956 if (This
->state
.rt
[i
] && This
->state
.rt
[i
]->desc
.Format
!= D3DFMT_NULL
)
1960 /* fast path, clears everything at once */
1962 (!(bufs
& PIPE_CLEAR_COLOR
) || (rt_mask
== This
->state
.rt_mask
)) &&
1963 rect
.x1
== 0 && rect
.y1
== 0 &&
1964 /* Case we clear only render target. Check clear region vs rt. */
1965 ((!(bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
1966 rect
.x2
>= This
->state
.fb
.width
&&
1967 rect
.y2
>= This
->state
.fb
.height
) ||
1968 /* Case we clear depth buffer (and eventually rt too).
1969 * depth buffer size is always >= rt size. Compare to clear region */
1970 ((bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
1971 rect
.x2
>= zsbuf_surf
->desc
.Width
&&
1972 rect
.y2
>= zsbuf_surf
->desc
.Height
))) {
1973 DBG("Clear fast path\n");
1974 pipe
->clear(pipe
, bufs
, &rgba
, Z
, Stencil
);
1983 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
1984 rt
= This
->state
.rt
[i
];
1985 if (!rt
|| rt
->desc
.Format
== D3DFMT_NULL
||
1986 !(Flags
& D3DCLEAR_TARGET
))
1987 continue; /* save space, compiler should hoist this */
1988 cbuf
= NineSurface9_GetSurface(rt
, sRGB
);
1989 for (r
= 0; r
< Count
; ++r
) {
1990 /* Don't trust users to pass these in the right order. */
1991 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
1992 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
1993 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
1994 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
1996 /* Drop negative rectangles (like wine expects). */
1997 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
1998 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2001 x1
= MAX2(x1
, rect
.x1
);
2002 y1
= MAX2(y1
, rect
.y1
);
2003 x2
= MIN3(x2
, rect
.x2
, rt
->desc
.Width
);
2004 y2
= MIN3(y2
, rect
.y2
, rt
->desc
.Height
);
2006 DBG("Clearing (%u..%u)x(%u..%u)\n", x1
, x2
, y1
, y2
);
2007 pipe
->clear_render_target(pipe
, cbuf
, &rgba
,
2008 x1
, y1
, x2
- x1
, y2
- y1
);
2011 if (!(Flags
& NINED3DCLEAR_DEPTHSTENCIL
))
2014 bufs
&= PIPE_CLEAR_DEPTHSTENCIL
;
2016 for (r
= 0; r
< Count
; ++r
) {
2017 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2018 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2019 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2020 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2022 /* Drop negative rectangles. */
2023 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2024 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2027 x1
= MIN2(x1
, rect
.x1
);
2028 y1
= MIN2(y1
, rect
.y1
);
2029 x2
= MIN3(x2
, rect
.x2
, zsbuf_surf
->desc
.Width
);
2030 y2
= MIN3(y2
, rect
.y2
, zsbuf_surf
->desc
.Height
);
2032 zsbuf
= NineSurface9_GetSurface(zsbuf_surf
, 0);
2034 pipe
->clear_depth_stencil(pipe
, zsbuf
, bufs
, Z
, Stencil
,
2035 x1
, y1
, x2
- x1
, y2
- y1
);
2041 NineDevice9_SetTransform( struct NineDevice9
*This
,
2042 D3DTRANSFORMSTATETYPE State
,
2043 const D3DMATRIX
*pMatrix
)
2045 struct nine_state
*state
= This
->update
;
2046 D3DMATRIX
*M
= nine_state_access_transform(state
, State
, TRUE
);
2048 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2050 user_assert(M
, D3DERR_INVALIDCALL
);
2053 state
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
2054 state
->changed
.group
|= NINE_STATE_FF
;
2060 NineDevice9_GetTransform( struct NineDevice9
*This
,
2061 D3DTRANSFORMSTATETYPE State
,
2062 D3DMATRIX
*pMatrix
)
2064 D3DMATRIX
*M
= nine_state_access_transform(&This
->state
, State
, FALSE
);
2065 user_assert(M
, D3DERR_INVALIDCALL
);
2071 NineDevice9_MultiplyTransform( struct NineDevice9
*This
,
2072 D3DTRANSFORMSTATETYPE State
,
2073 const D3DMATRIX
*pMatrix
)
2075 struct nine_state
*state
= This
->update
;
2077 D3DMATRIX
*M
= nine_state_access_transform(state
, State
, TRUE
);
2079 DBG("This=%p State=%d pMatrix=%p\n", This
, State
, pMatrix
);
2081 user_assert(M
, D3DERR_INVALIDCALL
);
2083 nine_d3d_matrix_matrix_mul(&T
, pMatrix
, M
);
2084 return NineDevice9_SetTransform(This
, State
, &T
);
2088 NineDevice9_SetViewport( struct NineDevice9
*This
,
2089 const D3DVIEWPORT9
*pViewport
)
2091 struct nine_state
*state
= This
->update
;
2093 DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
2094 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
,
2095 pViewport
->MinZ
, pViewport
->MaxZ
);
2097 state
->viewport
= *pViewport
;
2098 state
->changed
.group
|= NINE_STATE_VIEWPORT
;
2104 NineDevice9_GetViewport( struct NineDevice9
*This
,
2105 D3DVIEWPORT9
*pViewport
)
2107 *pViewport
= This
->state
.viewport
;
2112 NineDevice9_SetMaterial( struct NineDevice9
*This
,
2113 const D3DMATERIAL9
*pMaterial
)
2115 struct nine_state
*state
= This
->update
;
2117 DBG("This=%p pMaterial=%p\n", This
, pMaterial
);
2119 nine_dump_D3DMATERIAL9(DBG_FF
, pMaterial
);
2121 user_assert(pMaterial
, E_POINTER
);
2123 state
->ff
.material
= *pMaterial
;
2124 state
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
2130 NineDevice9_GetMaterial( struct NineDevice9
*This
,
2131 D3DMATERIAL9
*pMaterial
)
2133 user_assert(pMaterial
, E_POINTER
);
2134 *pMaterial
= This
->state
.ff
.material
;
2139 NineDevice9_SetLight( struct NineDevice9
*This
,
2141 const D3DLIGHT9
*pLight
)
2143 struct nine_state
*state
= This
->update
;
2145 DBG("This=%p Index=%u pLight=%p\n", This
, Index
, pLight
);
2147 nine_dump_D3DLIGHT9(DBG_FF
, pLight
);
2149 user_assert(pLight
, D3DERR_INVALIDCALL
);
2150 user_assert(pLight
->Type
< NINED3DLIGHT_INVALID
, D3DERR_INVALIDCALL
);
2152 user_assert(Index
< NINE_MAX_LIGHTS
, D3DERR_INVALIDCALL
); /* sanity */
2154 if (Index
>= state
->ff
.num_lights
) {
2155 unsigned n
= state
->ff
.num_lights
;
2156 unsigned N
= Index
+ 1;
2158 state
->ff
.light
= REALLOC(state
->ff
.light
, n
* sizeof(D3DLIGHT9
),
2159 N
* sizeof(D3DLIGHT9
));
2160 if (!state
->ff
.light
)
2161 return E_OUTOFMEMORY
;
2162 state
->ff
.num_lights
= N
;
2164 for (; n
< Index
; ++n
) {
2165 memset(&state
->ff
.light
[n
], 0, sizeof(D3DLIGHT9
));
2166 state
->ff
.light
[n
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
2169 state
->ff
.light
[Index
] = *pLight
;
2171 if (pLight
->Type
== D3DLIGHT_SPOT
&& pLight
->Theta
>= pLight
->Phi
) {
2172 DBG("Warning: clamping D3DLIGHT9.Theta\n");
2173 state
->ff
.light
[Index
].Theta
= state
->ff
.light
[Index
].Phi
;
2175 if (pLight
->Type
!= D3DLIGHT_DIRECTIONAL
&&
2176 pLight
->Attenuation0
== 0.0f
&&
2177 pLight
->Attenuation1
== 0.0f
&&
2178 pLight
->Attenuation2
== 0.0f
) {
2179 DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
2182 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2188 NineDevice9_GetLight( struct NineDevice9
*This
,
2192 const struct nine_state
*state
= &This
->state
;
2194 user_assert(pLight
, D3DERR_INVALIDCALL
);
2195 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2196 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2197 D3DERR_INVALIDCALL
);
2199 *pLight
= state
->ff
.light
[Index
];
2205 NineDevice9_LightEnable( struct NineDevice9
*This
,
2209 struct nine_state
*state
= This
->update
;
2212 DBG("This=%p Index=%u Enable=%i\n", This
, Index
, Enable
);
2214 if (Index
>= state
->ff
.num_lights
||
2215 state
->ff
.light
[Index
].Type
== NINED3DLIGHT_INVALID
) {
2216 /* This should create a default light. */
2218 memset(&light
, 0, sizeof(light
));
2219 light
.Type
= D3DLIGHT_DIRECTIONAL
;
2220 light
.Diffuse
.r
= 1.0f
;
2221 light
.Diffuse
.g
= 1.0f
;
2222 light
.Diffuse
.b
= 1.0f
;
2223 light
.Direction
.z
= 1.0f
;
2224 NineDevice9_SetLight(This
, Index
, &light
);
2226 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2228 for (i
= 0; i
< state
->ff
.num_lights_active
; ++i
) {
2229 if (state
->ff
.active_light
[i
] == Index
)
2234 if (i
< state
->ff
.num_lights_active
)
2236 /* XXX wine thinks this should still succeed:
2238 user_assert(i
< NINE_MAX_LIGHTS_ACTIVE
, D3DERR_INVALIDCALL
);
2240 state
->ff
.active_light
[i
] = Index
;
2241 state
->ff
.num_lights_active
++;
2243 if (i
== state
->ff
.num_lights_active
)
2245 --state
->ff
.num_lights_active
;
2246 for (; i
< state
->ff
.num_lights_active
; ++i
)
2247 state
->ff
.active_light
[i
] = state
->ff
.active_light
[i
+ 1];
2249 state
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
2255 NineDevice9_GetLightEnable( struct NineDevice9
*This
,
2259 const struct nine_state
*state
= &This
->state
;
2262 user_assert(Index
< state
->ff
.num_lights
, D3DERR_INVALIDCALL
);
2263 user_assert(state
->ff
.light
[Index
].Type
< NINED3DLIGHT_INVALID
,
2264 D3DERR_INVALIDCALL
);
2266 for (i
= 0; i
< state
->ff
.num_lights_active
; ++i
)
2267 if (state
->ff
.active_light
[i
] == Index
)
2270 *pEnable
= i
!= state
->ff
.num_lights_active
? 128 : 0; // Taken from wine
2276 NineDevice9_SetClipPlane( struct NineDevice9
*This
,
2278 const float *pPlane
)
2280 struct nine_state
*state
= This
->update
;
2282 user_assert(pPlane
, D3DERR_INVALIDCALL
);
2284 DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This
, Index
,
2285 pPlane
[0], pPlane
[1],
2286 pPlane
[2], pPlane
[3]);
2288 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2290 memcpy(&state
->clip
.ucp
[Index
][0], pPlane
, sizeof(state
->clip
.ucp
[0]));
2291 state
->changed
.ucp
|= 1 << Index
;
2297 NineDevice9_GetClipPlane( struct NineDevice9
*This
,
2301 const struct nine_state
*state
= &This
->state
;
2303 user_assert(Index
< PIPE_MAX_CLIP_PLANES
, D3DERR_INVALIDCALL
);
2305 memcpy(pPlane
, &state
->clip
.ucp
[Index
][0], sizeof(state
->clip
.ucp
[0]));
2309 #define RESZ_CODE 0x7fa05000
2312 NineDevice9_ResolveZ( struct NineDevice9
*This
)
2314 struct nine_state
*state
= &This
->state
;
2315 const struct util_format_description
*desc
;
2316 struct NineSurface9
*source
= state
->ds
;
2317 struct NineBaseTexture9
*destination
= state
->texture
[0];
2318 struct pipe_resource
*src
, *dst
;
2319 struct pipe_blit_info blit
;
2321 DBG("RESZ resolve\n");
2323 user_assert(source
&& destination
&&
2324 destination
->base
.type
== D3DRTYPE_TEXTURE
, D3DERR_INVALIDCALL
);
2326 src
= source
->base
.resource
;
2327 dst
= destination
->base
.resource
;
2329 user_assert(src
&& dst
, D3DERR_INVALIDCALL
);
2331 /* check dst is depth format. we know already for src */
2332 desc
= util_format_description(dst
->format
);
2333 user_assert(desc
->colorspace
== UTIL_FORMAT_COLORSPACE_ZS
, D3DERR_INVALIDCALL
);
2335 memset(&blit
, 0, sizeof(blit
));
2336 blit
.src
.resource
= src
;
2338 blit
.src
.format
= src
->format
;
2340 blit
.src
.box
.depth
= 1;
2343 blit
.src
.box
.width
= src
->width0
;
2344 blit
.src
.box
.height
= src
->height0
;
2346 blit
.dst
.resource
= dst
;
2348 blit
.dst
.format
= dst
->format
;
2350 blit
.dst
.box
.depth
= 1;
2353 blit
.dst
.box
.width
= dst
->width0
;
2354 blit
.dst
.box
.height
= dst
->height0
;
2356 blit
.mask
= PIPE_MASK_ZS
;
2357 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
2358 blit
.scissor_enable
= FALSE
;
2360 This
->pipe
->blit(This
->pipe
, &blit
);
2364 #define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1')
2365 #define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0')
2368 NineDevice9_SetRenderState( struct NineDevice9
*This
,
2369 D3DRENDERSTATETYPE State
,
2372 struct nine_state
*state
= This
->update
;
2374 DBG("This=%p State=%u(%s) Value=%08x\n", This
,
2375 State
, nine_d3drs_to_string(State
), Value
);
2377 user_assert(State
< D3DRS_COUNT
, D3DERR_INVALIDCALL
);
2379 if (state
->rs_advertised
[State
] == Value
&& likely(!This
->is_recording
))
2382 state
->rs_advertised
[State
] = Value
;
2384 /* Amd hacks (equivalent to GL extensions) */
2385 if (unlikely(State
== D3DRS_POINTSIZE
)) {
2386 if (Value
== RESZ_CODE
)
2387 return NineDevice9_ResolveZ(This
);
2389 if (Value
== ALPHA_TO_COVERAGE_ENABLE
||
2390 Value
== ALPHA_TO_COVERAGE_DISABLE
) {
2391 state
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== ALPHA_TO_COVERAGE_ENABLE
);
2392 state
->changed
.group
|= NINE_STATE_BLEND
;
2398 if (unlikely(State
== D3DRS_ADAPTIVETESS_Y
)) {
2399 if (Value
== D3DFMT_ATOC
|| (Value
== D3DFMT_UNKNOWN
&& state
->rs
[NINED3DRS_ALPHACOVERAGE
])) {
2400 state
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== D3DFMT_ATOC
);
2401 state
->changed
.group
|= NINE_STATE_BLEND
;
2406 state
->rs
[State
] = nine_fix_render_state_value(State
, Value
);
2407 state
->changed
.rs
[State
/ 32] |= 1 << (State
% 32);
2408 state
->changed
.group
|= nine_render_state_group
[State
];
2414 NineDevice9_GetRenderState( struct NineDevice9
*This
,
2415 D3DRENDERSTATETYPE State
,
2418 user_assert(State
< D3DRS_COUNT
, D3DERR_INVALIDCALL
);
2420 *pValue
= This
->state
.rs_advertised
[State
];
2425 NineDevice9_CreateStateBlock( struct NineDevice9
*This
,
2426 D3DSTATEBLOCKTYPE Type
,
2427 IDirect3DStateBlock9
**ppSB
)
2429 struct NineStateBlock9
*nsb
;
2430 struct nine_state
*dst
;
2432 enum nine_stateblock_type type
;
2435 DBG("This=%p Type=%u ppSB=%p\n", This
, Type
, ppSB
);
2437 user_assert(Type
== D3DSBT_ALL
||
2438 Type
== D3DSBT_VERTEXSTATE
||
2439 Type
== D3DSBT_PIXELSTATE
, D3DERR_INVALIDCALL
);
2442 case D3DSBT_VERTEXSTATE
: type
= NINESBT_VERTEXSTATE
; break;
2443 case D3DSBT_PIXELSTATE
: type
= NINESBT_PIXELSTATE
; break;
2449 hr
= NineStateBlock9_new(This
, &nsb
, type
);
2452 *ppSB
= (IDirect3DStateBlock9
*)nsb
;
2455 dst
->changed
.group
=
2456 NINE_STATE_TEXTURE
|
2459 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_VERTEXSTATE
) {
2460 dst
->changed
.group
|=
2461 NINE_STATE_FF_LIGHTING
|
2462 NINE_STATE_VS
| NINE_STATE_VS_CONST
|
2464 /* TODO: texture/sampler state */
2465 memcpy(dst
->changed
.rs
,
2466 nine_render_states_vertex
, sizeof(dst
->changed
.rs
));
2467 nine_ranges_insert(&dst
->changed
.vs_const_f
, 0, This
->max_vs_const_f
,
2469 dst
->changed
.vs_const_i
= 0xffff;
2470 dst
->changed
.vs_const_b
= 0xffff;
2471 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2472 dst
->changed
.sampler
[s
] |= 1 << D3DSAMP_DMAPOFFSET
;
2473 if (This
->state
.ff
.num_lights
) {
2474 dst
->ff
.num_lights
= This
->state
.ff
.num_lights
;
2475 /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
2476 * all currently existing lights will be captured
2478 dst
->ff
.light
= CALLOC(This
->state
.ff
.num_lights
,
2480 if (!dst
->ff
.light
) {
2481 nine_bind(ppSB
, NULL
);
2482 return E_OUTOFMEMORY
;
2486 if (Type
== D3DSBT_ALL
|| Type
== D3DSBT_PIXELSTATE
) {
2487 dst
->changed
.group
|=
2488 NINE_STATE_PS
| NINE_STATE_PS_CONST
;
2489 /* TODO: texture/sampler state */
2490 memcpy(dst
->changed
.rs
,
2491 nine_render_states_pixel
, sizeof(dst
->changed
.rs
));
2492 nine_ranges_insert(&dst
->changed
.ps_const_f
, 0, This
->max_ps_const_f
,
2494 dst
->changed
.ps_const_i
= 0xffff;
2495 dst
->changed
.ps_const_b
= 0xffff;
2496 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2497 dst
->changed
.sampler
[s
] |= 0x1ffe;
2499 if (Type
== D3DSBT_ALL
) {
2500 dst
->changed
.group
|=
2501 NINE_STATE_VIEWPORT
|
2502 NINE_STATE_SCISSOR
|
2503 NINE_STATE_RASTERIZER
|
2507 NINE_STATE_MATERIAL
|
2508 NINE_STATE_BLEND_COLOR
|
2509 NINE_STATE_SAMPLE_MASK
;
2510 memset(dst
->changed
.rs
, ~0, (D3DRS_COUNT
/ 32) * sizeof(uint32_t));
2511 dst
->changed
.rs
[D3DRS_LAST
/ 32] |= (1 << (D3DRS_COUNT
% 32)) - 1;
2512 dst
->changed
.vtxbuf
= (1ULL << This
->caps
.MaxStreams
) - 1;
2513 dst
->changed
.stream_freq
= dst
->changed
.vtxbuf
;
2514 dst
->changed
.ucp
= (1 << PIPE_MAX_CLIP_PLANES
) - 1;
2515 dst
->changed
.texture
= (1 << NINE_MAX_SAMPLERS
) - 1;
2517 NineStateBlock9_Capture(NineStateBlock9(*ppSB
));
2519 /* TODO: fixed function state */
2525 NineDevice9_BeginStateBlock( struct NineDevice9
*This
)
2529 DBG("This=%p\n", This
);
2531 user_assert(!This
->record
, D3DERR_INVALIDCALL
);
2533 hr
= NineStateBlock9_new(This
, &This
->record
, NINESBT_CUSTOM
);
2536 NineUnknown_ConvertRefToBind(NineUnknown(This
->record
));
2538 This
->update
= &This
->record
->state
;
2539 This
->is_recording
= TRUE
;
2545 NineDevice9_EndStateBlock( struct NineDevice9
*This
,
2546 IDirect3DStateBlock9
**ppSB
)
2548 DBG("This=%p ppSB=%p\n", This
, ppSB
);
2550 user_assert(This
->record
, D3DERR_INVALIDCALL
);
2552 This
->update
= &This
->state
;
2553 This
->is_recording
= FALSE
;
2555 NineUnknown_AddRef(NineUnknown(This
->record
));
2556 *ppSB
= (IDirect3DStateBlock9
*)This
->record
;
2557 NineUnknown_Unbind(NineUnknown(This
->record
));
2558 This
->record
= NULL
;
2564 NineDevice9_SetClipStatus( struct NineDevice9
*This
,
2565 const D3DCLIPSTATUS9
*pClipStatus
)
2567 STUB(D3DERR_INVALIDCALL
);
2571 NineDevice9_GetClipStatus( struct NineDevice9
*This
,
2572 D3DCLIPSTATUS9
*pClipStatus
)
2574 STUB(D3DERR_INVALIDCALL
);
2578 NineDevice9_GetTexture( struct NineDevice9
*This
,
2580 IDirect3DBaseTexture9
**ppTexture
)
2582 user_assert(Stage
< This
->caps
.MaxSimultaneousTextures
||
2583 Stage
== D3DDMAPSAMPLER
||
2584 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2585 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2586 user_assert(ppTexture
, D3DERR_INVALIDCALL
);
2588 if (Stage
>= D3DDMAPSAMPLER
)
2589 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2591 *ppTexture
= (IDirect3DBaseTexture9
*)This
->state
.texture
[Stage
];
2593 if (This
->state
.texture
[Stage
])
2594 NineUnknown_AddRef(NineUnknown(This
->state
.texture
[Stage
]));
2599 NineDevice9_SetTexture( struct NineDevice9
*This
,
2601 IDirect3DBaseTexture9
*pTexture
)
2603 struct nine_state
*state
= This
->update
;
2604 struct NineBaseTexture9
*tex
= NineBaseTexture9(pTexture
);
2606 DBG("This=%p Stage=%u pTexture=%p\n", This
, Stage
, pTexture
);
2608 user_assert(Stage
< This
->caps
.MaxSimultaneousTextures
||
2609 Stage
== D3DDMAPSAMPLER
||
2610 (Stage
>= D3DVERTEXTEXTURESAMPLER0
&&
2611 Stage
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2612 user_assert(!tex
|| (tex
->base
.pool
!= D3DPOOL_SCRATCH
&&
2613 tex
->base
.pool
!= D3DPOOL_SYSTEMMEM
), D3DERR_INVALIDCALL
);
2615 if (Stage
>= D3DDMAPSAMPLER
)
2616 Stage
= Stage
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2618 if (!This
->is_recording
) {
2619 struct NineBaseTexture9
*old
= state
->texture
[Stage
];
2623 state
->samplers_shadow
&= ~(1 << Stage
);
2625 state
->samplers_shadow
|= tex
->shadow
<< Stage
;
2627 if ((tex
->managed
.dirty
| tex
->dirty_mip
) && LIST_IS_EMPTY(&tex
->list
))
2628 list_add(&tex
->list
, &This
->update_textures
);
2635 nine_bind(&state
->texture
[Stage
], pTexture
);
2637 state
->changed
.texture
|= 1 << Stage
;
2638 state
->changed
.group
|= NINE_STATE_TEXTURE
;
2644 NineDevice9_GetTextureStageState( struct NineDevice9
*This
,
2646 D3DTEXTURESTAGESTATETYPE Type
,
2649 const struct nine_state
*state
= &This
->state
;
2651 user_assert(Stage
< Elements(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2652 user_assert(Type
< Elements(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2654 *pValue
= state
->ff
.tex_stage
[Stage
][Type
];
2660 NineDevice9_SetTextureStageState( struct NineDevice9
*This
,
2662 D3DTEXTURESTAGESTATETYPE Type
,
2665 struct nine_state
*state
= This
->update
;
2666 int bumpmap_index
= -1;
2668 DBG("Stage=%u Type=%u Value=%08x\n", Stage
, Type
, Value
);
2669 nine_dump_D3DTSS_value(DBG_FF
, Type
, Value
);
2671 user_assert(Stage
< Elements(state
->ff
.tex_stage
), D3DERR_INVALIDCALL
);
2672 user_assert(Type
< Elements(state
->ff
.tex_stage
[0]), D3DERR_INVALIDCALL
);
2674 state
->ff
.tex_stage
[Stage
][Type
] = Value
;
2676 case D3DTSS_BUMPENVMAT00
:
2677 bumpmap_index
= 4 * Stage
;
2679 case D3DTSS_BUMPENVMAT10
:
2680 bumpmap_index
= 4 * Stage
+ 1;
2682 case D3DTSS_BUMPENVMAT01
:
2683 bumpmap_index
= 4 * Stage
+ 2;
2685 case D3DTSS_BUMPENVMAT11
:
2686 bumpmap_index
= 4 * Stage
+ 3;
2688 case D3DTSS_BUMPENVLSCALE
:
2689 bumpmap_index
= 4 * 8 + 2 * Stage
;
2691 case D3DTSS_BUMPENVLOFFSET
:
2692 bumpmap_index
= 4 * 8 + 2 * Stage
+ 1;
2694 case D3DTSS_TEXTURETRANSFORMFLAGS
:
2695 state
->changed
.group
|= NINE_STATE_PS1X_SHADER
;
2701 if (bumpmap_index
>= 0) {
2702 state
->bumpmap_vars
[bumpmap_index
] = Value
;
2703 state
->changed
.group
|= NINE_STATE_PS_CONST
;
2706 state
->changed
.group
|= NINE_STATE_FF_PSSTAGES
;
2707 state
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
2713 NineDevice9_GetSamplerState( struct NineDevice9
*This
,
2715 D3DSAMPLERSTATETYPE Type
,
2718 user_assert(Sampler
< This
->caps
.MaxSimultaneousTextures
||
2719 Sampler
== D3DDMAPSAMPLER
||
2720 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2721 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2723 if (Sampler
>= D3DDMAPSAMPLER
)
2724 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2726 *pValue
= This
->state
.samp
[Sampler
][Type
];
2731 NineDevice9_SetSamplerState( struct NineDevice9
*This
,
2733 D3DSAMPLERSTATETYPE Type
,
2736 struct nine_state
*state
= This
->update
;
2738 DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This
,
2739 Sampler
, nine_D3DSAMP_to_str(Type
), Value
);
2741 user_assert(Sampler
< This
->caps
.MaxSimultaneousTextures
||
2742 Sampler
== D3DDMAPSAMPLER
||
2743 (Sampler
>= D3DVERTEXTEXTURESAMPLER0
&&
2744 Sampler
<= D3DVERTEXTEXTURESAMPLER3
), D3DERR_INVALIDCALL
);
2746 if (Sampler
>= D3DDMAPSAMPLER
)
2747 Sampler
= Sampler
- D3DDMAPSAMPLER
+ NINE_MAX_SAMPLERS_PS
;
2749 if (state
->samp
[Sampler
][Type
] != Value
|| unlikely(This
->is_recording
)) {
2750 state
->samp
[Sampler
][Type
] = Value
;
2751 state
->changed
.group
|= NINE_STATE_SAMPLER
;
2752 state
->changed
.sampler
[Sampler
] |= 1 << Type
;
2759 NineDevice9_ValidateDevice( struct NineDevice9
*This
,
2762 const struct nine_state
*state
= &This
->state
;
2764 unsigned w
= 0, h
= 0;
2766 DBG("This=%p pNumPasses=%p\n", This
, pNumPasses
);
2768 for (i
= 0; i
< Elements(state
->samp
); ++i
) {
2769 if (state
->samp
[i
][D3DSAMP_MINFILTER
] == D3DTEXF_NONE
||
2770 state
->samp
[i
][D3DSAMP_MAGFILTER
] == D3DTEXF_NONE
)
2771 return D3DERR_UNSUPPORTEDTEXTUREFILTER
;
2774 for (i
= 0; i
< This
->caps
.NumSimultaneousRTs
; ++i
) {
2778 w
= state
->rt
[i
]->desc
.Width
;
2779 h
= state
->rt
[i
]->desc
.Height
;
2781 if (state
->rt
[i
]->desc
.Width
!= w
|| state
->rt
[i
]->desc
.Height
!= h
) {
2782 return D3DERR_CONFLICTINGRENDERSTATE
;
2786 (state
->rs
[D3DRS_ZENABLE
] || state
->rs
[D3DRS_STENCILENABLE
])) {
2788 (state
->ds
->desc
.Width
!= w
|| state
->ds
->desc
.Height
!= h
))
2789 return D3DERR_CONFLICTINGRENDERSTATE
;
2799 NineDevice9_SetPaletteEntries( struct NineDevice9
*This
,
2801 const PALETTEENTRY
*pEntries
)
2803 STUB(D3D_OK
); /* like wine */
2807 NineDevice9_GetPaletteEntries( struct NineDevice9
*This
,
2809 PALETTEENTRY
*pEntries
)
2811 STUB(D3DERR_INVALIDCALL
);
2815 NineDevice9_SetCurrentTexturePalette( struct NineDevice9
*This
,
2816 UINT PaletteNumber
)
2818 STUB(D3D_OK
); /* like wine */
2822 NineDevice9_GetCurrentTexturePalette( struct NineDevice9
*This
,
2823 UINT
*PaletteNumber
)
2825 STUB(D3DERR_INVALIDCALL
);
2829 NineDevice9_SetScissorRect( struct NineDevice9
*This
,
2832 struct nine_state
*state
= This
->update
;
2834 DBG("x=(%u..%u) y=(%u..%u)\n",
2835 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
2837 state
->scissor
.minx
= pRect
->left
;
2838 state
->scissor
.miny
= pRect
->top
;
2839 state
->scissor
.maxx
= pRect
->right
;
2840 state
->scissor
.maxy
= pRect
->bottom
;
2842 state
->changed
.group
|= NINE_STATE_SCISSOR
;
2848 NineDevice9_GetScissorRect( struct NineDevice9
*This
,
2851 pRect
->left
= This
->state
.scissor
.minx
;
2852 pRect
->top
= This
->state
.scissor
.miny
;
2853 pRect
->right
= This
->state
.scissor
.maxx
;
2854 pRect
->bottom
= This
->state
.scissor
.maxy
;
2860 NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9
*This
,
2863 STUB(D3DERR_INVALIDCALL
);
2867 NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9
*This
)
2869 return !!(This
->params
.BehaviorFlags
& D3DCREATE_SOFTWARE_VERTEXPROCESSING
);
2873 NineDevice9_SetNPatchMode( struct NineDevice9
*This
,
2876 STUB(D3DERR_INVALIDCALL
);
2880 NineDevice9_GetNPatchMode( struct NineDevice9
*This
)
2886 init_draw_info(struct pipe_draw_info
*info
,
2887 struct NineDevice9
*dev
, D3DPRIMITIVETYPE type
, UINT count
)
2889 info
->mode
= d3dprimitivetype_to_pipe_prim(type
);
2890 info
->count
= prim_count_to_vertex_count(type
, count
);
2891 info
->start_instance
= 0;
2892 info
->instance_count
= 1;
2893 if (dev
->state
.stream_instancedata_mask
& dev
->state
.stream_usage_mask
)
2894 info
->instance_count
= MAX2(dev
->state
.stream_freq
[0] & 0x7FFFFF, 1);
2895 info
->primitive_restart
= FALSE
;
2896 info
->restart_index
= 0;
2897 info
->count_from_stream_output
= NULL
;
2898 info
->indirect
= NULL
;
2902 NineDevice9_DrawPrimitive( struct NineDevice9
*This
,
2903 D3DPRIMITIVETYPE PrimitiveType
,
2905 UINT PrimitiveCount
)
2907 struct pipe_draw_info info
;
2909 DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
2910 This
, PrimitiveType
, StartVertex
, PrimitiveCount
);
2912 nine_update_state(This
);
2914 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
2915 info
.indexed
= FALSE
;
2916 info
.start
= StartVertex
;
2917 info
.index_bias
= 0;
2918 info
.min_index
= info
.start
;
2919 info
.max_index
= info
.count
- 1;
2921 This
->pipe
->draw_vbo(This
->pipe
, &info
);
2927 NineDevice9_DrawIndexedPrimitive( struct NineDevice9
*This
,
2928 D3DPRIMITIVETYPE PrimitiveType
,
2929 INT BaseVertexIndex
,
2930 UINT MinVertexIndex
,
2933 UINT PrimitiveCount
)
2935 struct pipe_draw_info info
;
2937 DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
2938 "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
2939 This
, PrimitiveType
, BaseVertexIndex
, MinVertexIndex
, NumVertices
,
2940 StartIndex
, PrimitiveCount
);
2942 user_assert(This
->state
.idxbuf
, D3DERR_INVALIDCALL
);
2943 user_assert(This
->state
.vdecl
, D3DERR_INVALIDCALL
);
2945 nine_update_state(This
);
2947 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
2948 info
.indexed
= TRUE
;
2949 info
.start
= StartIndex
;
2950 info
.index_bias
= BaseVertexIndex
;
2951 /* These don't include index bias: */
2952 info
.min_index
= MinVertexIndex
;
2953 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2955 This
->pipe
->draw_vbo(This
->pipe
, &info
);
2961 NineDevice9_DrawPrimitiveUP( struct NineDevice9
*This
,
2962 D3DPRIMITIVETYPE PrimitiveType
,
2963 UINT PrimitiveCount
,
2964 const void *pVertexStreamZeroData
,
2965 UINT VertexStreamZeroStride
)
2967 struct pipe_vertex_buffer vtxbuf
;
2968 struct pipe_draw_info info
;
2970 DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
2971 This
, PrimitiveType
, PrimitiveCount
,
2972 pVertexStreamZeroData
, VertexStreamZeroStride
);
2974 user_assert(pVertexStreamZeroData
&& VertexStreamZeroStride
,
2975 D3DERR_INVALIDCALL
);
2977 nine_update_state(This
);
2979 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
2980 info
.indexed
= FALSE
;
2982 info
.index_bias
= 0;
2984 info
.max_index
= info
.count
- 1;
2986 vtxbuf
.stride
= VertexStreamZeroStride
;
2987 vtxbuf
.buffer_offset
= 0;
2988 vtxbuf
.buffer
= NULL
;
2989 vtxbuf
.user_buffer
= pVertexStreamZeroData
;
2991 if (!This
->driver_caps
.user_vbufs
) {
2992 u_upload_data(This
->vertex_uploader
,
2994 (info
.max_index
+ 1) * VertexStreamZeroStride
, /* XXX */
2997 &vtxbuf
.buffer_offset
,
2999 u_upload_unmap(This
->vertex_uploader
);
3000 vtxbuf
.user_buffer
= NULL
;
3003 This
->pipe
->set_vertex_buffers(This
->pipe
, 0, 1, &vtxbuf
);
3005 This
->pipe
->draw_vbo(This
->pipe
, &info
);
3007 NineDevice9_PauseRecording(This
);
3008 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
3009 NineDevice9_ResumeRecording(This
);
3011 pipe_resource_reference(&vtxbuf
.buffer
, NULL
);
3017 NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9
*This
,
3018 D3DPRIMITIVETYPE PrimitiveType
,
3019 UINT MinVertexIndex
,
3021 UINT PrimitiveCount
,
3022 const void *pIndexData
,
3023 D3DFORMAT IndexDataFormat
,
3024 const void *pVertexStreamZeroData
,
3025 UINT VertexStreamZeroStride
)
3027 struct pipe_draw_info info
;
3028 struct pipe_vertex_buffer vbuf
;
3029 struct pipe_index_buffer ibuf
;
3031 DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
3032 "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
3033 "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
3034 This
, PrimitiveType
, MinVertexIndex
, NumVertices
, PrimitiveCount
,
3035 pIndexData
, IndexDataFormat
,
3036 pVertexStreamZeroData
, VertexStreamZeroStride
);
3038 user_assert(pIndexData
&& pVertexStreamZeroData
, D3DERR_INVALIDCALL
);
3039 user_assert(VertexStreamZeroStride
, D3DERR_INVALIDCALL
);
3040 user_assert(IndexDataFormat
== D3DFMT_INDEX16
||
3041 IndexDataFormat
== D3DFMT_INDEX32
, D3DERR_INVALIDCALL
);
3043 nine_update_state(This
);
3045 init_draw_info(&info
, This
, PrimitiveType
, PrimitiveCount
);
3046 info
.indexed
= TRUE
;
3048 info
.index_bias
= 0;
3049 info
.min_index
= MinVertexIndex
;
3050 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
3052 vbuf
.stride
= VertexStreamZeroStride
;
3053 vbuf
.buffer_offset
= 0;
3055 vbuf
.user_buffer
= pVertexStreamZeroData
;
3057 ibuf
.index_size
= (IndexDataFormat
== D3DFMT_INDEX16
) ? 2 : 4;
3060 ibuf
.user_buffer
= pIndexData
;
3062 if (!This
->driver_caps
.user_vbufs
) {
3063 const unsigned base
= info
.min_index
* VertexStreamZeroStride
;
3064 u_upload_data(This
->vertex_uploader
,
3067 info
.min_index
+ 1) * VertexStreamZeroStride
, /* XXX */
3069 (const uint8_t *)vbuf
.user_buffer
+ base
,
3070 &vbuf
.buffer_offset
,
3072 u_upload_unmap(This
->vertex_uploader
);
3073 /* Won't be used: */
3074 vbuf
.buffer_offset
-= base
;
3075 vbuf
.user_buffer
= NULL
;
3077 if (!This
->driver_caps
.user_ibufs
) {
3078 u_upload_data(This
->index_uploader
,
3080 info
.count
* ibuf
.index_size
,
3085 u_upload_unmap(This
->index_uploader
);
3086 ibuf
.user_buffer
= NULL
;
3089 This
->pipe
->set_vertex_buffers(This
->pipe
, 0, 1, &vbuf
);
3090 This
->pipe
->set_index_buffer(This
->pipe
, &ibuf
);
3092 This
->pipe
->draw_vbo(This
->pipe
, &info
);
3094 pipe_resource_reference(&vbuf
.buffer
, NULL
);
3095 pipe_resource_reference(&ibuf
.buffer
, NULL
);
3097 NineDevice9_PauseRecording(This
);
3098 NineDevice9_SetIndices(This
, NULL
);
3099 NineDevice9_SetStreamSource(This
, 0, NULL
, 0, 0);
3100 NineDevice9_ResumeRecording(This
);
3105 /* TODO: Write to pDestBuffer directly if vertex declaration contains
3109 NineDevice9_ProcessVertices( struct NineDevice9
*This
,
3113 IDirect3DVertexBuffer9
*pDestBuffer
,
3114 IDirect3DVertexDeclaration9
*pVertexDecl
,
3117 struct pipe_screen
*screen
= This
->screen
;
3118 struct NineVertexDeclaration9
*vdecl
= NineVertexDeclaration9(pVertexDecl
);
3119 struct NineVertexShader9
*vs
;
3120 struct pipe_resource
*resource
;
3121 struct pipe_stream_output_target
*target
;
3122 struct pipe_draw_info draw
;
3124 unsigned buffer_offset
, buffer_size
;
3126 DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
3127 "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
3128 This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
,
3129 pVertexDecl
, Flags
);
3131 if (!screen
->get_param(screen
, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS
))
3132 STUB(D3DERR_INVALIDCALL
);
3134 nine_update_state(This
);
3136 /* TODO: Create shader with stream output. */
3137 STUB(D3DERR_INVALIDCALL
);
3138 struct NineVertexBuffer9
*dst
= NineVertexBuffer9(pDestBuffer
);
3140 vs
= This
->state
.vs
? This
->state
.vs
: This
->ff
.vs
;
3142 buffer_size
= VertexCount
* vs
->so
->stride
[0];
3144 struct pipe_resource templ
;
3146 templ
.target
= PIPE_BUFFER
;
3147 templ
.format
= PIPE_FORMAT_R8_UNORM
;
3148 templ
.width0
= buffer_size
;
3150 templ
.bind
= PIPE_BIND_STREAM_OUTPUT
;
3151 templ
.usage
= PIPE_USAGE_STREAM
;
3152 templ
.height0
= templ
.depth0
= templ
.array_size
= 1;
3153 templ
.last_level
= templ
.nr_samples
= 0;
3155 resource
= This
->screen
->resource_create(This
->screen
, &templ
);
3157 return E_OUTOFMEMORY
;
3160 /* SO matches vertex declaration */
3161 resource
= NineVertexBuffer9_GetResource(dst
);
3162 buffer_offset
= DestIndex
* vs
->so
->stride
[0];
3164 target
= This
->pipe
->create_stream_output_target(This
->pipe
, resource
,
3168 pipe_resource_reference(&resource
, NULL
);
3169 return D3DERR_DRIVERINTERNALERROR
;
3173 hr
= NineVertexDeclaration9_new_from_fvf(This
, dst
->desc
.FVF
, &vdecl
);
3178 init_draw_info(&draw
, This
, D3DPT_POINTLIST
, VertexCount
);
3179 draw
.instance_count
= 1;
3180 draw
.indexed
= FALSE
;
3181 draw
.start
= SrcStartIndex
;
3182 draw
.index_bias
= 0;
3183 draw
.min_index
= SrcStartIndex
;
3184 draw
.max_index
= SrcStartIndex
+ VertexCount
- 1;
3186 This
->pipe
->set_stream_output_targets(This
->pipe
, 1, &target
, 0);
3187 This
->pipe
->draw_vbo(This
->pipe
, &draw
);
3188 This
->pipe
->set_stream_output_targets(This
->pipe
, 0, NULL
, 0);
3189 This
->pipe
->stream_output_target_destroy(This
->pipe
, target
);
3191 hr
= NineVertexDeclaration9_ConvertStreamOutput(vdecl
,
3192 dst
, DestIndex
, VertexCount
,
3195 pipe_resource_reference(&resource
, NULL
);
3197 NineUnknown_Release(NineUnknown(vdecl
));
3202 NineDevice9_CreateVertexDeclaration( struct NineDevice9
*This
,
3203 const D3DVERTEXELEMENT9
*pVertexElements
,
3204 IDirect3DVertexDeclaration9
**ppDecl
)
3206 struct NineVertexDeclaration9
*vdecl
;
3208 DBG("This=%p pVertexElements=%p ppDecl=%p\n",
3209 This
, pVertexElements
, ppDecl
);
3211 HRESULT hr
= NineVertexDeclaration9_new(This
, pVertexElements
, &vdecl
);
3213 *ppDecl
= (IDirect3DVertexDeclaration9
*)vdecl
;
3219 NineDevice9_SetVertexDeclaration( struct NineDevice9
*This
,
3220 IDirect3DVertexDeclaration9
*pDecl
)
3222 struct nine_state
*state
= This
->update
;
3223 BOOL was_programmable_vs
= This
->state
.programmable_vs
;
3225 DBG("This=%p pDecl=%p\n", This
, pDecl
);
3227 if (likely(!This
->is_recording
) && state
->vdecl
== NineVertexDeclaration9(pDecl
))
3230 nine_bind(&state
->vdecl
, pDecl
);
3232 This
->state
.programmable_vs
= This
->state
.vs
&& !(This
->state
.vdecl
&& This
->state
.vdecl
->position_t
);
3233 if (likely(!This
->is_recording
) && was_programmable_vs
!= This
->state
.programmable_vs
) {
3234 state
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
3235 state
->changed
.group
|= NINE_STATE_VS
;
3238 state
->changed
.group
|= NINE_STATE_VDECL
;
3244 NineDevice9_GetVertexDeclaration( struct NineDevice9
*This
,
3245 IDirect3DVertexDeclaration9
**ppDecl
)
3247 user_assert(ppDecl
, D3DERR_INVALIDCALL
);
3249 *ppDecl
= (IDirect3DVertexDeclaration9
*)This
->state
.vdecl
;
3251 NineUnknown_AddRef(NineUnknown(*ppDecl
));
3256 NineDevice9_SetFVF( struct NineDevice9
*This
,
3259 struct NineVertexDeclaration9
*vdecl
;
3262 DBG("FVF = %08x\n", FVF
);
3264 return D3D_OK
; /* like wine */
3266 vdecl
= util_hash_table_get(This
->ff
.ht_fvf
, &FVF
);
3268 hr
= NineVertexDeclaration9_new_from_fvf(This
, FVF
, &vdecl
);
3272 util_hash_table_set(This
->ff
.ht_fvf
, &vdecl
->fvf
, vdecl
);
3273 NineUnknown_ConvertRefToBind(NineUnknown(vdecl
));
3275 return NineDevice9_SetVertexDeclaration(
3276 This
, (IDirect3DVertexDeclaration9
*)vdecl
);
3280 NineDevice9_GetFVF( struct NineDevice9
*This
,
3283 *pFVF
= This
->state
.vdecl
? This
->state
.vdecl
->fvf
: 0;
3288 NineDevice9_CreateVertexShader( struct NineDevice9
*This
,
3289 const DWORD
*pFunction
,
3290 IDirect3DVertexShader9
**ppShader
)
3292 struct NineVertexShader9
*vs
;
3295 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3297 hr
= NineVertexShader9_new(This
, &vs
, pFunction
, NULL
);
3300 *ppShader
= (IDirect3DVertexShader9
*)vs
;
3305 NineDevice9_SetVertexShader( struct NineDevice9
*This
,
3306 IDirect3DVertexShader9
*pShader
)
3308 struct nine_state
*state
= This
->update
;
3309 BOOL was_programmable_vs
= This
->state
.programmable_vs
;
3311 DBG("This=%p pShader=%p\n", This
, pShader
);
3313 if (!This
->is_recording
&& state
->vs
== (struct NineVertexShader9
*)pShader
)
3316 nine_bind(&state
->vs
, pShader
);
3318 This
->state
.programmable_vs
= This
->state
.vs
&& !(This
->state
.vdecl
&& This
->state
.vdecl
->position_t
);
3320 /* ff -> non-ff: commit back non-ff constants */
3321 if (!was_programmable_vs
&& This
->state
.programmable_vs
)
3322 state
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
3324 state
->changed
.group
|= NINE_STATE_VS
;
3330 NineDevice9_GetVertexShader( struct NineDevice9
*This
,
3331 IDirect3DVertexShader9
**ppShader
)
3333 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3334 nine_reference_set(ppShader
, This
->state
.vs
);
3339 NineDevice9_SetVertexShaderConstantF( struct NineDevice9
*This
,
3341 const float *pConstantData
,
3342 UINT Vector4fCount
)
3344 struct nine_state
*state
= This
->update
;
3346 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3347 This
, StartRegister
, pConstantData
, Vector4fCount
);
3349 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3350 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3354 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3356 if (!This
->is_recording
) {
3357 if (!memcmp(&state
->vs_const_f
[StartRegister
* 4], pConstantData
,
3358 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0])))
3362 memcpy(&state
->vs_const_f
[StartRegister
* 4],
3364 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3366 nine_ranges_insert(&state
->changed
.vs_const_f
,
3367 StartRegister
, StartRegister
+ Vector4fCount
,
3370 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3376 NineDevice9_GetVertexShaderConstantF( struct NineDevice9
*This
,
3378 float *pConstantData
,
3379 UINT Vector4fCount
)
3381 const struct nine_state
*state
= &This
->state
;
3383 user_assert(StartRegister
< This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3384 user_assert(StartRegister
+ Vector4fCount
<= This
->caps
.MaxVertexShaderConst
, D3DERR_INVALIDCALL
);
3385 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3387 memcpy(pConstantData
,
3388 &state
->vs_const_f
[StartRegister
* 4],
3389 Vector4fCount
* 4 * sizeof(state
->vs_const_f
[0]));
3395 NineDevice9_SetVertexShaderConstantI( struct NineDevice9
*This
,
3397 const int *pConstantData
,
3398 UINT Vector4iCount
)
3400 struct nine_state
*state
= This
->update
;
3403 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3404 This
, StartRegister
, pConstantData
, Vector4iCount
);
3406 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3407 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3408 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3410 if (This
->driver_caps
.vs_integer
) {
3411 if (!This
->is_recording
) {
3412 if (!memcmp(&state
->vs_const_i
[StartRegister
][0], pConstantData
,
3413 Vector4iCount
* sizeof(state
->vs_const_i
[0])))
3416 memcpy(&state
->vs_const_i
[StartRegister
][0],
3418 Vector4iCount
* sizeof(state
->vs_const_i
[0]));
3420 for (i
= 0; i
< Vector4iCount
; i
++) {
3421 state
->vs_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
3422 state
->vs_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
3423 state
->vs_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
3424 state
->vs_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
3428 state
->changed
.vs_const_i
|= ((1 << Vector4iCount
) - 1) << StartRegister
;
3429 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3435 NineDevice9_GetVertexShaderConstantI( struct NineDevice9
*This
,
3438 UINT Vector4iCount
)
3440 const struct nine_state
*state
= &This
->state
;
3443 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3444 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3445 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3447 if (This
->driver_caps
.vs_integer
) {
3448 memcpy(pConstantData
,
3449 &state
->vs_const_i
[StartRegister
][0],
3450 Vector4iCount
* sizeof(state
->vs_const_i
[0]));
3452 for (i
= 0; i
< Vector4iCount
; i
++) {
3453 pConstantData
[4*i
] = (int32_t) uif(state
->vs_const_i
[StartRegister
+i
][0]);
3454 pConstantData
[4*i
+1] = (int32_t) uif(state
->vs_const_i
[StartRegister
+i
][1]);
3455 pConstantData
[4*i
+2] = (int32_t) uif(state
->vs_const_i
[StartRegister
+i
][2]);
3456 pConstantData
[4*i
+3] = (int32_t) uif(state
->vs_const_i
[StartRegister
+i
][3]);
3464 NineDevice9_SetVertexShaderConstantB( struct NineDevice9
*This
,
3466 const BOOL
*pConstantData
,
3469 struct nine_state
*state
= This
->update
;
3471 uint32_t bool_true
= This
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
3473 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3474 This
, StartRegister
, pConstantData
, BoolCount
);
3476 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3477 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3478 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3480 if (!This
->is_recording
) {
3481 bool noChange
= true;
3482 for (i
= 0; i
< BoolCount
; i
++) {
3483 if (!!state
->vs_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3490 for (i
= 0; i
< BoolCount
; i
++)
3491 state
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3493 state
->changed
.vs_const_b
|= ((1 << BoolCount
) - 1) << StartRegister
;
3494 state
->changed
.group
|= NINE_STATE_VS_CONST
;
3500 NineDevice9_GetVertexShaderConstantB( struct NineDevice9
*This
,
3502 BOOL
*pConstantData
,
3505 const struct nine_state
*state
= &This
->state
;
3508 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3509 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3510 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3512 for (i
= 0; i
< BoolCount
; i
++)
3513 pConstantData
[i
] = state
->vs_const_b
[StartRegister
+ i
] != 0 ? TRUE
: FALSE
;
3519 NineDevice9_SetStreamSource( struct NineDevice9
*This
,
3521 IDirect3DVertexBuffer9
*pStreamData
,
3525 struct nine_state
*state
= This
->update
;
3526 struct NineVertexBuffer9
*pVBuf9
= NineVertexBuffer9(pStreamData
);
3527 const unsigned i
= StreamNumber
;
3529 DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",
3530 This
, StreamNumber
, pStreamData
, OffsetInBytes
, Stride
);
3532 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3533 user_assert(Stride
<= This
->caps
.MaxStreamStride
, D3DERR_INVALIDCALL
);
3535 if (likely(!This
->is_recording
)) {
3536 if (state
->stream
[i
] == NineVertexBuffer9(pStreamData
) &&
3537 state
->vtxbuf
[i
].stride
== Stride
&&
3538 state
->vtxbuf
[i
].buffer_offset
== OffsetInBytes
)
3541 nine_bind(&state
->stream
[i
], pStreamData
);
3543 state
->changed
.vtxbuf
|= 1 << StreamNumber
;
3546 state
->vtxbuf
[i
].stride
= Stride
;
3547 state
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
3549 pipe_resource_reference(&state
->vtxbuf
[i
].buffer
,
3550 pStreamData
? NineVertexBuffer9_GetResource(pVBuf9
) : NULL
);
3556 NineDevice9_GetStreamSource( struct NineDevice9
*This
,
3558 IDirect3DVertexBuffer9
**ppStreamData
,
3559 UINT
*pOffsetInBytes
,
3562 const struct nine_state
*state
= &This
->state
;
3563 const unsigned i
= StreamNumber
;
3565 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3566 user_assert(ppStreamData
, D3DERR_INVALIDCALL
);
3568 nine_reference_set(ppStreamData
, state
->stream
[i
]);
3569 *pStride
= state
->vtxbuf
[i
].stride
;
3570 *pOffsetInBytes
= state
->vtxbuf
[i
].buffer_offset
;
3576 NineDevice9_SetStreamSourceFreq( struct NineDevice9
*This
,
3580 struct nine_state
*state
= This
->update
;
3581 /* const UINT freq = Setting & 0x7FFFFF; */
3583 DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This
,
3584 StreamNumber
, Setting
);
3586 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3587 user_assert(StreamNumber
!= 0 || !(Setting
& D3DSTREAMSOURCE_INSTANCEDATA
),
3588 D3DERR_INVALIDCALL
);
3589 user_assert(!((Setting
& D3DSTREAMSOURCE_INSTANCEDATA
) &&
3590 (Setting
& D3DSTREAMSOURCE_INDEXEDDATA
)), D3DERR_INVALIDCALL
);
3591 user_assert(Setting
, D3DERR_INVALIDCALL
);
3593 if (likely(!This
->is_recording
) && state
->stream_freq
[StreamNumber
] == Setting
)
3596 state
->stream_freq
[StreamNumber
] = Setting
;
3598 if (Setting
& D3DSTREAMSOURCE_INSTANCEDATA
)
3599 state
->stream_instancedata_mask
|= 1 << StreamNumber
;
3601 state
->stream_instancedata_mask
&= ~(1 << StreamNumber
);
3603 state
->changed
.stream_freq
|= 1 << StreamNumber
; /* Used for stateblocks */
3604 if (StreamNumber
!= 0)
3605 state
->changed
.group
|= NINE_STATE_STREAMFREQ
;
3610 NineDevice9_GetStreamSourceFreq( struct NineDevice9
*This
,
3614 user_assert(StreamNumber
< This
->caps
.MaxStreams
, D3DERR_INVALIDCALL
);
3615 *pSetting
= This
->state
.stream_freq
[StreamNumber
];
3620 NineDevice9_SetIndices( struct NineDevice9
*This
,
3621 IDirect3DIndexBuffer9
*pIndexData
)
3623 struct nine_state
*state
= This
->update
;
3625 DBG("This=%p pIndexData=%p\n", This
, pIndexData
);
3627 if (likely(!This
->is_recording
))
3628 if (state
->idxbuf
== NineIndexBuffer9(pIndexData
))
3630 nine_bind(&state
->idxbuf
, pIndexData
);
3632 state
->changed
.group
|= NINE_STATE_IDXBUF
;
3637 /* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
3638 * here because it's an argument passed to the Draw calls.
3641 NineDevice9_GetIndices( struct NineDevice9
*This
,
3642 IDirect3DIndexBuffer9
**ppIndexData
/*,
3643 UINT *pBaseVertexIndex */ )
3645 user_assert(ppIndexData
, D3DERR_INVALIDCALL
);
3646 nine_reference_set(ppIndexData
, This
->state
.idxbuf
);
3651 NineDevice9_CreatePixelShader( struct NineDevice9
*This
,
3652 const DWORD
*pFunction
,
3653 IDirect3DPixelShader9
**ppShader
)
3655 struct NinePixelShader9
*ps
;
3658 DBG("This=%p pFunction=%p ppShader=%p\n", This
, pFunction
, ppShader
);
3660 hr
= NinePixelShader9_new(This
, &ps
, pFunction
, NULL
);
3663 *ppShader
= (IDirect3DPixelShader9
*)ps
;
3668 NineDevice9_SetPixelShader( struct NineDevice9
*This
,
3669 IDirect3DPixelShader9
*pShader
)
3671 struct nine_state
*state
= This
->update
;
3672 unsigned old_mask
= state
->ps
? state
->ps
->rt_mask
: 1;
3675 DBG("This=%p pShader=%p\n", This
, pShader
);
3677 if (!This
->is_recording
&& state
->ps
== (struct NinePixelShader9
*)pShader
)
3680 /* ff -> non-ff: commit back non-ff constants */
3681 if (!state
->ps
&& pShader
)
3682 state
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
3684 nine_bind(&state
->ps
, pShader
);
3686 state
->changed
.group
|= NINE_STATE_PS
;
3688 mask
= state
->ps
? state
->ps
->rt_mask
: 1;
3689 /* We need to update cbufs if the pixel shader would
3690 * write to different render targets */
3691 if (mask
!= old_mask
)
3692 state
->changed
.group
|= NINE_STATE_FB
;
3698 NineDevice9_GetPixelShader( struct NineDevice9
*This
,
3699 IDirect3DPixelShader9
**ppShader
)
3701 user_assert(ppShader
, D3DERR_INVALIDCALL
);
3702 nine_reference_set(ppShader
, This
->state
.ps
);
3707 NineDevice9_SetPixelShaderConstantF( struct NineDevice9
*This
,
3709 const float *pConstantData
,
3710 UINT Vector4fCount
)
3712 struct nine_state
*state
= This
->update
;
3714 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3715 This
, StartRegister
, pConstantData
, Vector4fCount
);
3717 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3718 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3722 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3724 if (!This
->is_recording
) {
3725 if (!memcmp(&state
->ps_const_f
[StartRegister
* 4], pConstantData
,
3726 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0])))
3730 memcpy(&state
->ps_const_f
[StartRegister
* 4],
3732 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3734 nine_ranges_insert(&state
->changed
.ps_const_f
,
3735 StartRegister
, StartRegister
+ Vector4fCount
,
3738 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3744 NineDevice9_GetPixelShaderConstantF( struct NineDevice9
*This
,
3746 float *pConstantData
,
3747 UINT Vector4fCount
)
3749 const struct nine_state
*state
= &This
->state
;
3751 user_assert(StartRegister
< NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3752 user_assert(StartRegister
+ Vector4fCount
<= NINE_MAX_CONST_F_PS3
, D3DERR_INVALIDCALL
);
3753 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3755 memcpy(pConstantData
,
3756 &state
->ps_const_f
[StartRegister
* 4],
3757 Vector4fCount
* 4 * sizeof(state
->ps_const_f
[0]));
3763 NineDevice9_SetPixelShaderConstantI( struct NineDevice9
*This
,
3765 const int *pConstantData
,
3766 UINT Vector4iCount
)
3768 struct nine_state
*state
= This
->update
;
3771 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3772 This
, StartRegister
, pConstantData
, Vector4iCount
);
3774 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3775 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3776 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3778 if (This
->driver_caps
.ps_integer
) {
3779 if (!This
->is_recording
) {
3780 if (!memcmp(&state
->ps_const_i
[StartRegister
][0], pConstantData
,
3781 Vector4iCount
* sizeof(state
->ps_const_i
[0])))
3784 memcpy(&state
->ps_const_i
[StartRegister
][0],
3786 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3788 for (i
= 0; i
< Vector4iCount
; i
++) {
3789 state
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
3790 state
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
3791 state
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
3792 state
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
3795 state
->changed
.ps_const_i
|= ((1 << Vector4iCount
) - 1) << StartRegister
;
3796 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3802 NineDevice9_GetPixelShaderConstantI( struct NineDevice9
*This
,
3805 UINT Vector4iCount
)
3807 const struct nine_state
*state
= &This
->state
;
3810 user_assert(StartRegister
< NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3811 user_assert(StartRegister
+ Vector4iCount
<= NINE_MAX_CONST_I
, D3DERR_INVALIDCALL
);
3812 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3814 if (This
->driver_caps
.ps_integer
) {
3815 memcpy(pConstantData
,
3816 &state
->ps_const_i
[StartRegister
][0],
3817 Vector4iCount
* sizeof(state
->ps_const_i
[0]));
3819 for (i
= 0; i
< Vector4iCount
; i
++) {
3820 pConstantData
[4*i
] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][0]);
3821 pConstantData
[4*i
+1] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][1]);
3822 pConstantData
[4*i
+2] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][2]);
3823 pConstantData
[4*i
+3] = (int32_t) uif(state
->ps_const_i
[StartRegister
+i
][3]);
3831 NineDevice9_SetPixelShaderConstantB( struct NineDevice9
*This
,
3833 const BOOL
*pConstantData
,
3836 struct nine_state
*state
= This
->update
;
3838 uint32_t bool_true
= This
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
3840 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3841 This
, StartRegister
, pConstantData
, BoolCount
);
3843 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3844 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3845 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3847 if (!This
->is_recording
) {
3848 bool noChange
= true;
3849 for (i
= 0; i
< BoolCount
; i
++) {
3850 if (!!state
->ps_const_b
[StartRegister
+ i
] != !!pConstantData
[i
])
3857 for (i
= 0; i
< BoolCount
; i
++)
3858 state
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
3860 state
->changed
.ps_const_b
|= ((1 << BoolCount
) - 1) << StartRegister
;
3861 state
->changed
.group
|= NINE_STATE_PS_CONST
;
3867 NineDevice9_GetPixelShaderConstantB( struct NineDevice9
*This
,
3869 BOOL
*pConstantData
,
3872 const struct nine_state
*state
= &This
->state
;
3875 user_assert(StartRegister
< NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3876 user_assert(StartRegister
+ BoolCount
<= NINE_MAX_CONST_B
, D3DERR_INVALIDCALL
);
3877 user_assert(pConstantData
, D3DERR_INVALIDCALL
);
3879 for (i
= 0; i
< BoolCount
; i
++)
3880 pConstantData
[i
] = state
->ps_const_b
[StartRegister
+ i
] ? TRUE
: FALSE
;
3886 NineDevice9_DrawRectPatch( struct NineDevice9
*This
,
3888 const float *pNumSegs
,
3889 const D3DRECTPATCH_INFO
*pRectPatchInfo
)
3891 STUB(D3DERR_INVALIDCALL
);
3895 NineDevice9_DrawTriPatch( struct NineDevice9
*This
,
3897 const float *pNumSegs
,
3898 const D3DTRIPATCH_INFO
*pTriPatchInfo
)
3900 STUB(D3DERR_INVALIDCALL
);
3904 NineDevice9_DeletePatch( struct NineDevice9
*This
,
3907 STUB(D3DERR_INVALIDCALL
);
3911 NineDevice9_CreateQuery( struct NineDevice9
*This
,
3913 IDirect3DQuery9
**ppQuery
)
3915 struct NineQuery9
*query
;
3918 DBG("This=%p Type=%d ppQuery=%p\n", This
, Type
, ppQuery
);
3920 hr
= nine_is_query_supported(This
->screen
, Type
);
3921 if (!ppQuery
|| hr
!= D3D_OK
)
3924 hr
= NineQuery9_new(This
, &query
, Type
);
3927 *ppQuery
= (IDirect3DQuery9
*)query
;
3931 IDirect3DDevice9Vtbl NineDevice9_vtable
= {
3932 (void *)NineUnknown_QueryInterface
,
3933 (void *)NineUnknown_AddRef
,
3934 (void *)NineUnknown_Release
,
3935 (void *)NineDevice9_TestCooperativeLevel
,
3936 (void *)NineDevice9_GetAvailableTextureMem
,
3937 (void *)NineDevice9_EvictManagedResources
,
3938 (void *)NineDevice9_GetDirect3D
,
3939 (void *)NineDevice9_GetDeviceCaps
,
3940 (void *)NineDevice9_GetDisplayMode
,
3941 (void *)NineDevice9_GetCreationParameters
,
3942 (void *)NineDevice9_SetCursorProperties
,
3943 (void *)NineDevice9_SetCursorPosition
,
3944 (void *)NineDevice9_ShowCursor
,
3945 (void *)NineDevice9_CreateAdditionalSwapChain
,
3946 (void *)NineDevice9_GetSwapChain
,
3947 (void *)NineDevice9_GetNumberOfSwapChains
,
3948 (void *)NineDevice9_Reset
,
3949 (void *)NineDevice9_Present
,
3950 (void *)NineDevice9_GetBackBuffer
,
3951 (void *)NineDevice9_GetRasterStatus
,
3952 (void *)NineDevice9_SetDialogBoxMode
,
3953 (void *)NineDevice9_SetGammaRamp
,
3954 (void *)NineDevice9_GetGammaRamp
,
3955 (void *)NineDevice9_CreateTexture
,
3956 (void *)NineDevice9_CreateVolumeTexture
,
3957 (void *)NineDevice9_CreateCubeTexture
,
3958 (void *)NineDevice9_CreateVertexBuffer
,
3959 (void *)NineDevice9_CreateIndexBuffer
,
3960 (void *)NineDevice9_CreateRenderTarget
,
3961 (void *)NineDevice9_CreateDepthStencilSurface
,
3962 (void *)NineDevice9_UpdateSurface
,
3963 (void *)NineDevice9_UpdateTexture
,
3964 (void *)NineDevice9_GetRenderTargetData
,
3965 (void *)NineDevice9_GetFrontBufferData
,
3966 (void *)NineDevice9_StretchRect
,
3967 (void *)NineDevice9_ColorFill
,
3968 (void *)NineDevice9_CreateOffscreenPlainSurface
,
3969 (void *)NineDevice9_SetRenderTarget
,
3970 (void *)NineDevice9_GetRenderTarget
,
3971 (void *)NineDevice9_SetDepthStencilSurface
,
3972 (void *)NineDevice9_GetDepthStencilSurface
,
3973 (void *)NineDevice9_BeginScene
,
3974 (void *)NineDevice9_EndScene
,
3975 (void *)NineDevice9_Clear
,
3976 (void *)NineDevice9_SetTransform
,
3977 (void *)NineDevice9_GetTransform
,
3978 (void *)NineDevice9_MultiplyTransform
,
3979 (void *)NineDevice9_SetViewport
,
3980 (void *)NineDevice9_GetViewport
,
3981 (void *)NineDevice9_SetMaterial
,
3982 (void *)NineDevice9_GetMaterial
,
3983 (void *)NineDevice9_SetLight
,
3984 (void *)NineDevice9_GetLight
,
3985 (void *)NineDevice9_LightEnable
,
3986 (void *)NineDevice9_GetLightEnable
,
3987 (void *)NineDevice9_SetClipPlane
,
3988 (void *)NineDevice9_GetClipPlane
,
3989 (void *)NineDevice9_SetRenderState
,
3990 (void *)NineDevice9_GetRenderState
,
3991 (void *)NineDevice9_CreateStateBlock
,
3992 (void *)NineDevice9_BeginStateBlock
,
3993 (void *)NineDevice9_EndStateBlock
,
3994 (void *)NineDevice9_SetClipStatus
,
3995 (void *)NineDevice9_GetClipStatus
,
3996 (void *)NineDevice9_GetTexture
,
3997 (void *)NineDevice9_SetTexture
,
3998 (void *)NineDevice9_GetTextureStageState
,
3999 (void *)NineDevice9_SetTextureStageState
,
4000 (void *)NineDevice9_GetSamplerState
,
4001 (void *)NineDevice9_SetSamplerState
,
4002 (void *)NineDevice9_ValidateDevice
,
4003 (void *)NineDevice9_SetPaletteEntries
,
4004 (void *)NineDevice9_GetPaletteEntries
,
4005 (void *)NineDevice9_SetCurrentTexturePalette
,
4006 (void *)NineDevice9_GetCurrentTexturePalette
,
4007 (void *)NineDevice9_SetScissorRect
,
4008 (void *)NineDevice9_GetScissorRect
,
4009 (void *)NineDevice9_SetSoftwareVertexProcessing
,
4010 (void *)NineDevice9_GetSoftwareVertexProcessing
,
4011 (void *)NineDevice9_SetNPatchMode
,
4012 (void *)NineDevice9_GetNPatchMode
,
4013 (void *)NineDevice9_DrawPrimitive
,
4014 (void *)NineDevice9_DrawIndexedPrimitive
,
4015 (void *)NineDevice9_DrawPrimitiveUP
,
4016 (void *)NineDevice9_DrawIndexedPrimitiveUP
,
4017 (void *)NineDevice9_ProcessVertices
,
4018 (void *)NineDevice9_CreateVertexDeclaration
,
4019 (void *)NineDevice9_SetVertexDeclaration
,
4020 (void *)NineDevice9_GetVertexDeclaration
,
4021 (void *)NineDevice9_SetFVF
,
4022 (void *)NineDevice9_GetFVF
,
4023 (void *)NineDevice9_CreateVertexShader
,
4024 (void *)NineDevice9_SetVertexShader
,
4025 (void *)NineDevice9_GetVertexShader
,
4026 (void *)NineDevice9_SetVertexShaderConstantF
,
4027 (void *)NineDevice9_GetVertexShaderConstantF
,
4028 (void *)NineDevice9_SetVertexShaderConstantI
,
4029 (void *)NineDevice9_GetVertexShaderConstantI
,
4030 (void *)NineDevice9_SetVertexShaderConstantB
,
4031 (void *)NineDevice9_GetVertexShaderConstantB
,
4032 (void *)NineDevice9_SetStreamSource
,
4033 (void *)NineDevice9_GetStreamSource
,
4034 (void *)NineDevice9_SetStreamSourceFreq
,
4035 (void *)NineDevice9_GetStreamSourceFreq
,
4036 (void *)NineDevice9_SetIndices
,
4037 (void *)NineDevice9_GetIndices
,
4038 (void *)NineDevice9_CreatePixelShader
,
4039 (void *)NineDevice9_SetPixelShader
,
4040 (void *)NineDevice9_GetPixelShader
,
4041 (void *)NineDevice9_SetPixelShaderConstantF
,
4042 (void *)NineDevice9_GetPixelShaderConstantF
,
4043 (void *)NineDevice9_SetPixelShaderConstantI
,
4044 (void *)NineDevice9_GetPixelShaderConstantI
,
4045 (void *)NineDevice9_SetPixelShaderConstantB
,
4046 (void *)NineDevice9_GetPixelShaderConstantB
,
4047 (void *)NineDevice9_DrawRectPatch
,
4048 (void *)NineDevice9_DrawTriPatch
,
4049 (void *)NineDevice9_DeletePatch
,
4050 (void *)NineDevice9_CreateQuery
4053 static const GUID
*NineDevice9_IIDs
[] = {
4054 &IID_IDirect3DDevice9
,
4060 NineDevice9_new( struct pipe_screen
*pScreen
,
4061 D3DDEVICE_CREATION_PARAMETERS
*pCreationParameters
,
4063 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
4065 ID3DPresentGroup
*pPresentationGroup
,
4066 struct d3dadapter9_context
*pCTX
,
4068 D3DDISPLAYMODEEX
*pFullscreenDisplayMode
,
4069 struct NineDevice9
**ppOut
,
4070 int minorVersionNum
)
4073 lock
= !!(pCreationParameters
->BehaviorFlags
& D3DCREATE_MULTITHREADED
);
4075 NINE_NEW(Device9
, ppOut
, lock
, /* args */
4076 pScreen
, pCreationParameters
, pCaps
,
4077 pPresentationParameters
, pD3D9
, pPresentationGroup
, pCTX
,
4078 ex
, pFullscreenDisplayMode
, minorVersionNum
);