2 * Copyright 2002 Lionel Ulmer
3 * Copyright 2002-2005 Jason Edmeades
4 * Copyright 2003-2004 Raphael Junqueira
5 * Copyright 2004 Christian Costa
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
8 * Copyright 2006-2008 Henri Verbeet
9 * Copyright 2007 Andrew Riedi
10 * Copyright 2009-2011 Henri Verbeet for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/port.h"
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
37 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
39 struct wined3d_matrix_3x3
46 struct light_transformed
48 struct wined3d_color diffuse
, specular
, ambient
;
49 struct wined3d_vec4 position
;
50 struct wined3d_vec3 direction
;
51 float range
, falloff
, c_att
, l_att
, q_att
, cos_htheta
, cos_hphi
;
54 struct lights_settings
56 struct light_transformed lights
[WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS
];
57 struct wined3d_color ambient_light
;
58 struct wined3d_matrix modelview_matrix
;
59 struct wined3d_matrix_3x3 normal_matrix
;
60 struct wined3d_vec4 position_transformed
;
62 float fog_start
, fog_end
, fog_density
;
64 uint32_t point_light_count
: 8;
65 uint32_t spot_light_count
: 8;
66 uint32_t directional_light_count
: 8;
67 uint32_t parallel_point_light_count
: 8;
68 uint32_t lighting
: 1;
69 uint32_t legacy_lighting
: 1;
70 uint32_t normalise
: 1;
71 uint32_t localviewer
: 1;
72 uint32_t fog_coord_mode
: 2;
73 uint32_t fog_mode
: 2;
74 uint32_t padding
: 24;
77 /* Define the default light parameters as specified by MSDN. */
78 const struct wined3d_light WINED3D_default_light
=
80 WINED3D_LIGHT_DIRECTIONAL
, /* Type */
81 { 1.0f
, 1.0f
, 1.0f
, 0.0f
}, /* Diffuse r,g,b,a */
82 { 0.0f
, 0.0f
, 0.0f
, 0.0f
}, /* Specular r,g,b,a */
83 { 0.0f
, 0.0f
, 0.0f
, 0.0f
}, /* Ambient r,g,b,a, */
84 { 0.0f
, 0.0f
, 0.0f
}, /* Position x,y,z */
85 { 0.0f
, 0.0f
, 1.0f
}, /* Direction x,y,z */
88 0.0f
, 0.0f
, 0.0f
, /* Attenuation 0,1,2 */
93 /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
94 * actually have the same values in GL and D3D. */
95 GLenum
gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type
)
97 switch (primitive_type
)
99 case WINED3D_PT_POINTLIST
:
102 case WINED3D_PT_LINELIST
:
105 case WINED3D_PT_LINESTRIP
:
106 return GL_LINE_STRIP
;
108 case WINED3D_PT_TRIANGLELIST
:
111 case WINED3D_PT_TRIANGLESTRIP
:
112 return GL_TRIANGLE_STRIP
;
114 case WINED3D_PT_TRIANGLEFAN
:
115 return GL_TRIANGLE_FAN
;
117 case WINED3D_PT_LINELIST_ADJ
:
118 return GL_LINES_ADJACENCY_ARB
;
120 case WINED3D_PT_LINESTRIP_ADJ
:
121 return GL_LINE_STRIP_ADJACENCY_ARB
;
123 case WINED3D_PT_TRIANGLELIST_ADJ
:
124 return GL_TRIANGLES_ADJACENCY_ARB
;
126 case WINED3D_PT_TRIANGLESTRIP_ADJ
:
127 return GL_TRIANGLE_STRIP_ADJACENCY_ARB
;
129 case WINED3D_PT_PATCH
:
133 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type
));
134 case WINED3D_PT_UNDEFINED
:
139 enum wined3d_primitive_type
d3d_primitive_type_from_gl(GLenum primitive_type
)
141 switch (primitive_type
)
144 return WINED3D_PT_POINTLIST
;
147 return WINED3D_PT_LINELIST
;
150 return WINED3D_PT_LINESTRIP
;
153 return WINED3D_PT_TRIANGLELIST
;
155 case GL_TRIANGLE_STRIP
:
156 return WINED3D_PT_TRIANGLESTRIP
;
158 case GL_TRIANGLE_FAN
:
159 return WINED3D_PT_TRIANGLEFAN
;
161 case GL_LINES_ADJACENCY_ARB
:
162 return WINED3D_PT_LINELIST_ADJ
;
164 case GL_LINE_STRIP_ADJACENCY_ARB
:
165 return WINED3D_PT_LINESTRIP_ADJ
;
167 case GL_TRIANGLES_ADJACENCY_ARB
:
168 return WINED3D_PT_TRIANGLELIST_ADJ
;
170 case GL_TRIANGLE_STRIP_ADJACENCY_ARB
:
171 return WINED3D_PT_TRIANGLESTRIP_ADJ
;
174 return WINED3D_PT_PATCH
;
177 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type
));
179 return WINED3D_PT_UNDEFINED
;
183 BOOL
device_context_add(struct wined3d_device
*device
, struct wined3d_context
*context
)
185 struct wined3d_context
**new_array
;
187 TRACE("Adding context %p.\n", context
);
189 if (!device
->shader_backend
->shader_allocate_context_data(context
))
191 ERR("Failed to allocate shader backend context data.\n");
194 device
->shader_backend
->shader_init_context_state(context
);
196 if (!device
->adapter
->fragment_pipe
->allocate_context_data(context
))
198 ERR("Failed to allocate fragment pipeline context data.\n");
199 device
->shader_backend
->shader_free_context_data(context
);
203 if (!(new_array
= heap_realloc(device
->contexts
, sizeof(*new_array
) * (device
->context_count
+ 1))))
205 ERR("Failed to grow the context array.\n");
206 device
->adapter
->fragment_pipe
->free_context_data(context
);
207 device
->shader_backend
->shader_free_context_data(context
);
211 new_array
[device
->context_count
++] = context
;
212 device
->contexts
= new_array
;
217 void device_context_remove(struct wined3d_device
*device
, struct wined3d_context
*context
)
219 struct wined3d_context
**new_array
;
223 TRACE("Removing context %p.\n", context
);
225 device
->adapter
->fragment_pipe
->free_context_data(context
);
226 device
->shader_backend
->shader_free_context_data(context
);
228 for (i
= 0; i
< device
->context_count
; ++i
)
230 if (device
->contexts
[i
] == context
)
239 ERR("Context %p doesn't exist in context array.\n", context
);
243 if (!--device
->context_count
)
245 heap_free(device
->contexts
);
246 device
->contexts
= NULL
;
250 memmove(&device
->contexts
[i
], &device
->contexts
[i
+ 1], (device
->context_count
- i
) * sizeof(*device
->contexts
));
251 if (!(new_array
= heap_realloc(device
->contexts
, device
->context_count
* sizeof(*device
->contexts
))))
253 ERR("Failed to shrink context array. Oh well.\n");
257 device
->contexts
= new_array
;
260 static BOOL
is_full_clear(const struct wined3d_texture
*texture
, unsigned int sub_resource_idx
,
261 const RECT
*draw_rect
, const RECT
*clear_rect
)
263 unsigned int width
, height
, level
;
265 level
= sub_resource_idx
% texture
->level_count
;
266 width
= wined3d_texture_get_level_width(texture
, level
);
267 height
= wined3d_texture_get_level_height(texture
, level
);
269 /* partial draw rect */
270 if (draw_rect
->left
|| draw_rect
->top
|| draw_rect
->right
< width
|| draw_rect
->bottom
< height
)
273 /* partial clear rect */
274 if (clear_rect
&& (clear_rect
->left
> 0 || clear_rect
->top
> 0
275 || clear_rect
->right
< width
|| clear_rect
->bottom
< height
))
281 void device_clear_render_targets(struct wined3d_device
*device
, UINT rt_count
, const struct wined3d_fb_state
*fb
,
282 UINT rect_count
, const RECT
*clear_rect
, const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*color
,
283 float depth
, DWORD stencil
)
285 struct wined3d_rendertarget_view
*rtv
= rt_count
? fb
->render_targets
[0] : NULL
;
286 struct wined3d_rendertarget_view
*dsv
= fb
->depth_stencil
;
287 const struct wined3d_state
*state
= &device
->cs
->state
;
288 struct wined3d_texture
*depth_stencil
= NULL
;
289 const struct wined3d_gl_info
*gl_info
;
290 struct wined3d_context_gl
*context_gl
;
291 struct wined3d_texture
*target
= NULL
;
292 UINT drawable_width
, drawable_height
;
293 struct wined3d_color colour_srgb
;
294 struct wined3d_context
*context
;
295 GLbitfield clear_mask
= 0;
296 BOOL render_offscreen
;
299 if (rtv
&& rtv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
301 target
= texture_from_resource(rtv
->resource
);
302 context
= context_acquire(device
, target
, rtv
->sub_resource_idx
);
306 context
= context_acquire(device
, NULL
, 0);
308 context_gl
= wined3d_context_gl(context
);
310 if (dsv
&& dsv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
311 depth_stencil
= texture_from_resource(dsv
->resource
);
313 if (!context_gl
->valid
)
315 context_release(context
);
316 WARN("Invalid context, skipping clear.\n");
319 gl_info
= context_gl
->gl_info
;
321 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
322 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
323 * for the cleared parts, and the untouched parts.
325 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
326 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
327 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
328 * checking all this if the dest surface is in the drawable anyway. */
329 for (i
= 0; i
< rt_count
; ++i
)
331 struct wined3d_rendertarget_view
*rtv
= fb
->render_targets
[i
];
333 if (rtv
&& rtv
->format
->id
!= WINED3DFMT_NULL
)
335 struct wined3d_texture
*rt
= wined3d_texture_from_resource(rtv
->resource
);
337 if (flags
& WINED3DCLEAR_TARGET
&& !is_full_clear(rt
, rtv
->sub_resource_idx
,
338 draw_rect
, rect_count
? clear_rect
: NULL
))
339 wined3d_texture_load_location(rt
, rtv
->sub_resource_idx
, context
, rtv
->resource
->draw_binding
);
341 wined3d_texture_prepare_location(rt
, rtv
->sub_resource_idx
, context
, rtv
->resource
->draw_binding
);
347 render_offscreen
= context
->render_offscreen
;
348 wined3d_rendertarget_view_get_drawable_size(rtv
, context
, &drawable_width
, &drawable_height
);
352 unsigned int ds_level
= dsv
->sub_resource_idx
% depth_stencil
->level_count
;
354 render_offscreen
= TRUE
;
355 drawable_width
= wined3d_texture_get_level_pow2_width(depth_stencil
, ds_level
);
356 drawable_height
= wined3d_texture_get_level_pow2_height(depth_stencil
, ds_level
);
361 DWORD ds_location
= render_offscreen
? dsv
->resource
->draw_binding
: WINED3D_LOCATION_DRAWABLE
;
362 struct wined3d_texture
*ds
= wined3d_texture_from_resource(dsv
->resource
);
364 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)
365 && !is_full_clear(ds
, dsv
->sub_resource_idx
, draw_rect
, rect_count
? clear_rect
: NULL
))
366 wined3d_texture_load_location(ds
, dsv
->sub_resource_idx
, context
, ds_location
);
368 wined3d_texture_prepare_location(ds
, dsv
->sub_resource_idx
, context
, ds_location
);
370 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
372 wined3d_texture_validate_location(ds
, dsv
->sub_resource_idx
, ds_location
);
373 wined3d_texture_invalidate_location(ds
, dsv
->sub_resource_idx
, ~ds_location
);
377 if (!wined3d_context_gl_apply_clear_state(context_gl
, state
, rt_count
, fb
))
379 context_release(context
);
380 WARN("Failed to apply clear state, skipping clear.\n");
384 /* Only set the values up once, as they are not changing. */
385 if (flags
& WINED3DCLEAR_STENCIL
)
387 if (gl_info
->supported
[EXT_STENCIL_TWO_SIDE
])
389 gl_info
->gl_ops
.gl
.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
390 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE
));
392 gl_info
->gl_ops
.gl
.p_glStencilMask(~0U);
393 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK
));
394 gl_info
->gl_ops
.gl
.p_glClearStencil(stencil
);
395 checkGLcall("glClearStencil");
396 clear_mask
= clear_mask
| GL_STENCIL_BUFFER_BIT
;
399 if (flags
& WINED3DCLEAR_ZBUFFER
)
401 gl_info
->gl_ops
.gl
.p_glDepthMask(GL_TRUE
);
402 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_ZWRITEENABLE
));
403 gl_info
->gl_ops
.gl
.p_glClearDepth(depth
);
404 checkGLcall("glClearDepth");
405 clear_mask
= clear_mask
| GL_DEPTH_BUFFER_BIT
;
408 if (flags
& WINED3DCLEAR_TARGET
)
410 for (i
= 0; i
< rt_count
; ++i
)
412 struct wined3d_rendertarget_view
*rtv
= fb
->render_targets
[i
];
413 struct wined3d_texture
*texture
;
418 if (rtv
->resource
->type
== WINED3D_RTYPE_BUFFER
)
420 FIXME("Not supported on buffer resources.\n");
424 texture
= texture_from_resource(rtv
->resource
);
425 wined3d_texture_validate_location(texture
, rtv
->sub_resource_idx
, rtv
->resource
->draw_binding
);
426 wined3d_texture_invalidate_location(texture
, rtv
->sub_resource_idx
, ~rtv
->resource
->draw_binding
);
429 if (!gl_info
->supported
[ARB_FRAMEBUFFER_SRGB
] && needs_srgb_write(context
, state
, fb
))
432 WARN("Clearing multiple sRGB render targets without GL_ARB_framebuffer_sRGB "
433 "support, this might cause graphical issues.\n");
435 wined3d_colour_srgb_from_linear(&colour_srgb
, color
);
436 color
= &colour_srgb
;
439 gl_info
->gl_ops
.gl
.p_glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
440 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE
));
441 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1
));
442 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2
));
443 context_invalidate_state(context
, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3
));
444 gl_info
->gl_ops
.gl
.p_glClearColor(color
->r
, color
->g
, color
->b
, color
->a
);
445 checkGLcall("glClearColor");
446 clear_mask
= clear_mask
| GL_COLOR_BUFFER_BIT
;
451 if (render_offscreen
)
453 gl_info
->gl_ops
.gl
.p_glScissor(draw_rect
->left
, draw_rect
->top
,
454 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
458 gl_info
->gl_ops
.gl
.p_glScissor(draw_rect
->left
, drawable_height
- draw_rect
->bottom
,
459 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
461 gl_info
->gl_ops
.gl
.p_glClear(clear_mask
);
467 /* Now process each rect in turn. */
468 for (i
= 0; i
< rect_count
; ++i
)
470 /* Note that GL uses lower left, width/height. */
471 IntersectRect(¤t_rect
, draw_rect
, &clear_rect
[i
]);
473 TRACE("clear_rect[%u] %s, current_rect %s.\n", i
,
474 wine_dbgstr_rect(&clear_rect
[i
]),
475 wine_dbgstr_rect(¤t_rect
));
477 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
478 * The rectangle is not cleared, no error is returned, but further rectangles are
479 * still cleared if they are valid. */
480 if (current_rect
.left
> current_rect
.right
|| current_rect
.top
> current_rect
.bottom
)
482 TRACE("Rectangle with negative dimensions, ignoring.\n");
486 if (render_offscreen
)
488 gl_info
->gl_ops
.gl
.p_glScissor(current_rect
.left
, current_rect
.top
,
489 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
493 gl_info
->gl_ops
.gl
.p_glScissor(current_rect
.left
, drawable_height
- current_rect
.bottom
,
494 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
496 gl_info
->gl_ops
.gl
.p_glClear(clear_mask
);
499 context
->scissor_rect_count
= WINED3D_MAX_VIEWPORTS
;
500 checkGLcall("clear");
502 if (flags
& WINED3DCLEAR_TARGET
&& target
->swapchain
&& target
->swapchain
->front_buffer
== target
)
503 gl_info
->gl_ops
.gl
.p_glFlush();
505 context_release(context
);
508 ULONG CDECL
wined3d_device_incref(struct wined3d_device
*device
)
510 ULONG refcount
= InterlockedIncrement(&device
->ref
);
512 TRACE("%p increasing refcount to %u.\n", device
, refcount
);
517 static void device_leftover_sampler(struct wine_rb_entry
*entry
, void *context
)
519 struct wined3d_sampler
*sampler
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_sampler
, entry
);
521 ERR("Leftover sampler %p.\n", sampler
);
524 static void device_free_rasterizer_state(struct wine_rb_entry
*entry
, void *context
)
526 struct wined3d_rasterizer_state
*state
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_rasterizer_state
, entry
);
528 wined3d_rasterizer_state_decref(state
);
531 void wined3d_device_cleanup(struct wined3d_device
*device
)
535 if (device
->swapchain_count
)
536 wined3d_device_uninit_3d(device
);
538 wined3d_blend_state_decref(device
->blend_state_atoc_enabled
);
539 wine_rb_destroy(&device
->rasterizer_states
, device_free_rasterizer_state
, NULL
);
541 wined3d_cs_destroy(device
->cs
);
543 for (i
= 0; i
< ARRAY_SIZE(device
->multistate_funcs
); ++i
)
545 heap_free(device
->multistate_funcs
[i
]);
546 device
->multistate_funcs
[i
] = NULL
;
549 if (!list_empty(&device
->resources
))
551 struct wined3d_resource
*resource
;
553 ERR("Device released with resources still bound.\n");
555 LIST_FOR_EACH_ENTRY(resource
, &device
->resources
, struct wined3d_resource
, resource_list_entry
)
557 ERR("Leftover resource %p with type %s (%#x).\n",
558 resource
, debug_d3dresourcetype(resource
->type
), resource
->type
);
562 if (device
->contexts
)
563 ERR("Context array not freed!\n");
564 if (device
->hardwareCursor
)
565 DestroyCursor(device
->hardwareCursor
);
566 device
->hardwareCursor
= 0;
568 wine_rb_destroy(&device
->samplers
, device_leftover_sampler
, NULL
);
570 wined3d_decref(device
->wined3d
);
571 device
->wined3d
= NULL
;
574 ULONG CDECL
wined3d_device_decref(struct wined3d_device
*device
)
576 ULONG refcount
= InterlockedDecrement(&device
->ref
);
578 TRACE("%p decreasing refcount to %u.\n", device
, refcount
);
582 device
->adapter
->adapter_ops
->adapter_destroy_device(device
);
583 TRACE("Destroyed device %p.\n", device
);
589 UINT CDECL
wined3d_device_get_swapchain_count(const struct wined3d_device
*device
)
591 TRACE("device %p.\n", device
);
593 return device
->swapchain_count
;
596 struct wined3d_swapchain
* CDECL
wined3d_device_get_swapchain(const struct wined3d_device
*device
, UINT swapchain_idx
)
598 TRACE("device %p, swapchain_idx %u.\n", device
, swapchain_idx
);
600 if (swapchain_idx
>= device
->swapchain_count
)
602 WARN("swapchain_idx %u >= swapchain_count %u.\n",
603 swapchain_idx
, device
->swapchain_count
);
607 return device
->swapchains
[swapchain_idx
];
610 static void device_load_logo(struct wined3d_device
*device
, const char *filename
)
612 struct wined3d_color_key color_key
;
613 struct wined3d_resource_desc desc
;
617 HDC dcb
= NULL
, dcs
= NULL
;
619 if (!(hbm
= LoadImageA(NULL
, filename
, IMAGE_BITMAP
, 0, 0, LR_LOADFROMFILE
| LR_CREATEDIBSECTION
)))
621 ERR_(winediag
)("Failed to load logo %s.\n", wine_dbgstr_a(filename
));
624 GetObjectA(hbm
, sizeof(BITMAP
), &bm
);
626 if (!(dcb
= CreateCompatibleDC(NULL
)))
628 SelectObject(dcb
, hbm
);
630 desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
631 desc
.format
= WINED3DFMT_B5G6R5_UNORM
;
632 desc
.multisample_type
= WINED3D_MULTISAMPLE_NONE
;
633 desc
.multisample_quality
= 0;
634 desc
.usage
= WINED3DUSAGE_DYNAMIC
;
636 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
637 desc
.width
= bm
.bmWidth
;
638 desc
.height
= bm
.bmHeight
;
641 if (FAILED(hr
= wined3d_texture_create(device
, &desc
, 1, 1, WINED3D_TEXTURE_CREATE_GET_DC
,
642 NULL
, NULL
, &wined3d_null_parent_ops
, &device
->logo_texture
)))
644 ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr
);
648 if (FAILED(hr
= wined3d_texture_get_dc(device
->logo_texture
, 0, &dcs
)))
650 wined3d_texture_decref(device
->logo_texture
);
651 device
->logo_texture
= NULL
;
654 BitBlt(dcs
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, dcb
, 0, 0, SRCCOPY
);
655 wined3d_texture_release_dc(device
->logo_texture
, 0, dcs
);
657 color_key
.color_space_low_value
= 0;
658 color_key
.color_space_high_value
= 0;
659 wined3d_texture_set_color_key(device
->logo_texture
, WINED3D_CKEY_SRC_BLT
, &color_key
);
662 if (dcb
) DeleteDC(dcb
);
663 if (hbm
) DeleteObject(hbm
);
666 /* Context activation is done by the caller. */
667 static void wined3d_device_gl_create_dummy_textures(struct wined3d_device_gl
*device_gl
,
668 struct wined3d_context_gl
*context_gl
)
670 struct wined3d_dummy_textures
*textures
= &device_gl
->dummy_textures
;
671 const struct wined3d_d3d_info
*d3d_info
= context_gl
->c
.d3d_info
;
672 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
676 if (d3d_info
->wined3d_creation_flags
& WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR
)
681 /* Under DirectX you can sample even if no texture is bound, whereas
682 * OpenGL will only allow that when a valid texture is bound.
683 * We emulate this by creating dummy textures and binding them
684 * to each texture stage when the currently set D3D texture is NULL. */
685 wined3d_context_gl_active_texture(context_gl
, gl_info
, 0);
687 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_1d
);
688 TRACE("Dummy 1D texture given name %u.\n", textures
->tex_1d
);
689 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_1D
, textures
->tex_1d
);
690 gl_info
->gl_ops
.gl
.p_glTexImage1D(GL_TEXTURE_1D
, 0, GL_RGBA8
, 1, 0,
691 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
);
693 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_2d
);
694 TRACE("Dummy 2D texture given name %u.\n", textures
->tex_2d
);
695 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_2D
, textures
->tex_2d
);
696 gl_info
->gl_ops
.gl
.p_glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 1, 1, 0,
697 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
);
699 if (gl_info
->supported
[ARB_TEXTURE_RECTANGLE
])
701 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_rect
);
702 TRACE("Dummy rectangle texture given name %u.\n", textures
->tex_rect
);
703 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, textures
->tex_rect
);
704 gl_info
->gl_ops
.gl
.p_glTexImage2D(GL_TEXTURE_RECTANGLE_ARB
, 0, GL_RGBA8
, 1, 1, 0,
705 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
);
708 if (gl_info
->supported
[EXT_TEXTURE3D
])
710 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_3d
);
711 TRACE("Dummy 3D texture given name %u.\n", textures
->tex_3d
);
712 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_3D
, textures
->tex_3d
);
713 GL_EXTCALL(glTexImage3D(GL_TEXTURE_3D
, 0, GL_RGBA8
, 1, 1, 1, 0,
714 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
));
717 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
])
719 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_cube
);
720 TRACE("Dummy cube texture given name %u.\n", textures
->tex_cube
);
721 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_CUBE_MAP
, textures
->tex_cube
);
722 for (i
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
; i
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
; ++i
)
724 gl_info
->gl_ops
.gl
.p_glTexImage2D(i
, 0, GL_RGBA8
, 1, 1, 0,
725 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
);
729 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP_ARRAY
])
731 DWORD cube_array_data
[6];
733 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_cube_array
);
734 TRACE("Dummy cube array texture given name %u.\n", textures
->tex_cube_array
);
735 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY
, textures
->tex_cube_array
);
736 for (i
= 0; i
< ARRAY_SIZE(cube_array_data
); ++i
)
737 cube_array_data
[i
] = color
;
738 GL_EXTCALL(glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY
, 0, GL_RGBA8
, 1, 1, 6, 0,
739 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, cube_array_data
));
742 if (gl_info
->supported
[EXT_TEXTURE_ARRAY
])
744 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_1d_array
);
745 TRACE("Dummy 1D array texture given name %u.\n", textures
->tex_1d_array
);
746 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_1D_ARRAY
, textures
->tex_1d_array
);
747 gl_info
->gl_ops
.gl
.p_glTexImage2D(GL_TEXTURE_1D_ARRAY
, 0, GL_RGBA8
, 1, 1, 0,
748 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
);
750 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_2d_array
);
751 TRACE("Dummy 2D array texture given name %u.\n", textures
->tex_2d_array
);
752 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_2D_ARRAY
, textures
->tex_2d_array
);
753 GL_EXTCALL(glTexImage3D(GL_TEXTURE_2D_ARRAY
, 0, GL_RGBA8
, 1, 1, 1, 0,
754 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
));
757 if (gl_info
->supported
[ARB_TEXTURE_BUFFER_OBJECT
])
761 GL_EXTCALL(glGenBuffers(1, &buffer
));
762 GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER
, buffer
));
763 GL_EXTCALL(glBufferData(GL_TEXTURE_BUFFER
, sizeof(color
), &color
, GL_STATIC_DRAW
));
764 GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER
, 0));
766 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_buffer
);
767 TRACE("Dummy buffer texture given name %u.\n", textures
->tex_buffer
);
768 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_BUFFER
, textures
->tex_buffer
);
769 GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER
, GL_RGBA8
, buffer
));
770 GL_EXTCALL(glDeleteBuffers(1, &buffer
));
773 if (gl_info
->supported
[ARB_TEXTURE_MULTISAMPLE
])
775 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_2d_ms
);
776 TRACE("Dummy multisample texture given name %u.\n", textures
->tex_2d_ms
);
777 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, textures
->tex_2d_ms
);
778 GL_EXTCALL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE
, 1, GL_RGBA8
, 1, 1, GL_TRUE
));
780 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &textures
->tex_2d_ms_array
);
781 TRACE("Dummy multisample array texture given name %u.\n", textures
->tex_2d_ms_array
);
782 gl_info
->gl_ops
.gl
.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY
, textures
->tex_2d_ms_array
);
783 GL_EXTCALL(glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY
, 1, GL_RGBA8
, 1, 1, 1, GL_TRUE
));
785 if (gl_info
->supported
[ARB_CLEAR_TEXTURE
])
787 GL_EXTCALL(glClearTexImage(textures
->tex_2d_ms
, 0, GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
));
788 GL_EXTCALL(glClearTexImage(textures
->tex_2d_ms_array
, 0, GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, &color
));
792 WARN("ARB_clear_texture is currently required to clear dummy multisample textures.\n");
796 checkGLcall("create dummy textures");
798 wined3d_context_gl_bind_dummy_textures(context_gl
);
801 /* Context activation is done by the caller. */
802 static void wined3d_device_gl_destroy_dummy_textures(struct wined3d_device_gl
*device_gl
,
803 struct wined3d_context_gl
*context_gl
)
805 struct wined3d_dummy_textures
*dummy_textures
= &device_gl
->dummy_textures
;
806 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
808 if (gl_info
->supported
[ARB_TEXTURE_MULTISAMPLE
])
810 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_2d_ms
);
811 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_2d_ms_array
);
814 if (gl_info
->supported
[ARB_TEXTURE_BUFFER_OBJECT
])
815 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_buffer
);
817 if (gl_info
->supported
[EXT_TEXTURE_ARRAY
])
819 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_2d_array
);
820 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_1d_array
);
823 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP_ARRAY
])
824 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_cube_array
);
826 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
])
827 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_cube
);
829 if (gl_info
->supported
[EXT_TEXTURE3D
])
830 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_3d
);
832 if (gl_info
->supported
[ARB_TEXTURE_RECTANGLE
])
833 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_rect
);
835 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_2d
);
836 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &dummy_textures
->tex_1d
);
838 checkGLcall("delete dummy textures");
840 memset(dummy_textures
, 0, sizeof(*dummy_textures
));
843 /* Context activation is done by the caller. */
844 void wined3d_device_create_default_samplers(struct wined3d_device
*device
, struct wined3d_context
*context
)
846 struct wined3d_sampler_desc desc
;
849 desc
.address_u
= WINED3D_TADDRESS_WRAP
;
850 desc
.address_v
= WINED3D_TADDRESS_WRAP
;
851 desc
.address_w
= WINED3D_TADDRESS_WRAP
;
852 memset(desc
.border_color
, 0, sizeof(desc
.border_color
));
853 desc
.mag_filter
= WINED3D_TEXF_POINT
;
854 desc
.min_filter
= WINED3D_TEXF_POINT
;
855 desc
.mip_filter
= WINED3D_TEXF_NONE
;
856 desc
.lod_bias
= 0.0f
;
857 desc
.min_lod
= -1000.0f
;
858 desc
.max_lod
= 1000.0f
;
859 desc
.mip_base_level
= 0;
860 desc
.max_anisotropy
= 1;
861 desc
.compare
= FALSE
;
862 desc
.comparison_func
= WINED3D_CMP_NEVER
;
863 desc
.srgb_decode
= TRUE
;
865 /* In SM4+ shaders there is a separation between resources and samplers. Some shader
866 * instructions allow access to resources without using samplers.
867 * In GLSL, resources are always accessed through sampler or image variables. The default
868 * sampler object is used to emulate the direct resource access when there is no sampler state
871 if (FAILED(hr
= wined3d_sampler_create(device
, &desc
, NULL
, &wined3d_null_parent_ops
, &device
->default_sampler
)))
873 ERR("Failed to create default sampler, hr %#x.\n", hr
);
874 device
->default_sampler
= NULL
;
877 /* In D3D10+, a NULL sampler maps to the default sampler state. */
878 desc
.address_u
= WINED3D_TADDRESS_CLAMP
;
879 desc
.address_v
= WINED3D_TADDRESS_CLAMP
;
880 desc
.address_w
= WINED3D_TADDRESS_CLAMP
;
881 desc
.mag_filter
= WINED3D_TEXF_LINEAR
;
882 desc
.min_filter
= WINED3D_TEXF_LINEAR
;
883 desc
.mip_filter
= WINED3D_TEXF_LINEAR
;
884 if (FAILED(hr
= wined3d_sampler_create(device
, &desc
, NULL
, &wined3d_null_parent_ops
, &device
->null_sampler
)))
886 ERR("Failed to create null sampler, hr %#x.\n", hr
);
887 device
->null_sampler
= NULL
;
891 /* Context activation is done by the caller. */
892 void wined3d_device_destroy_default_samplers(struct wined3d_device
*device
, struct wined3d_context
*context
)
894 wined3d_sampler_decref(device
->default_sampler
);
895 device
->default_sampler
= NULL
;
896 wined3d_sampler_decref(device
->null_sampler
);
897 device
->null_sampler
= NULL
;
900 HRESULT CDECL
wined3d_device_acquire_focus_window(struct wined3d_device
*device
, HWND window
)
902 unsigned int screensaver_active
;
904 TRACE("device %p, window %p.\n", device
, window
);
906 if (!wined3d_register_window(NULL
, window
, device
, 0))
908 ERR("Failed to register window %p.\n", window
);
912 InterlockedExchangePointer((void **)&device
->focus_window
, window
);
913 SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
914 SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE
, 0, &screensaver_active
, 0);
915 if ((device
->restore_screensaver
= !!screensaver_active
))
916 SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE
, FALSE
, NULL
, 0);
921 void CDECL
wined3d_device_release_focus_window(struct wined3d_device
*device
)
923 TRACE("device %p.\n", device
);
925 if (device
->focus_window
) wined3d_unregister_window(device
->focus_window
);
926 InterlockedExchangePointer((void **)&device
->focus_window
, NULL
);
927 if (device
->restore_screensaver
)
929 SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE
, TRUE
, NULL
, 0);
930 device
->restore_screensaver
= FALSE
;
934 static void device_init_swapchain_state(struct wined3d_device
*device
, struct wined3d_swapchain
*swapchain
)
936 BOOL ds_enable
= swapchain
->state
.desc
.enable_auto_depth_stencil
;
939 for (i
= 0; i
< device
->adapter
->d3d_info
.limits
.max_rt_count
; ++i
)
941 wined3d_device_set_rendertarget_view(device
, i
, NULL
, FALSE
);
943 if (device
->back_buffer_view
)
944 wined3d_device_set_rendertarget_view(device
, 0, device
->back_buffer_view
, TRUE
);
946 wined3d_device_set_depth_stencil_view(device
, ds_enable
? device
->auto_depth_stencil_view
: NULL
);
949 void wined3d_device_delete_opengl_contexts_cs(void *object
)
951 struct wined3d_swapchain_gl
*swapchain_gl
;
952 struct wined3d_device
*device
= object
;
953 struct wined3d_context_gl
*context_gl
;
954 struct wined3d_device_gl
*device_gl
;
955 struct wined3d_context
*context
;
956 struct wined3d_shader
*shader
;
958 device_gl
= wined3d_device_gl(device
);
960 LIST_FOR_EACH_ENTRY(shader
, &device
->shaders
, struct wined3d_shader
, shader_list_entry
)
962 device
->shader_backend
->shader_destroy(shader
);
965 context
= context_acquire(device
, NULL
, 0);
966 context_gl
= wined3d_context_gl(context
);
967 device
->blitter
->ops
->blitter_destroy(device
->blitter
, context
);
968 device
->shader_backend
->shader_free_private(device
, context
);
969 wined3d_device_gl_destroy_dummy_textures(device_gl
, context_gl
);
970 wined3d_device_destroy_default_samplers(device
, context
);
971 context_release(context
);
973 while (device
->context_count
)
975 if ((swapchain_gl
= wined3d_swapchain_gl(device
->contexts
[0]->swapchain
)))
976 wined3d_swapchain_gl_destroy_contexts(swapchain_gl
);
978 wined3d_context_gl_destroy(wined3d_context_gl(device
->contexts
[0]));
982 void wined3d_device_create_primary_opengl_context_cs(void *object
)
984 struct wined3d_device
*device
= object
;
985 struct wined3d_context_gl
*context_gl
;
986 struct wined3d_swapchain
*swapchain
;
987 struct wined3d_context
*context
;
988 struct wined3d_texture
*target
;
991 swapchain
= device
->swapchains
[0];
992 target
= swapchain
->back_buffers
? swapchain
->back_buffers
[0] : swapchain
->front_buffer
;
993 if (!(context
= context_acquire(device
, target
, 0)))
995 WARN("Failed to acquire context.\n");
999 if (FAILED(hr
= device
->shader_backend
->shader_alloc_private(device
,
1000 device
->adapter
->vertex_pipe
, device
->adapter
->fragment_pipe
)))
1002 ERR("Failed to allocate shader private data, hr %#x.\n", hr
);
1003 context_release(context
);
1007 if (!(device
->blitter
= wined3d_cpu_blitter_create()))
1009 ERR("Failed to create CPU blitter.\n");
1010 device
->shader_backend
->shader_free_private(device
, NULL
);
1011 context_release(context
);
1015 context_gl
= wined3d_context_gl(context
);
1017 wined3d_ffp_blitter_create(&device
->blitter
, context_gl
->gl_info
);
1018 if (!wined3d_glsl_blitter_create(&device
->blitter
, device
))
1019 wined3d_arbfp_blitter_create(&device
->blitter
, device
);
1020 wined3d_fbo_blitter_create(&device
->blitter
, context_gl
->gl_info
);
1021 wined3d_raw_blitter_create(&device
->blitter
, context_gl
->gl_info
);
1023 wined3d_device_gl_create_dummy_textures(wined3d_device_gl(device
), context_gl
);
1024 wined3d_device_create_default_samplers(device
, context
);
1025 context_release(context
);
1028 HRESULT
wined3d_device_set_implicit_swapchain(struct wined3d_device
*device
, struct wined3d_swapchain
*swapchain
)
1030 static const struct wined3d_color black
= {0.0f
, 0.0f
, 0.0f
, 0.0f
};
1031 const struct wined3d_swapchain_desc
*swapchain_desc
;
1032 DWORD clear_flags
= 0;
1035 TRACE("device %p, swapchain %p.\n", device
, swapchain
);
1037 if (device
->d3d_initialized
)
1038 return WINED3DERR_INVALIDCALL
;
1040 swapchain_desc
= &swapchain
->state
.desc
;
1041 if (swapchain_desc
->backbuffer_count
&& swapchain_desc
->backbuffer_bind_flags
& WINED3D_BIND_RENDER_TARGET
)
1043 struct wined3d_resource
*back_buffer
= &swapchain
->back_buffers
[0]->resource
;
1044 struct wined3d_view_desc view_desc
;
1046 view_desc
.format_id
= back_buffer
->format
->id
;
1047 view_desc
.flags
= 0;
1048 view_desc
.u
.texture
.level_idx
= 0;
1049 view_desc
.u
.texture
.level_count
= 1;
1050 view_desc
.u
.texture
.layer_idx
= 0;
1051 view_desc
.u
.texture
.layer_count
= 1;
1052 if (FAILED(hr
= wined3d_rendertarget_view_create(&view_desc
, back_buffer
,
1053 NULL
, &wined3d_null_parent_ops
, &device
->back_buffer_view
)))
1055 ERR("Failed to create rendertarget view, hr %#x.\n", hr
);
1060 device
->swapchain_count
= 1;
1061 if (!(device
->swapchains
= heap_calloc(device
->swapchain_count
, sizeof(*device
->swapchains
))))
1063 ERR("Failed to allocate swapchain array.\n");
1067 device
->swapchains
[0] = swapchain
;
1069 memset(device
->fb
.render_targets
, 0, sizeof(device
->fb
.render_targets
));
1070 if (FAILED(hr
= device
->adapter
->adapter_ops
->adapter_init_3d(device
)))
1073 device_init_swapchain_state(device
, swapchain
);
1075 TRACE("All defaults now set up.\n");
1077 /* Clear the screen. */
1078 if (device
->back_buffer_view
)
1079 clear_flags
|= WINED3DCLEAR_TARGET
;
1080 if (swapchain_desc
->enable_auto_depth_stencil
)
1081 clear_flags
|= WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
;
1083 wined3d_device_clear(device
, 0, NULL
, clear_flags
, &black
, 1.0f
, 0);
1085 if (wined3d_settings
.logo
)
1086 device_load_logo(device
, wined3d_settings
.logo
);
1091 heap_free(device
->swapchains
);
1092 device
->swapchains
= NULL
;
1093 device
->swapchain_count
= 0;
1094 if (device
->back_buffer_view
)
1096 wined3d_rendertarget_view_decref(device
->back_buffer_view
);
1097 device
->back_buffer_view
= NULL
;
1103 static void device_free_sampler(struct wine_rb_entry
*entry
, void *context
)
1105 struct wined3d_sampler
*sampler
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_sampler
, entry
);
1107 wined3d_sampler_decref(sampler
);
1110 void wined3d_device_uninit_3d(struct wined3d_device
*device
)
1112 BOOL no3d
= device
->wined3d
->flags
& WINED3D_NO3D
;
1113 struct wined3d_resource
*resource
, *cursor
;
1114 struct wined3d_rendertarget_view
*view
;
1115 struct wined3d_texture
*texture
;
1118 TRACE("device %p.\n", device
);
1120 if (!device
->d3d_initialized
&& !no3d
)
1122 ERR("Called while 3D support was not initialised.\n");
1126 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
1128 device
->swapchain_count
= 0;
1130 if ((texture
= device
->logo_texture
))
1132 device
->logo_texture
= NULL
;
1133 wined3d_texture_decref(texture
);
1136 if ((texture
= device
->cursor_texture
))
1138 device
->cursor_texture
= NULL
;
1139 wined3d_texture_decref(texture
);
1142 wined3d_cs_emit_reset_state(device
->cs
);
1143 state_cleanup(&device
->state
);
1144 memset(&device
->state
, 0, sizeof(device
->state
));
1145 state_init(&device
->state
, &device
->fb
, &device
->adapter
->d3d_info
, WINED3D_STATE_INIT_DEFAULT
);
1146 for (i
= 0; i
< device
->adapter
->d3d_info
.limits
.max_rt_count
; ++i
)
1148 wined3d_device_set_rendertarget_view(device
, i
, NULL
, FALSE
);
1151 wine_rb_clear(&device
->samplers
, device_free_sampler
, NULL
);
1153 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &device
->resources
, struct wined3d_resource
, resource_list_entry
)
1155 TRACE("Unloading resource %p.\n", resource
);
1156 wined3d_cs_emit_unload_resource(device
->cs
, resource
);
1159 device
->adapter
->adapter_ops
->adapter_uninit_3d(device
);
1160 device
->d3d_initialized
= FALSE
;
1162 if ((view
= device
->fb
.depth_stencil
))
1164 TRACE("Releasing depth/stencil view %p.\n", view
);
1166 device
->fb
.depth_stencil
= NULL
;
1167 wined3d_rendertarget_view_decref(view
);
1170 if ((view
= device
->auto_depth_stencil_view
))
1172 device
->auto_depth_stencil_view
= NULL
;
1173 if (wined3d_rendertarget_view_decref(view
))
1174 ERR("Something's still holding the auto depth/stencil view (%p).\n", view
);
1177 if ((view
= device
->back_buffer_view
))
1179 device
->back_buffer_view
= NULL
;
1180 wined3d_rendertarget_view_decref(view
);
1183 heap_free(device
->swapchains
);
1184 device
->swapchains
= NULL
;
1187 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
1188 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
1189 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
1191 * There is no way to deactivate thread safety once it is enabled.
1193 void CDECL
wined3d_device_set_multithreaded(struct wined3d_device
*device
)
1195 TRACE("device %p.\n", device
);
1197 /* For now just store the flag (needed in case of ddraw). */
1198 device
->create_parms
.flags
|= WINED3DCREATE_MULTITHREADED
;
1201 UINT CDECL
wined3d_device_get_available_texture_mem(const struct wined3d_device
*device
)
1203 const struct wined3d_driver_info
*driver_info
;
1205 TRACE("device %p.\n", device
);
1207 driver_info
= &device
->adapter
->driver_info
;
1209 TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n",
1210 wine_dbgstr_longlong(driver_info
->vram_bytes
),
1211 wine_dbgstr_longlong(device
->adapter
->vram_bytes_used
),
1212 wine_dbgstr_longlong(driver_info
->vram_bytes
- device
->adapter
->vram_bytes_used
));
1214 return min(UINT_MAX
, driver_info
->vram_bytes
- device
->adapter
->vram_bytes_used
);
1217 void CDECL
wined3d_device_set_stream_output(struct wined3d_device
*device
, UINT idx
,
1218 struct wined3d_buffer
*buffer
, UINT offset
)
1220 struct wined3d_stream_output
*stream
;
1221 struct wined3d_buffer
*prev_buffer
;
1223 TRACE("device %p, idx %u, buffer %p, offset %u.\n", device
, idx
, buffer
, offset
);
1225 if (idx
>= WINED3D_MAX_STREAM_OUTPUT_BUFFERS
)
1227 WARN("Invalid stream output %u.\n", idx
);
1231 stream
= &device
->state
.stream_output
[idx
];
1232 prev_buffer
= stream
->buffer
;
1235 wined3d_buffer_incref(buffer
);
1236 stream
->buffer
= buffer
;
1237 stream
->offset
= offset
;
1238 wined3d_cs_emit_set_stream_output(device
->cs
, idx
, buffer
, offset
);
1240 wined3d_buffer_decref(prev_buffer
);
1243 struct wined3d_buffer
* CDECL
wined3d_device_get_stream_output(struct wined3d_device
*device
,
1244 UINT idx
, UINT
*offset
)
1246 TRACE("device %p, idx %u, offset %p.\n", device
, idx
, offset
);
1248 if (idx
>= WINED3D_MAX_STREAM_OUTPUT_BUFFERS
)
1250 WARN("Invalid stream output %u.\n", idx
);
1255 *offset
= device
->state
.stream_output
[idx
].offset
;
1256 return device
->state
.stream_output
[idx
].buffer
;
1259 HRESULT CDECL
wined3d_device_set_stream_source(struct wined3d_device
*device
, UINT stream_idx
,
1260 struct wined3d_buffer
*buffer
, UINT offset
, UINT stride
)
1262 struct wined3d_stream_state
*stream
;
1263 struct wined3d_buffer
*prev_buffer
;
1265 TRACE("device %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
1266 device
, stream_idx
, buffer
, offset
, stride
);
1268 if (stream_idx
>= WINED3D_MAX_STREAMS
)
1270 WARN("Stream index %u out of range.\n", stream_idx
);
1271 return WINED3DERR_INVALIDCALL
;
1273 else if (offset
& 0x3)
1275 WARN("Offset %u is not 4 byte aligned.\n", offset
);
1276 return WINED3DERR_INVALIDCALL
;
1279 stream
= &device
->state
.streams
[stream_idx
];
1280 prev_buffer
= stream
->buffer
;
1282 if (prev_buffer
== buffer
1283 && stream
->stride
== stride
1284 && stream
->offset
== offset
)
1286 TRACE("Application is setting the old values over, nothing to do.\n");
1290 stream
->buffer
= buffer
;
1291 stream
->stride
= stride
;
1292 stream
->offset
= offset
;
1294 wined3d_buffer_incref(buffer
);
1295 wined3d_cs_emit_set_stream_source(device
->cs
, stream_idx
, buffer
, offset
, stride
);
1297 wined3d_buffer_decref(prev_buffer
);
1302 HRESULT CDECL
wined3d_device_get_stream_source(const struct wined3d_device
*device
,
1303 UINT stream_idx
, struct wined3d_buffer
**buffer
, UINT
*offset
, UINT
*stride
)
1305 const struct wined3d_stream_state
*stream
;
1307 TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
1308 device
, stream_idx
, buffer
, offset
, stride
);
1310 if (stream_idx
>= WINED3D_MAX_STREAMS
)
1312 WARN("Stream index %u out of range.\n", stream_idx
);
1313 return WINED3DERR_INVALIDCALL
;
1316 stream
= &device
->state
.streams
[stream_idx
];
1317 *buffer
= stream
->buffer
;
1319 *offset
= stream
->offset
;
1320 *stride
= stream
->stride
;
1325 static void wined3d_device_set_stream_source_freq(struct wined3d_device
*device
, UINT stream_idx
, UINT divider
)
1327 struct wined3d_stream_state
*stream
;
1328 UINT old_flags
, old_freq
;
1330 TRACE("device %p, stream_idx %u, divider %#x.\n", device
, stream_idx
, divider
);
1332 stream
= &device
->state
.streams
[stream_idx
];
1333 old_flags
= stream
->flags
;
1334 old_freq
= stream
->frequency
;
1336 stream
->flags
= divider
& (WINED3DSTREAMSOURCE_INSTANCEDATA
| WINED3DSTREAMSOURCE_INDEXEDDATA
);
1337 stream
->frequency
= divider
& 0x7fffff;
1338 if (stream
->frequency
!= old_freq
|| stream
->flags
!= old_flags
)
1339 wined3d_cs_emit_set_stream_source_freq(device
->cs
, stream_idx
, stream
->frequency
, stream
->flags
);
1342 static void wined3d_device_set_transform(struct wined3d_device
*device
,
1343 enum wined3d_transform_state d3dts
, const struct wined3d_matrix
*matrix
)
1345 TRACE("device %p, state %s, matrix %p.\n",
1346 device
, debug_d3dtstype(d3dts
), matrix
);
1347 TRACE("%.8e %.8e %.8e %.8e\n", matrix
->_11
, matrix
->_12
, matrix
->_13
, matrix
->_14
);
1348 TRACE("%.8e %.8e %.8e %.8e\n", matrix
->_21
, matrix
->_22
, matrix
->_23
, matrix
->_24
);
1349 TRACE("%.8e %.8e %.8e %.8e\n", matrix
->_31
, matrix
->_32
, matrix
->_33
, matrix
->_34
);
1350 TRACE("%.8e %.8e %.8e %.8e\n", matrix
->_41
, matrix
->_42
, matrix
->_43
, matrix
->_44
);
1352 /* If the new matrix is the same as the current one,
1353 * we cut off any further processing. this seems to be a reasonable
1354 * optimization because as was noticed, some apps (warcraft3 for example)
1355 * tend towards setting the same matrix repeatedly for some reason.
1357 * From here on we assume that the new matrix is different, wherever it matters. */
1358 if (!memcmp(&device
->state
.transforms
[d3dts
], matrix
, sizeof(*matrix
)))
1360 TRACE("The application is setting the same matrix over again.\n");
1364 device
->state
.transforms
[d3dts
] = *matrix
;
1365 wined3d_cs_emit_set_transform(device
->cs
, d3dts
, matrix
);
1368 static void wined3d_device_get_transform(const struct wined3d_device
*device
,
1369 enum wined3d_transform_state state
, struct wined3d_matrix
*matrix
)
1371 TRACE("device %p, state %s, matrix %p.\n", device
, debug_d3dtstype(state
), matrix
);
1373 *matrix
= device
->state
.transforms
[state
];
1376 /* Note lights are real special cases. Although the device caps state only
1377 * e.g. 8 are supported, you can reference any indexes you want as long as
1378 * that number max are enabled at any one point in time. Therefore since the
1379 * indices can be anything, we need a hashmap of them. However, this causes
1380 * stateblock problems. When capturing the state block, I duplicate the
1381 * hashmap, but when recording, just build a chain pretty much of commands to
1383 static void wined3d_device_set_light(struct wined3d_device
*device
,
1384 UINT light_idx
, const struct wined3d_light
*light
)
1386 struct wined3d_light_info
*object
= NULL
;
1389 TRACE("device %p, light_idx %u, light %p.\n", device
, light_idx
, light
);
1391 if (FAILED(wined3d_light_state_set_light(&device
->state
.light_state
, light_idx
, light
, &object
)))
1394 /* Initialize the object. */
1395 TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, "
1396 "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, "
1397 "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n",
1398 light_idx
, light
->type
, debug_color(&light
->diffuse
),
1399 debug_color(&light
->specular
), debug_color(&light
->ambient
),
1400 light
->position
.x
, light
->position
.y
, light
->position
.z
,
1401 light
->direction
.x
, light
->direction
.y
, light
->direction
.z
,
1402 light
->range
, light
->falloff
, light
->theta
, light
->phi
);
1404 switch (light
->type
)
1406 case WINED3D_LIGHT_POINT
:
1408 object
->position
.x
= light
->position
.x
;
1409 object
->position
.y
= light
->position
.y
;
1410 object
->position
.z
= light
->position
.z
;
1411 object
->position
.w
= 1.0f
;
1412 object
->cutoff
= 180.0f
;
1416 case WINED3D_LIGHT_DIRECTIONAL
:
1418 object
->direction
.x
= -light
->direction
.x
;
1419 object
->direction
.y
= -light
->direction
.y
;
1420 object
->direction
.z
= -light
->direction
.z
;
1421 object
->direction
.w
= 0.0f
;
1422 object
->exponent
= 0.0f
;
1423 object
->cutoff
= 180.0f
;
1426 case WINED3D_LIGHT_SPOT
:
1428 object
->position
.x
= light
->position
.x
;
1429 object
->position
.y
= light
->position
.y
;
1430 object
->position
.z
= light
->position
.z
;
1431 object
->position
.w
= 1.0f
;
1434 object
->direction
.x
= light
->direction
.x
;
1435 object
->direction
.y
= light
->direction
.y
;
1436 object
->direction
.z
= light
->direction
.z
;
1437 object
->direction
.w
= 0.0f
;
1439 /* opengl-ish and d3d-ish spot lights use too different models
1440 * for the light "intensity" as a function of the angle towards
1441 * the main light direction, so we only can approximate very
1442 * roughly. However, spot lights are rather rarely used in games
1443 * (if ever used at all). Furthermore if still used, probably
1444 * nobody pays attention to such details. */
1445 if (!light
->falloff
)
1447 /* Falloff = 0 is easy, because d3d's and opengl's spot light
1448 * equations have the falloff resp. exponent parameter as an
1449 * exponent, so the spot light lighting will always be 1.0 for
1450 * both of them, and we don't have to care for the rest of the
1451 * rather complex calculation. */
1452 object
->exponent
= 0.0f
;
1456 rho
= light
->theta
+ (light
->phi
- light
->theta
) / (2 * light
->falloff
);
1459 object
->exponent
= -0.3f
/ logf(cosf(rho
/ 2));
1462 if (object
->exponent
> 128.0f
)
1463 object
->exponent
= 128.0f
;
1465 object
->cutoff
= (float)(light
->phi
* 90 / M_PI
);
1469 case WINED3D_LIGHT_PARALLELPOINT
:
1470 object
->position
.x
= light
->position
.x
;
1471 object
->position
.y
= light
->position
.y
;
1472 object
->position
.z
= light
->position
.z
;
1473 object
->position
.w
= 1.0f
;
1477 FIXME("Unrecognized light type %#x.\n", light
->type
);
1480 wined3d_cs_emit_set_light(device
->cs
, object
);
1483 static void wined3d_device_set_light_enable(struct wined3d_device
*device
, UINT light_idx
, BOOL enable
)
1485 struct wined3d_light_info
*light_info
;
1487 TRACE("device %p, light_idx %u, enable %#x.\n", device
, light_idx
, enable
);
1489 /* Special case - enabling an undefined light creates one with a strict set of parameters. */
1490 if (!(light_info
= wined3d_light_state_get_light(&device
->state
.light_state
, light_idx
)))
1492 TRACE("Light enabled requested but light not defined, so defining one!\n");
1493 wined3d_device_set_light(device
, light_idx
, &WINED3D_default_light
);
1495 if (!(light_info
= wined3d_light_state_get_light(&device
->state
.light_state
, light_idx
)))
1497 FIXME("Adding default lights has failed dismally\n");
1502 wined3d_light_state_enable_light(&device
->state
.light_state
, &device
->adapter
->d3d_info
, light_info
, enable
);
1503 wined3d_cs_emit_set_light_enable(device
->cs
, light_idx
, enable
);
1506 static HRESULT
wined3d_device_set_clip_plane(struct wined3d_device
*device
,
1507 UINT plane_idx
, const struct wined3d_vec4
*plane
)
1509 TRACE("device %p, plane_idx %u, plane %p.\n", device
, plane_idx
, plane
);
1511 if (plane_idx
>= device
->adapter
->d3d_info
.limits
.max_clip_distances
)
1513 TRACE("Application has requested clipplane this device doesn't support.\n");
1514 return WINED3DERR_INVALIDCALL
;
1517 if (!memcmp(&device
->state
.clip_planes
[plane_idx
], plane
, sizeof(*plane
)))
1519 TRACE("Application is setting old values over, nothing to do.\n");
1523 device
->state
.clip_planes
[plane_idx
] = *plane
;
1525 wined3d_cs_emit_set_clip_plane(device
->cs
, plane_idx
, plane
);
1530 HRESULT CDECL
wined3d_device_set_clip_status(struct wined3d_device
*device
,
1531 const struct wined3d_clip_status
*clip_status
)
1533 FIXME("device %p, clip_status %p stub!\n", device
, clip_status
);
1536 return WINED3DERR_INVALIDCALL
;
1541 HRESULT CDECL
wined3d_device_get_clip_status(const struct wined3d_device
*device
,
1542 struct wined3d_clip_status
*clip_status
)
1544 FIXME("device %p, clip_status %p stub!\n", device
, clip_status
);
1547 return WINED3DERR_INVALIDCALL
;
1552 static void wined3d_device_set_material(struct wined3d_device
*device
, const struct wined3d_material
*material
)
1554 TRACE("device %p, material %p.\n", device
, material
);
1556 device
->state
.material
= *material
;
1557 wined3d_cs_emit_set_material(device
->cs
, material
);
1560 void CDECL
wined3d_device_set_index_buffer(struct wined3d_device
*device
,
1561 struct wined3d_buffer
*buffer
, enum wined3d_format_id format_id
, unsigned int offset
)
1563 enum wined3d_format_id prev_format
;
1564 struct wined3d_buffer
*prev_buffer
;
1565 unsigned int prev_offset
;
1567 TRACE("device %p, buffer %p, format %s, offset %u.\n",
1568 device
, buffer
, debug_d3dformat(format_id
), offset
);
1570 prev_buffer
= device
->state
.index_buffer
;
1571 prev_format
= device
->state
.index_format
;
1572 prev_offset
= device
->state
.index_offset
;
1574 if (prev_buffer
== buffer
&& prev_format
== format_id
&& prev_offset
== offset
)
1578 wined3d_buffer_incref(buffer
);
1579 device
->state
.index_buffer
= buffer
;
1580 device
->state
.index_format
= format_id
;
1581 device
->state
.index_offset
= offset
;
1582 wined3d_cs_emit_set_index_buffer(device
->cs
, buffer
, format_id
, offset
);
1584 wined3d_buffer_decref(prev_buffer
);
1587 struct wined3d_buffer
* CDECL
wined3d_device_get_index_buffer(const struct wined3d_device
*device
,
1588 enum wined3d_format_id
*format
, unsigned int *offset
)
1590 TRACE("device %p, format %p, offset %p.\n", device
, format
, offset
);
1592 *format
= device
->state
.index_format
;
1594 *offset
= device
->state
.index_offset
;
1595 return device
->state
.index_buffer
;
1598 void CDECL
wined3d_device_set_base_vertex_index(struct wined3d_device
*device
, INT base_index
)
1600 TRACE("device %p, base_index %d.\n", device
, base_index
);
1602 device
->state
.base_vertex_index
= base_index
;
1605 void CDECL
wined3d_device_set_viewports(struct wined3d_device
*device
, unsigned int viewport_count
,
1606 const struct wined3d_viewport
*viewports
)
1610 TRACE("device %p, viewport_count %u, viewports %p.\n", device
, viewport_count
, viewports
);
1612 for (i
= 0; i
< viewport_count
; ++i
)
1614 TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", i
, viewports
[i
].x
, viewports
[i
].y
,
1615 viewports
[i
].width
, viewports
[i
].height
, viewports
[i
].min_z
, viewports
[i
].max_z
);
1619 memcpy(device
->state
.viewports
, viewports
, viewport_count
* sizeof(*viewports
));
1621 memset(device
->state
.viewports
, 0, sizeof(device
->state
.viewports
));
1622 device
->state
.viewport_count
= viewport_count
;
1624 wined3d_cs_emit_set_viewports(device
->cs
, viewport_count
, viewports
);
1627 void CDECL
wined3d_device_get_viewports(const struct wined3d_device
*device
, unsigned int *viewport_count
,
1628 struct wined3d_viewport
*viewports
)
1632 TRACE("device %p, viewport_count %p, viewports %p.\n", device
, viewport_count
, viewports
);
1634 count
= viewport_count
? min(*viewport_count
, device
->state
.viewport_count
) : 1;
1635 if (count
&& viewports
)
1636 memcpy(viewports
, device
->state
.viewports
, count
* sizeof(*viewports
));
1638 *viewport_count
= device
->state
.viewport_count
;
1641 static void resolve_depth_buffer(struct wined3d_device
*device
)
1643 const struct wined3d_state
*state
= &device
->state
;
1644 struct wined3d_rendertarget_view
*src_view
;
1645 struct wined3d_resource
*dst_resource
;
1646 struct wined3d_texture
*dst_texture
;
1648 if (!(dst_texture
= state
->textures
[0]))
1650 dst_resource
= &dst_texture
->resource
;
1651 if (!(dst_resource
->format_flags
& WINED3DFMT_FLAG_DEPTH
))
1653 if (!(src_view
= state
->fb
->depth_stencil
))
1656 wined3d_device_resolve_sub_resource(device
, dst_resource
, 0,
1657 src_view
->resource
, src_view
->sub_resource_idx
, dst_resource
->format
->id
);
1660 void CDECL
wined3d_device_set_blend_state(struct wined3d_device
*device
,
1661 struct wined3d_blend_state
*blend_state
, const struct wined3d_color
*blend_factor
)
1663 struct wined3d_state
*state
= &device
->state
;
1664 struct wined3d_blend_state
*prev
;
1666 TRACE("device %p, blend_state %p, blend_factor %s.\n", device
, blend_state
, debug_color(blend_factor
));
1668 prev
= state
->blend_state
;
1669 if (prev
== blend_state
&& !memcmp(blend_factor
, &state
->blend_factor
, sizeof(*blend_factor
)))
1673 wined3d_blend_state_incref(blend_state
);
1674 state
->blend_state
= blend_state
;
1675 state
->blend_factor
= *blend_factor
;
1676 wined3d_cs_emit_set_blend_state(device
->cs
, blend_state
, blend_factor
);
1678 wined3d_blend_state_decref(prev
);
1681 struct wined3d_blend_state
* CDECL
wined3d_device_get_blend_state(const struct wined3d_device
*device
,
1682 struct wined3d_color
*blend_factor
)
1684 const struct wined3d_state
*state
= &device
->state
;
1686 TRACE("device %p, blend_factor %p.\n", device
, blend_factor
);
1688 *blend_factor
= state
->blend_factor
;
1689 return state
->blend_state
;
1692 void CDECL
wined3d_device_set_rasterizer_state(struct wined3d_device
*device
,
1693 struct wined3d_rasterizer_state
*rasterizer_state
)
1695 struct wined3d_rasterizer_state
*prev
;
1697 TRACE("device %p, rasterizer_state %p.\n", device
, rasterizer_state
);
1699 prev
= device
->state
.rasterizer_state
;
1700 if (prev
== rasterizer_state
)
1703 if (rasterizer_state
)
1704 wined3d_rasterizer_state_incref(rasterizer_state
);
1705 device
->state
.rasterizer_state
= rasterizer_state
;
1706 wined3d_cs_emit_set_rasterizer_state(device
->cs
, rasterizer_state
);
1708 wined3d_rasterizer_state_decref(prev
);
1711 struct wined3d_rasterizer_state
* CDECL
wined3d_device_get_rasterizer_state(struct wined3d_device
*device
)
1713 TRACE("device %p.\n", device
);
1715 return device
->state
.rasterizer_state
;
1718 void CDECL
wined3d_device_set_render_state(struct wined3d_device
*device
,
1719 enum wined3d_render_state state
, DWORD value
)
1721 TRACE("device %p, state %s (%#x), value %#x.\n", device
, debug_d3drenderstate(state
), state
, value
);
1723 if (state
> WINEHIGHEST_RENDER_STATE
)
1725 WARN("Unhandled render state %#x.\n", state
);
1729 if (value
== device
->state
.render_states
[state
])
1730 TRACE("Application is setting the old value over, nothing to do.\n");
1733 device
->state
.render_states
[state
] = value
;
1734 wined3d_cs_emit_set_render_state(device
->cs
, state
, value
);
1737 if (state
== WINED3D_RS_POINTSIZE
&& value
== WINED3D_RESZ_CODE
)
1739 TRACE("RESZ multisampled depth buffer resolve triggered.\n");
1740 resolve_depth_buffer(device
);
1744 DWORD CDECL
wined3d_device_get_render_state(const struct wined3d_device
*device
, enum wined3d_render_state state
)
1746 TRACE("device %p, state %s (%#x).\n", device
, debug_d3drenderstate(state
), state
);
1748 return device
->state
.render_states
[state
];
1751 static void wined3d_device_set_sampler_state(struct wined3d_device
*device
,
1752 UINT sampler_idx
, enum wined3d_sampler_state state
, DWORD value
)
1754 TRACE("device %p, sampler_idx %u, state %s, value %#x.\n",
1755 device
, sampler_idx
, debug_d3dsamplerstate(state
), value
);
1757 if (sampler_idx
>= WINED3DVERTEXTEXTURESAMPLER0
&& sampler_idx
<= WINED3DVERTEXTEXTURESAMPLER3
)
1758 sampler_idx
-= (WINED3DVERTEXTEXTURESAMPLER0
- WINED3D_MAX_FRAGMENT_SAMPLERS
);
1760 if (value
== device
->state
.sampler_states
[sampler_idx
][state
])
1762 TRACE("Application is setting the old value over, nothing to do.\n");
1766 device
->state
.sampler_states
[sampler_idx
][state
] = value
;
1767 wined3d_cs_emit_set_sampler_state(device
->cs
, sampler_idx
, state
, value
);
1770 void CDECL
wined3d_device_set_scissor_rects(struct wined3d_device
*device
, unsigned int rect_count
,
1775 TRACE("device %p, rect_count %u, rects %p.\n", device
, rect_count
, rects
);
1777 for (i
= 0; i
< rect_count
; ++i
)
1779 TRACE("%u: %s\n", i
, wine_dbgstr_rect(&rects
[i
]));
1782 if (device
->state
.scissor_rect_count
== rect_count
1783 && !memcmp(device
->state
.scissor_rects
, rects
, rect_count
* sizeof(*rects
)))
1785 TRACE("App is setting the old scissor rectangles over, nothing to do.\n");
1790 memcpy(device
->state
.scissor_rects
, rects
, rect_count
* sizeof(*rects
));
1792 memset(device
->state
.scissor_rects
, 0, sizeof(device
->state
.scissor_rects
));
1793 device
->state
.scissor_rect_count
= rect_count
;
1795 wined3d_cs_emit_set_scissor_rects(device
->cs
, rect_count
, rects
);
1798 void CDECL
wined3d_device_get_scissor_rects(const struct wined3d_device
*device
, unsigned int *rect_count
, RECT
*rects
)
1802 TRACE("device %p, rect_count %p, rects %p.\n", device
, rect_count
, rects
);
1804 count
= rect_count
? min(*rect_count
, device
->state
.scissor_rect_count
) : 1;
1806 memcpy(rects
, device
->state
.scissor_rects
, count
* sizeof(*rects
));
1808 *rect_count
= device
->state
.scissor_rect_count
;
1811 void CDECL
wined3d_device_set_vertex_declaration(struct wined3d_device
*device
,
1812 struct wined3d_vertex_declaration
*declaration
)
1814 struct wined3d_vertex_declaration
*prev
= device
->state
.vertex_declaration
;
1816 TRACE("device %p, declaration %p.\n", device
, declaration
);
1818 if (declaration
== prev
)
1822 wined3d_vertex_declaration_incref(declaration
);
1823 device
->state
.vertex_declaration
= declaration
;
1824 wined3d_cs_emit_set_vertex_declaration(device
->cs
, declaration
);
1826 wined3d_vertex_declaration_decref(prev
);
1829 struct wined3d_vertex_declaration
* CDECL
wined3d_device_get_vertex_declaration(const struct wined3d_device
*device
)
1831 TRACE("device %p.\n", device
);
1833 return device
->state
.vertex_declaration
;
1836 void CDECL
wined3d_device_set_vertex_shader(struct wined3d_device
*device
, struct wined3d_shader
*shader
)
1838 struct wined3d_shader
*prev
= device
->state
.shader
[WINED3D_SHADER_TYPE_VERTEX
];
1840 TRACE("device %p, shader %p.\n", device
, shader
);
1846 wined3d_shader_incref(shader
);
1847 device
->state
.shader
[WINED3D_SHADER_TYPE_VERTEX
] = shader
;
1848 wined3d_cs_emit_set_shader(device
->cs
, WINED3D_SHADER_TYPE_VERTEX
, shader
);
1850 wined3d_shader_decref(prev
);
1853 struct wined3d_shader
* CDECL
wined3d_device_get_vertex_shader(const struct wined3d_device
*device
)
1855 TRACE("device %p.\n", device
);
1857 return device
->state
.shader
[WINED3D_SHADER_TYPE_VERTEX
];
1860 void CDECL
wined3d_device_set_constant_buffer(struct wined3d_device
*device
,
1861 enum wined3d_shader_type type
, UINT idx
, struct wined3d_buffer
*buffer
)
1863 struct wined3d_buffer
*prev
;
1865 TRACE("device %p, type %#x, idx %u, buffer %p.\n", device
, type
, idx
, buffer
);
1867 if (idx
>= MAX_CONSTANT_BUFFERS
)
1869 WARN("Invalid constant buffer index %u.\n", idx
);
1873 prev
= device
->state
.cb
[type
][idx
];
1878 wined3d_buffer_incref(buffer
);
1879 device
->state
.cb
[type
][idx
] = buffer
;
1880 wined3d_cs_emit_set_constant_buffer(device
->cs
, type
, idx
, buffer
);
1882 wined3d_buffer_decref(prev
);
1885 struct wined3d_buffer
* CDECL
wined3d_device_get_constant_buffer(const struct wined3d_device
*device
,
1886 enum wined3d_shader_type shader_type
, unsigned int idx
)
1888 TRACE("device %p, shader_type %#x, idx %u.\n", device
, shader_type
, idx
);
1890 if (idx
>= MAX_CONSTANT_BUFFERS
)
1892 WARN("Invalid constant buffer index %u.\n", idx
);
1896 return device
->state
.cb
[shader_type
][idx
];
1899 static void wined3d_device_set_shader_resource_view(struct wined3d_device
*device
,
1900 enum wined3d_shader_type type
, UINT idx
, struct wined3d_shader_resource_view
*view
)
1902 struct wined3d_shader_resource_view
*prev
;
1904 if (idx
>= MAX_SHADER_RESOURCE_VIEWS
)
1906 WARN("Invalid view index %u.\n", idx
);
1910 prev
= device
->state
.shader_resource_view
[type
][idx
];
1914 if (view
&& wined3d_resource_check_fbo_attached(&device
->state
, view
->resource
, view
->format
))
1916 WARN("Application is trying to bind resource which is attached as render target.\n");
1922 wined3d_shader_resource_view_incref(view
);
1923 ++view
->resource
->srv_bind_count_device
;
1926 device
->state
.shader_resource_view
[type
][idx
] = view
;
1927 wined3d_cs_emit_set_shader_resource_view(device
->cs
, type
, idx
, view
);
1930 --prev
->resource
->srv_bind_count_device
;
1931 wined3d_shader_resource_view_decref(prev
);
1935 void CDECL
wined3d_device_set_vs_resource_view(struct wined3d_device
*device
,
1936 UINT idx
, struct wined3d_shader_resource_view
*view
)
1938 TRACE("device %p, idx %u, view %p.\n", device
, idx
, view
);
1940 wined3d_device_set_shader_resource_view(device
, WINED3D_SHADER_TYPE_VERTEX
, idx
, view
);
1943 static struct wined3d_shader_resource_view
*wined3d_device_get_shader_resource_view(
1944 const struct wined3d_device
*device
, enum wined3d_shader_type shader_type
, unsigned int idx
)
1946 if (idx
>= MAX_SHADER_RESOURCE_VIEWS
)
1948 WARN("Invalid view index %u.\n", idx
);
1952 return device
->state
.shader_resource_view
[shader_type
][idx
];
1955 struct wined3d_shader_resource_view
* CDECL
wined3d_device_get_vs_resource_view(const struct wined3d_device
*device
,
1958 TRACE("device %p, idx %u.\n", device
, idx
);
1960 return wined3d_device_get_shader_resource_view(device
, WINED3D_SHADER_TYPE_VERTEX
, idx
);
1963 static void wined3d_device_set_sampler(struct wined3d_device
*device
,
1964 enum wined3d_shader_type type
, UINT idx
, struct wined3d_sampler
*sampler
)
1966 struct wined3d_sampler
*prev
;
1968 if (idx
>= MAX_SAMPLER_OBJECTS
)
1970 WARN("Invalid sampler index %u.\n", idx
);
1974 prev
= device
->state
.sampler
[type
][idx
];
1975 if (sampler
== prev
)
1979 wined3d_sampler_incref(sampler
);
1980 device
->state
.sampler
[type
][idx
] = sampler
;
1981 wined3d_cs_emit_set_sampler(device
->cs
, type
, idx
, sampler
);
1983 wined3d_sampler_decref(prev
);
1986 void CDECL
wined3d_device_set_vs_sampler(struct wined3d_device
*device
, UINT idx
, struct wined3d_sampler
*sampler
)
1988 TRACE("device %p, idx %u, sampler %p.\n", device
, idx
, sampler
);
1990 wined3d_device_set_sampler(device
, WINED3D_SHADER_TYPE_VERTEX
, idx
, sampler
);
1993 static struct wined3d_sampler
*wined3d_device_get_sampler(const struct wined3d_device
*device
,
1994 enum wined3d_shader_type shader_type
, unsigned int idx
)
1996 if (idx
>= MAX_SAMPLER_OBJECTS
)
1998 WARN("Invalid sampler index %u.\n", idx
);
2002 return device
->state
.sampler
[shader_type
][idx
];
2005 struct wined3d_sampler
* CDECL
wined3d_device_get_vs_sampler(const struct wined3d_device
*device
, UINT idx
)
2007 TRACE("device %p, idx %u.\n", device
, idx
);
2009 return wined3d_device_get_sampler(device
, WINED3D_SHADER_TYPE_VERTEX
, idx
);
2012 static void wined3d_device_set_vs_consts_b(struct wined3d_device
*device
,
2013 unsigned int start_idx
, unsigned int count
, const BOOL
*constants
)
2017 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2018 device
, start_idx
, count
, constants
);
2020 memcpy(&device
->state
.vs_consts_b
[start_idx
], constants
, count
* sizeof(*constants
));
2023 for (i
= 0; i
< count
; ++i
)
2024 TRACE("Set BOOL constant %u to %#x.\n", start_idx
+ i
, constants
[i
]);
2027 wined3d_cs_push_constants(device
->cs
, WINED3D_PUSH_CONSTANTS_VS_B
, start_idx
, count
, constants
);
2030 static void wined3d_device_set_vs_consts_i(struct wined3d_device
*device
,
2031 unsigned int start_idx
, unsigned int count
, const struct wined3d_ivec4
*constants
)
2035 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2036 device
, start_idx
, count
, constants
);
2038 memcpy(&device
->state
.vs_consts_i
[start_idx
], constants
, count
* sizeof(*constants
));
2041 for (i
= 0; i
< count
; ++i
)
2042 TRACE("Set ivec4 constant %u to %s.\n", start_idx
+ i
, debug_ivec4(&constants
[i
]));
2045 wined3d_cs_push_constants(device
->cs
, WINED3D_PUSH_CONSTANTS_VS_I
, start_idx
, count
, constants
);
2048 static void wined3d_device_set_vs_consts_f(struct wined3d_device
*device
,
2049 unsigned int start_idx
, unsigned int count
, const struct wined3d_vec4
*constants
)
2053 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2054 device
, start_idx
, count
, constants
);
2056 memcpy(&device
->state
.vs_consts_f
[start_idx
], constants
, count
* sizeof(*constants
));
2059 for (i
= 0; i
< count
; ++i
)
2060 TRACE("Set vec4 constant %u to %s.\n", start_idx
+ i
, debug_vec4(&constants
[i
]));
2063 wined3d_cs_push_constants(device
->cs
, WINED3D_PUSH_CONSTANTS_VS_F
, start_idx
, count
, constants
);
2066 void CDECL
wined3d_device_set_pixel_shader(struct wined3d_device
*device
, struct wined3d_shader
*shader
)
2068 struct wined3d_shader
*prev
= device
->state
.shader
[WINED3D_SHADER_TYPE_PIXEL
];
2070 TRACE("device %p, shader %p.\n", device
, shader
);
2076 wined3d_shader_incref(shader
);
2077 device
->state
.shader
[WINED3D_SHADER_TYPE_PIXEL
] = shader
;
2078 wined3d_cs_emit_set_shader(device
->cs
, WINED3D_SHADER_TYPE_PIXEL
, shader
);
2080 wined3d_shader_decref(prev
);
2083 struct wined3d_shader
* CDECL
wined3d_device_get_pixel_shader(const struct wined3d_device
*device
)
2085 TRACE("device %p.\n", device
);
2087 return device
->state
.shader
[WINED3D_SHADER_TYPE_PIXEL
];
2090 void CDECL
wined3d_device_set_ps_resource_view(struct wined3d_device
*device
,
2091 UINT idx
, struct wined3d_shader_resource_view
*view
)
2093 TRACE("device %p, idx %u, view %p.\n", device
, idx
, view
);
2095 wined3d_device_set_shader_resource_view(device
, WINED3D_SHADER_TYPE_PIXEL
, idx
, view
);
2098 struct wined3d_shader_resource_view
* CDECL
wined3d_device_get_ps_resource_view(const struct wined3d_device
*device
,
2101 TRACE("device %p, idx %u.\n", device
, idx
);
2103 return wined3d_device_get_shader_resource_view(device
, WINED3D_SHADER_TYPE_PIXEL
, idx
);
2106 void CDECL
wined3d_device_set_ps_sampler(struct wined3d_device
*device
, UINT idx
, struct wined3d_sampler
*sampler
)
2108 TRACE("device %p, idx %u, sampler %p.\n", device
, idx
, sampler
);
2110 wined3d_device_set_sampler(device
, WINED3D_SHADER_TYPE_PIXEL
, idx
, sampler
);
2113 struct wined3d_sampler
* CDECL
wined3d_device_get_ps_sampler(const struct wined3d_device
*device
, UINT idx
)
2115 TRACE("device %p, idx %u.\n", device
, idx
);
2117 return wined3d_device_get_sampler(device
, WINED3D_SHADER_TYPE_PIXEL
, idx
);
2120 static void wined3d_device_set_ps_consts_b(struct wined3d_device
*device
,
2121 unsigned int start_idx
, unsigned int count
, const BOOL
*constants
)
2125 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2126 device
, start_idx
, count
, constants
);
2128 memcpy(&device
->state
.ps_consts_b
[start_idx
], constants
, count
* sizeof(*constants
));
2131 for (i
= 0; i
< count
; ++i
)
2132 TRACE("Set BOOL constant %u to %#x.\n", start_idx
+ i
, constants
[i
]);
2135 wined3d_cs_push_constants(device
->cs
, WINED3D_PUSH_CONSTANTS_PS_B
, start_idx
, count
, constants
);
2138 static void wined3d_device_set_ps_consts_i(struct wined3d_device
*device
,
2139 unsigned int start_idx
, unsigned int count
, const struct wined3d_ivec4
*constants
)
2143 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2144 device
, start_idx
, count
, constants
);
2146 memcpy(&device
->state
.ps_consts_i
[start_idx
], constants
, count
* sizeof(*constants
));
2149 for (i
= 0; i
< count
; ++i
)
2150 TRACE("Set ivec4 constant %u to %s.\n", start_idx
+ i
, debug_ivec4(&constants
[i
]));
2153 wined3d_cs_push_constants(device
->cs
, WINED3D_PUSH_CONSTANTS_PS_I
, start_idx
, count
, constants
);
2156 static void wined3d_device_set_ps_consts_f(struct wined3d_device
*device
,
2157 unsigned int start_idx
, unsigned int count
, const struct wined3d_vec4
*constants
)
2161 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2162 device
, start_idx
, count
, constants
);
2164 memcpy(&device
->state
.ps_consts_f
[start_idx
], constants
, count
* sizeof(*constants
));
2167 for (i
= 0; i
< count
; ++i
)
2168 TRACE("Set vec4 constant %u to %s.\n", start_idx
+ i
, debug_vec4(&constants
[i
]));
2171 wined3d_cs_push_constants(device
->cs
, WINED3D_PUSH_CONSTANTS_PS_F
, start_idx
, count
, constants
);
2174 void CDECL
wined3d_device_set_hull_shader(struct wined3d_device
*device
, struct wined3d_shader
*shader
)
2176 struct wined3d_shader
*prev
;
2178 TRACE("device %p, shader %p.\n", device
, shader
);
2180 prev
= device
->state
.shader
[WINED3D_SHADER_TYPE_HULL
];
2184 wined3d_shader_incref(shader
);
2185 device
->state
.shader
[WINED3D_SHADER_TYPE_HULL
] = shader
;
2186 wined3d_cs_emit_set_shader(device
->cs
, WINED3D_SHADER_TYPE_HULL
, shader
);
2188 wined3d_shader_decref(prev
);
2191 struct wined3d_shader
* CDECL
wined3d_device_get_hull_shader(const struct wined3d_device
*device
)
2193 TRACE("device %p.\n", device
);
2195 return device
->state
.shader
[WINED3D_SHADER_TYPE_HULL
];
2198 void CDECL
wined3d_device_set_hs_resource_view(struct wined3d_device
*device
,
2199 unsigned int idx
, struct wined3d_shader_resource_view
*view
)
2201 TRACE("device %p, idx %u, view %p.\n", device
, idx
, view
);
2203 wined3d_device_set_shader_resource_view(device
, WINED3D_SHADER_TYPE_HULL
, idx
, view
);
2206 struct wined3d_shader_resource_view
* CDECL
wined3d_device_get_hs_resource_view(const struct wined3d_device
*device
,
2209 TRACE("device %p, idx %u.\n", device
, idx
);
2211 return wined3d_device_get_shader_resource_view(device
, WINED3D_SHADER_TYPE_HULL
, idx
);
2214 void CDECL
wined3d_device_set_hs_sampler(struct wined3d_device
*device
,
2215 unsigned int idx
, struct wined3d_sampler
*sampler
)
2217 TRACE("device %p, idx %u, sampler %p.\n", device
, idx
, sampler
);
2219 wined3d_device_set_sampler(device
, WINED3D_SHADER_TYPE_HULL
, idx
, sampler
);
2222 struct wined3d_sampler
* CDECL
wined3d_device_get_hs_sampler(const struct wined3d_device
*device
, unsigned int idx
)
2224 TRACE("device %p, idx %u.\n", device
, idx
);
2226 return wined3d_device_get_sampler(device
, WINED3D_SHADER_TYPE_HULL
, idx
);
2229 void CDECL
wined3d_device_set_domain_shader(struct wined3d_device
*device
, struct wined3d_shader
*shader
)
2231 struct wined3d_shader
*prev
;
2233 TRACE("device %p, shader %p.\n", device
, shader
);
2235 prev
= device
->state
.shader
[WINED3D_SHADER_TYPE_DOMAIN
];
2239 wined3d_shader_incref(shader
);
2240 device
->state
.shader
[WINED3D_SHADER_TYPE_DOMAIN
] = shader
;
2241 wined3d_cs_emit_set_shader(device
->cs
, WINED3D_SHADER_TYPE_DOMAIN
, shader
);
2243 wined3d_shader_decref(prev
);
2246 struct wined3d_shader
* CDECL
wined3d_device_get_domain_shader(const struct wined3d_device
*device
)
2248 TRACE("device %p.\n", device
);
2250 return device
->state
.shader
[WINED3D_SHADER_TYPE_DOMAIN
];
2253 void CDECL
wined3d_device_set_ds_resource_view(struct wined3d_device
*device
,
2254 unsigned int idx
, struct wined3d_shader_resource_view
*view
)
2256 TRACE("device %p, idx %u, view %p.\n", device
, idx
, view
);
2258 wined3d_device_set_shader_resource_view(device
, WINED3D_SHADER_TYPE_DOMAIN
, idx
, view
);
2261 struct wined3d_shader_resource_view
* CDECL
wined3d_device_get_ds_resource_view(const struct wined3d_device
*device
,
2264 TRACE("device %p, idx %u.\n", device
, idx
);
2266 return wined3d_device_get_shader_resource_view(device
, WINED3D_SHADER_TYPE_DOMAIN
, idx
);
2269 void CDECL
wined3d_device_set_ds_sampler(struct wined3d_device
*device
,
2270 unsigned int idx
, struct wined3d_sampler
*sampler
)
2272 TRACE("device %p, idx %u, sampler %p.\n", device
, idx
, sampler
);
2274 wined3d_device_set_sampler(device
, WINED3D_SHADER_TYPE_DOMAIN
, idx
, sampler
);
2277 struct wined3d_sampler
* CDECL
wined3d_device_get_ds_sampler(const struct wined3d_device
*device
, unsigned int idx
)
2279 TRACE("device %p, idx %u.\n", device
, idx
);
2281 return wined3d_device_get_sampler(device
, WINED3D_SHADER_TYPE_DOMAIN
, idx
);
2284 void CDECL
wined3d_device_set_geometry_shader(struct wined3d_device
*device
, struct wined3d_shader
*shader
)
2286 struct wined3d_shader
*prev
= device
->state
.shader
[WINED3D_SHADER_TYPE_GEOMETRY
];
2288 TRACE("device %p, shader %p.\n", device
, shader
);
2293 wined3d_shader_incref(shader
);
2294 device
->state
.shader
[WINED3D_SHADER_TYPE_GEOMETRY
] = shader
;
2295 wined3d_cs_emit_set_shader(device
->cs
, WINED3D_SHADER_TYPE_GEOMETRY
, shader
);
2297 wined3d_shader_decref(prev
);
2300 struct wined3d_shader
* CDECL
wined3d_device_get_geometry_shader(const struct wined3d_device
*device
)
2302 TRACE("device %p.\n", device
);
2304 return device
->state
.shader
[WINED3D_SHADER_TYPE_GEOMETRY
];
2307 void CDECL
wined3d_device_set_gs_resource_view(struct wined3d_device
*device
,
2308 UINT idx
, struct wined3d_shader_resource_view
*view
)
2310 TRACE("device %p, idx %u, view %p.\n", device
, idx
, view
);
2312 wined3d_device_set_shader_resource_view(device
, WINED3D_SHADER_TYPE_GEOMETRY
, idx
, view
);
2315 struct wined3d_shader_resource_view
* CDECL
wined3d_device_get_gs_resource_view(const struct wined3d_device
*device
,
2318 TRACE("device %p, idx %u.\n", device
, idx
);
2320 return wined3d_device_get_shader_resource_view(device
, WINED3D_SHADER_TYPE_GEOMETRY
, idx
);
2323 void CDECL
wined3d_device_set_gs_sampler(struct wined3d_device
*device
, UINT idx
, struct wined3d_sampler
*sampler
)
2325 TRACE("device %p, idx %u, sampler %p.\n", device
, idx
, sampler
);
2327 wined3d_device_set_sampler(device
, WINED3D_SHADER_TYPE_GEOMETRY
, idx
, sampler
);
2330 struct wined3d_sampler
* CDECL
wined3d_device_get_gs_sampler(const struct wined3d_device
*device
, UINT idx
)
2332 TRACE("device %p, idx %u.\n", device
, idx
);
2334 return wined3d_device_get_sampler(device
, WINED3D_SHADER_TYPE_GEOMETRY
, idx
);
2337 void CDECL
wined3d_device_set_compute_shader(struct wined3d_device
*device
, struct wined3d_shader
*shader
)
2339 struct wined3d_shader
*prev
;
2341 TRACE("device %p, shader %p.\n", device
, shader
);
2343 prev
= device
->state
.shader
[WINED3D_SHADER_TYPE_COMPUTE
];
2347 wined3d_shader_incref(shader
);
2348 device
->state
.shader
[WINED3D_SHADER_TYPE_COMPUTE
] = shader
;
2349 wined3d_cs_emit_set_shader(device
->cs
, WINED3D_SHADER_TYPE_COMPUTE
, shader
);
2351 wined3d_shader_decref(prev
);
2354 struct wined3d_shader
* CDECL
wined3d_device_get_compute_shader(const struct wined3d_device
*device
)
2356 TRACE("device %p.\n", device
);
2358 return device
->state
.shader
[WINED3D_SHADER_TYPE_COMPUTE
];
2361 void CDECL
wined3d_device_set_cs_resource_view(struct wined3d_device
*device
,
2362 unsigned int idx
, struct wined3d_shader_resource_view
*view
)
2364 TRACE("device %p, idx %u, view %p.\n", device
, idx
, view
);
2366 wined3d_device_set_shader_resource_view(device
, WINED3D_SHADER_TYPE_COMPUTE
, idx
, view
);
2369 struct wined3d_shader_resource_view
* CDECL
wined3d_device_get_cs_resource_view(const struct wined3d_device
*device
,
2372 TRACE("device %p, idx %u.\n", device
, idx
);
2374 return wined3d_device_get_shader_resource_view(device
, WINED3D_SHADER_TYPE_COMPUTE
, idx
);
2377 void CDECL
wined3d_device_set_cs_sampler(struct wined3d_device
*device
,
2378 unsigned int idx
, struct wined3d_sampler
*sampler
)
2380 TRACE("device %p, idx %u, sampler %p.\n", device
, idx
, sampler
);
2382 wined3d_device_set_sampler(device
, WINED3D_SHADER_TYPE_COMPUTE
, idx
, sampler
);
2385 struct wined3d_sampler
* CDECL
wined3d_device_get_cs_sampler(const struct wined3d_device
*device
, unsigned int idx
)
2387 TRACE("device %p, idx %u.\n", device
, idx
);
2389 return wined3d_device_get_sampler(device
, WINED3D_SHADER_TYPE_COMPUTE
, idx
);
2392 static void wined3d_device_set_pipeline_unordered_access_view(struct wined3d_device
*device
,
2393 enum wined3d_pipeline pipeline
, unsigned int idx
, struct wined3d_unordered_access_view
*uav
,
2394 unsigned int initial_count
)
2396 struct wined3d_unordered_access_view
*prev
;
2398 if (idx
>= MAX_UNORDERED_ACCESS_VIEWS
)
2400 WARN("Invalid UAV index %u.\n", idx
);
2404 prev
= device
->state
.unordered_access_view
[pipeline
][idx
];
2405 if (uav
== prev
&& initial_count
== ~0u)
2409 wined3d_unordered_access_view_incref(uav
);
2410 device
->state
.unordered_access_view
[pipeline
][idx
] = uav
;
2411 wined3d_cs_emit_set_unordered_access_view(device
->cs
, pipeline
, idx
, uav
, initial_count
);
2413 wined3d_unordered_access_view_decref(prev
);
2416 static struct wined3d_unordered_access_view
*wined3d_device_get_pipeline_unordered_access_view(
2417 const struct wined3d_device
*device
, enum wined3d_pipeline pipeline
, unsigned int idx
)
2419 if (idx
>= MAX_UNORDERED_ACCESS_VIEWS
)
2421 WARN("Invalid UAV index %u.\n", idx
);
2425 return device
->state
.unordered_access_view
[pipeline
][idx
];
2428 void CDECL
wined3d_device_set_cs_uav(struct wined3d_device
*device
, unsigned int idx
,
2429 struct wined3d_unordered_access_view
*uav
, unsigned int initial_count
)
2431 TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device
, idx
, uav
, initial_count
);
2433 wined3d_device_set_pipeline_unordered_access_view(device
, WINED3D_PIPELINE_COMPUTE
, idx
, uav
, initial_count
);
2436 struct wined3d_unordered_access_view
* CDECL
wined3d_device_get_cs_uav(const struct wined3d_device
*device
,
2439 TRACE("device %p, idx %u.\n", device
, idx
);
2441 return wined3d_device_get_pipeline_unordered_access_view(device
, WINED3D_PIPELINE_COMPUTE
, idx
);
2444 void CDECL
wined3d_device_set_unordered_access_view(struct wined3d_device
*device
,
2445 unsigned int idx
, struct wined3d_unordered_access_view
*uav
, unsigned int initial_count
)
2447 TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device
, idx
, uav
, initial_count
);
2449 wined3d_device_set_pipeline_unordered_access_view(device
, WINED3D_PIPELINE_GRAPHICS
, idx
, uav
, initial_count
);
2452 struct wined3d_unordered_access_view
* CDECL
wined3d_device_get_unordered_access_view(
2453 const struct wined3d_device
*device
, unsigned int idx
)
2455 TRACE("device %p, idx %u.\n", device
, idx
);
2457 return wined3d_device_get_pipeline_unordered_access_view(device
, WINED3D_PIPELINE_GRAPHICS
, idx
);
2460 void CDECL
wined3d_device_set_max_frame_latency(struct wined3d_device
*device
, unsigned int latency
)
2467 device
->max_frame_latency
= latency
;
2468 for (i
= 0; i
< device
->swapchain_count
; ++i
)
2469 swapchain_set_max_frame_latency(device
->swapchains
[i
], device
);
2472 unsigned int CDECL
wined3d_device_get_max_frame_latency(const struct wined3d_device
*device
)
2474 return device
->max_frame_latency
;
2477 static unsigned int wined3d_get_flexible_vertex_size(DWORD fvf
)
2479 unsigned int texcoord_count
= (fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
2480 unsigned int i
, size
= 0;
2482 if (fvf
& WINED3DFVF_NORMAL
) size
+= 3 * sizeof(float);
2483 if (fvf
& WINED3DFVF_DIFFUSE
) size
+= sizeof(DWORD
);
2484 if (fvf
& WINED3DFVF_SPECULAR
) size
+= sizeof(DWORD
);
2485 if (fvf
& WINED3DFVF_PSIZE
) size
+= sizeof(DWORD
);
2486 switch (fvf
& WINED3DFVF_POSITION_MASK
)
2488 case WINED3DFVF_XYZ
: size
+= 3 * sizeof(float); break;
2489 case WINED3DFVF_XYZRHW
: size
+= 4 * sizeof(float); break;
2490 case WINED3DFVF_XYZB1
: size
+= 4 * sizeof(float); break;
2491 case WINED3DFVF_XYZB2
: size
+= 5 * sizeof(float); break;
2492 case WINED3DFVF_XYZB3
: size
+= 6 * sizeof(float); break;
2493 case WINED3DFVF_XYZB4
: size
+= 7 * sizeof(float); break;
2494 case WINED3DFVF_XYZB5
: size
+= 8 * sizeof(float); break;
2495 case WINED3DFVF_XYZW
: size
+= 4 * sizeof(float); break;
2496 default: FIXME("Unexpected position mask %#x.\n", fvf
& WINED3DFVF_POSITION_MASK
);
2498 for (i
= 0; i
< texcoord_count
; ++i
)
2500 size
+= GET_TEXCOORD_SIZE_FROM_FVF(fvf
, i
) * sizeof(float);
2506 static void wined3d_format_get_colour(const struct wined3d_format
*format
,
2507 const void *data
, struct wined3d_color
*colour
)
2509 float *output
= &colour
->r
;
2510 const uint32_t *u32_data
;
2511 const uint16_t *u16_data
;
2512 const float *f32_data
;
2515 static const struct wined3d_color default_colour
= {0.0f
, 0.0f
, 0.0f
, 1.0f
};
2516 static unsigned int warned
;
2520 case WINED3DFMT_B8G8R8A8_UNORM
:
2522 wined3d_color_from_d3dcolor(colour
, *u32_data
);
2525 case WINED3DFMT_R8G8B8A8_UNORM
:
2527 colour
->r
= (*u32_data
& 0xffu
) / 255.0f
;
2528 colour
->g
= ((*u32_data
>> 8) & 0xffu
) / 255.0f
;
2529 colour
->b
= ((*u32_data
>> 16) & 0xffu
) / 255.0f
;
2530 colour
->a
= ((*u32_data
>> 24) & 0xffu
) / 255.0f
;
2533 case WINED3DFMT_R16G16_UNORM
:
2534 case WINED3DFMT_R16G16B16A16_UNORM
:
2536 *colour
= default_colour
;
2537 for (i
= 0; i
< format
->component_count
; ++i
)
2538 output
[i
] = u16_data
[i
] / 65535.0f
;
2541 case WINED3DFMT_R32_FLOAT
:
2542 case WINED3DFMT_R32G32_FLOAT
:
2543 case WINED3DFMT_R32G32B32_FLOAT
:
2544 case WINED3DFMT_R32G32B32A32_FLOAT
:
2546 *colour
= default_colour
;
2547 for (i
= 0; i
< format
->component_count
; ++i
)
2548 output
[i
] = f32_data
[i
];
2552 *colour
= default_colour
;
2554 FIXME("Unhandled colour format conversion, format %s.\n", debug_d3dformat(format
->id
));
2559 static void wined3d_colour_from_mcs(struct wined3d_color
*colour
, enum wined3d_material_color_source mcs
,
2560 const struct wined3d_color
*material_colour
, unsigned int index
,
2561 const struct wined3d_stream_info
*stream_info
)
2563 const struct wined3d_stream_info_element
*element
= NULL
;
2567 case WINED3D_MCS_MATERIAL
:
2568 *colour
= *material_colour
;
2571 case WINED3D_MCS_COLOR1
:
2572 if (!(stream_info
->use_map
& (1u << WINED3D_FFP_DIFFUSE
)))
2574 colour
->r
= colour
->g
= colour
->b
= colour
->a
= 1.0f
;
2577 element
= &stream_info
->elements
[WINED3D_FFP_DIFFUSE
];
2580 case WINED3D_MCS_COLOR2
:
2581 if (!(stream_info
->use_map
& (1u << WINED3D_FFP_SPECULAR
)))
2583 colour
->r
= colour
->g
= colour
->b
= colour
->a
= 0.0f
;
2586 element
= &stream_info
->elements
[WINED3D_FFP_SPECULAR
];
2590 colour
->r
= colour
->g
= colour
->b
= colour
->a
= 0.0f
;
2591 ERR("Invalid material colour source %#x.\n", mcs
);
2595 wined3d_format_get_colour(element
->format
, &element
->data
.addr
[index
* element
->stride
], colour
);
2598 static float wined3d_clamp(float value
, float min_value
, float max_value
)
2600 return value
< min_value
? min_value
: value
> max_value
? max_value
: value
;
2603 static float wined3d_vec3_dot(const struct wined3d_vec3
*v0
, const struct wined3d_vec3
*v1
)
2605 return v0
->x
* v1
->x
+ v0
->y
* v1
->y
+ v0
->z
* v1
->z
;
2608 static void wined3d_vec3_subtract(struct wined3d_vec3
*v0
, const struct wined3d_vec3
*v1
)
2615 static void wined3d_vec3_scale(struct wined3d_vec3
*v
, float s
)
2622 static void wined3d_vec3_normalise(struct wined3d_vec3
*v
)
2624 float rnorm
= 1.0f
/ sqrtf(wined3d_vec3_dot(v
, v
));
2626 if (isfinite(rnorm
))
2627 wined3d_vec3_scale(v
, rnorm
);
2630 static void wined3d_vec3_transform(struct wined3d_vec3
*dst
,
2631 const struct wined3d_vec3
*v
, const struct wined3d_matrix_3x3
*m
)
2633 struct wined3d_vec3 tmp
;
2635 tmp
.x
= v
->x
* m
->_11
+ v
->y
* m
->_21
+ v
->z
* m
->_31
;
2636 tmp
.y
= v
->x
* m
->_12
+ v
->y
* m
->_22
+ v
->z
* m
->_32
;
2637 tmp
.z
= v
->x
* m
->_13
+ v
->y
* m
->_23
+ v
->z
* m
->_33
;
2642 static void wined3d_color_clamp(struct wined3d_color
*dst
, const struct wined3d_color
*src
,
2643 float min_value
, float max_value
)
2645 dst
->r
= wined3d_clamp(src
->r
, min_value
, max_value
);
2646 dst
->g
= wined3d_clamp(src
->g
, min_value
, max_value
);
2647 dst
->b
= wined3d_clamp(src
->b
, min_value
, max_value
);
2648 dst
->a
= wined3d_clamp(src
->a
, min_value
, max_value
);
2651 static void wined3d_color_rgb_mul_add(struct wined3d_color
*dst
, const struct wined3d_color
*src
, float c
)
2653 dst
->r
+= src
->r
* c
;
2654 dst
->g
+= src
->g
* c
;
2655 dst
->b
+= src
->b
* c
;
2658 static void init_transformed_lights(struct lights_settings
*ls
,
2659 const struct wined3d_state
*state
, BOOL legacy_lighting
, BOOL compute_lighting
)
2661 const struct wined3d_light_info
*lights
[WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS
];
2662 const struct wined3d_light_info
*light_info
;
2663 struct light_transformed
*light
;
2664 struct wined3d_vec4 vec4
;
2665 unsigned int light_count
;
2666 unsigned int i
, index
;
2668 memset(ls
, 0, sizeof(*ls
));
2670 ls
->lighting
= !!compute_lighting
;
2671 ls
->fog_mode
= state
->render_states
[WINED3D_RS_FOGVERTEXMODE
];
2672 ls
->fog_coord_mode
= state
->render_states
[WINED3D_RS_RANGEFOGENABLE
]
2673 ? WINED3D_FFP_VS_FOG_RANGE
: WINED3D_FFP_VS_FOG_DEPTH
;
2674 ls
->fog_start
= wined3d_get_float_state(state
, WINED3D_RS_FOGSTART
);
2675 ls
->fog_end
= wined3d_get_float_state(state
, WINED3D_RS_FOGEND
);
2676 ls
->fog_density
= wined3d_get_float_state(state
, WINED3D_RS_FOGDENSITY
);
2678 if (ls
->fog_mode
== WINED3D_FOG_NONE
&& !compute_lighting
)
2681 multiply_matrix(&ls
->modelview_matrix
, &state
->transforms
[WINED3D_TS_VIEW
],
2682 &state
->transforms
[WINED3D_TS_WORLD_MATRIX(0)]);
2684 if (!compute_lighting
)
2687 compute_normal_matrix(&ls
->normal_matrix
._11
, legacy_lighting
, &ls
->modelview_matrix
);
2689 wined3d_color_from_d3dcolor(&ls
->ambient_light
, state
->render_states
[WINED3D_RS_AMBIENT
]);
2690 ls
->legacy_lighting
= !!legacy_lighting
;
2691 ls
->normalise
= !!state
->render_states
[WINED3D_RS_NORMALIZENORMALS
];
2692 ls
->localviewer
= !!state
->render_states
[WINED3D_RS_LOCALVIEWER
];
2694 for (i
= 0, index
= 0; i
< LIGHTMAP_SIZE
&& index
< ARRAY_SIZE(lights
); ++i
)
2696 LIST_FOR_EACH_ENTRY(light_info
, &state
->light_state
.light_map
[i
], struct wined3d_light_info
, entry
)
2698 if (!light_info
->enabled
)
2701 switch (light_info
->OriginalParms
.type
)
2703 case WINED3D_LIGHT_DIRECTIONAL
:
2704 ++ls
->directional_light_count
;
2707 case WINED3D_LIGHT_POINT
:
2708 ++ls
->point_light_count
;
2711 case WINED3D_LIGHT_SPOT
:
2712 ++ls
->spot_light_count
;
2715 case WINED3D_LIGHT_PARALLELPOINT
:
2716 ++ls
->parallel_point_light_count
;
2720 FIXME("Unhandled light type %#x.\n", light_info
->OriginalParms
.type
);
2723 lights
[index
++] = light_info
;
2724 if (index
== WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS
)
2729 light_count
= index
;
2730 for (i
= 0, index
= 0; i
< light_count
; ++i
)
2732 light_info
= lights
[i
];
2733 if (light_info
->OriginalParms
.type
!= WINED3D_LIGHT_DIRECTIONAL
)
2736 light
= &ls
->lights
[index
];
2737 wined3d_vec4_transform(&vec4
, &light_info
->direction
, &state
->transforms
[WINED3D_TS_VIEW
]);
2738 light
->direction
= *(struct wined3d_vec3
*)&vec4
;
2739 wined3d_vec3_normalise(&light
->direction
);
2741 light
->diffuse
= light_info
->OriginalParms
.diffuse
;
2742 light
->ambient
= light_info
->OriginalParms
.ambient
;
2743 light
->specular
= light_info
->OriginalParms
.specular
;
2747 for (i
= 0; i
< light_count
; ++i
)
2749 light_info
= lights
[i
];
2750 if (light_info
->OriginalParms
.type
!= WINED3D_LIGHT_POINT
)
2753 light
= &ls
->lights
[index
];
2755 wined3d_vec4_transform(&light
->position
, &light_info
->position
, &state
->transforms
[WINED3D_TS_VIEW
]);
2756 light
->range
= light_info
->OriginalParms
.range
;
2757 light
->c_att
= light_info
->OriginalParms
.attenuation0
;
2758 light
->l_att
= light_info
->OriginalParms
.attenuation1
;
2759 light
->q_att
= light_info
->OriginalParms
.attenuation2
;
2761 light
->diffuse
= light_info
->OriginalParms
.diffuse
;
2762 light
->ambient
= light_info
->OriginalParms
.ambient
;
2763 light
->specular
= light_info
->OriginalParms
.specular
;
2767 for (i
= 0; i
< light_count
; ++i
)
2769 light_info
= lights
[i
];
2770 if (light_info
->OriginalParms
.type
!= WINED3D_LIGHT_SPOT
)
2773 light
= &ls
->lights
[index
];
2775 wined3d_vec4_transform(&light
->position
, &light_info
->position
, &state
->transforms
[WINED3D_TS_VIEW
]);
2776 wined3d_vec4_transform(&vec4
, &light_info
->direction
, &state
->transforms
[WINED3D_TS_VIEW
]);
2777 light
->direction
= *(struct wined3d_vec3
*)&vec4
;
2778 wined3d_vec3_normalise(&light
->direction
);
2779 light
->range
= light_info
->OriginalParms
.range
;
2780 light
->falloff
= light_info
->OriginalParms
.falloff
;
2781 light
->c_att
= light_info
->OriginalParms
.attenuation0
;
2782 light
->l_att
= light_info
->OriginalParms
.attenuation1
;
2783 light
->q_att
= light_info
->OriginalParms
.attenuation2
;
2784 light
->cos_htheta
= cosf(light_info
->OriginalParms
.theta
/ 2.0f
);
2785 light
->cos_hphi
= cosf(light_info
->OriginalParms
.phi
/ 2.0f
);
2787 light
->diffuse
= light_info
->OriginalParms
.diffuse
;
2788 light
->ambient
= light_info
->OriginalParms
.ambient
;
2789 light
->specular
= light_info
->OriginalParms
.specular
;
2793 for (i
= 0; i
< light_count
; ++i
)
2795 light_info
= lights
[i
];
2796 if (light_info
->OriginalParms
.type
!= WINED3D_LIGHT_PARALLELPOINT
)
2799 light
= &ls
->lights
[index
];
2801 wined3d_vec4_transform(&vec4
, &light_info
->position
, &state
->transforms
[WINED3D_TS_VIEW
]);
2802 *(struct wined3d_vec3
*)&light
->position
= *(struct wined3d_vec3
*)&vec4
;
2803 wined3d_vec3_normalise((struct wined3d_vec3
*)&light
->position
);
2804 light
->diffuse
= light_info
->OriginalParms
.diffuse
;
2805 light
->ambient
= light_info
->OriginalParms
.ambient
;
2806 light
->specular
= light_info
->OriginalParms
.specular
;
2811 static void update_light_diffuse_specular(struct wined3d_color
*diffuse
, struct wined3d_color
*specular
,
2812 const struct wined3d_vec3
*dir
, float att
, float material_shininess
,
2813 const struct wined3d_vec3
*normal_transformed
,
2814 const struct wined3d_vec3
*position_transformed_normalised
,
2815 const struct light_transformed
*light
, const struct lights_settings
*ls
)
2817 struct wined3d_vec3 vec3
;
2820 c
= wined3d_clamp(wined3d_vec3_dot(dir
, normal_transformed
), 0.0f
, 1.0f
);
2821 wined3d_color_rgb_mul_add(diffuse
, &light
->diffuse
, c
* att
);
2824 if (ls
->localviewer
)
2825 wined3d_vec3_subtract(&vec3
, position_transformed_normalised
);
2828 wined3d_vec3_normalise(&vec3
);
2829 t
= wined3d_vec3_dot(normal_transformed
, &vec3
);
2830 if (t
> 0.0f
&& (!ls
->legacy_lighting
|| material_shininess
> 0.0f
)
2831 && wined3d_vec3_dot(dir
, normal_transformed
) > 0.0f
)
2832 wined3d_color_rgb_mul_add(specular
, &light
->specular
, att
* powf(t
, material_shininess
));
2835 static void light_set_vertex_data(struct lights_settings
*ls
,
2836 const struct wined3d_vec4
*position
)
2838 if (ls
->fog_mode
== WINED3D_FOG_NONE
&& !ls
->lighting
)
2841 wined3d_vec4_transform(&ls
->position_transformed
, position
, &ls
->modelview_matrix
);
2842 wined3d_vec3_scale((struct wined3d_vec3
*)&ls
->position_transformed
, 1.0f
/ ls
->position_transformed
.w
);
2845 static void compute_light(struct wined3d_color
*ambient
, struct wined3d_color
*diffuse
,
2846 struct wined3d_color
*specular
, struct lights_settings
*ls
, const struct wined3d_vec3
*normal
,
2847 float material_shininess
)
2849 struct wined3d_vec3 position_transformed_normalised
;
2850 struct wined3d_vec3 normal_transformed
= {0.0f
};
2851 const struct light_transformed
*light
;
2852 struct wined3d_vec3 dir
, dst
;
2853 unsigned int i
, index
;
2856 position_transformed_normalised
= *(const struct wined3d_vec3
*)&ls
->position_transformed
;
2857 wined3d_vec3_normalise(&position_transformed_normalised
);
2861 wined3d_vec3_transform(&normal_transformed
, normal
, &ls
->normal_matrix
);
2863 wined3d_vec3_normalise(&normal_transformed
);
2866 diffuse
->r
= diffuse
->g
= diffuse
->b
= diffuse
->a
= 0.0f
;
2867 *specular
= *diffuse
;
2868 *ambient
= ls
->ambient_light
;
2871 for (i
= 0; i
< ls
->directional_light_count
; ++i
, ++index
)
2873 light
= &ls
->lights
[index
];
2875 wined3d_color_rgb_mul_add(ambient
, &light
->ambient
, 1.0f
);
2877 update_light_diffuse_specular(diffuse
, specular
, &light
->direction
, 1.0f
, material_shininess
,
2878 &normal_transformed
, &position_transformed_normalised
, light
, ls
);
2881 for (i
= 0; i
< ls
->point_light_count
; ++i
, ++index
)
2883 light
= &ls
->lights
[index
];
2884 dir
.x
= light
->position
.x
- ls
->position_transformed
.x
;
2885 dir
.y
= light
->position
.y
- ls
->position_transformed
.y
;
2886 dir
.z
= light
->position
.z
- ls
->position_transformed
.z
;
2888 dst
.z
= wined3d_vec3_dot(&dir
, &dir
);
2889 dst
.y
= sqrtf(dst
.z
);
2891 if (ls
->legacy_lighting
)
2893 dst
.y
= (light
->range
- dst
.y
) / light
->range
;
2894 if (!(dst
.y
> 0.0f
))
2896 dst
.z
= dst
.y
* dst
.y
;
2900 if (!(dst
.y
<= light
->range
))
2903 att
= dst
.x
* light
->c_att
+ dst
.y
* light
->l_att
+ dst
.z
* light
->q_att
;
2904 if (!ls
->legacy_lighting
)
2907 wined3d_color_rgb_mul_add(ambient
, &light
->ambient
, att
);
2910 wined3d_vec3_normalise(&dir
);
2911 update_light_diffuse_specular(diffuse
, specular
, &dir
, att
, material_shininess
,
2912 &normal_transformed
, &position_transformed_normalised
, light
, ls
);
2916 for (i
= 0; i
< ls
->spot_light_count
; ++i
, ++index
)
2920 light
= &ls
->lights
[index
];
2922 dir
.x
= light
->position
.x
- ls
->position_transformed
.x
;
2923 dir
.y
= light
->position
.y
- ls
->position_transformed
.y
;
2924 dir
.z
= light
->position
.z
- ls
->position_transformed
.z
;
2926 dst
.z
= wined3d_vec3_dot(&dir
, &dir
);
2927 dst
.y
= sqrtf(dst
.z
);
2930 if (ls
->legacy_lighting
)
2932 dst
.y
= (light
->range
- dst
.y
) / light
->range
;
2933 if (!(dst
.y
> 0.0f
))
2935 dst
.z
= dst
.y
* dst
.y
;
2939 if (!(dst
.y
<= light
->range
))
2942 wined3d_vec3_normalise(&dir
);
2943 t
= -wined3d_vec3_dot(&dir
, &light
->direction
);
2944 if (t
> light
->cos_htheta
)
2946 else if (t
<= light
->cos_hphi
)
2949 att
= powf((t
- light
->cos_hphi
) / (light
->cos_htheta
- light
->cos_hphi
), light
->falloff
);
2951 t
= dst
.x
* light
->c_att
+ dst
.y
* light
->l_att
+ dst
.z
* light
->q_att
;
2952 if (ls
->legacy_lighting
)
2957 wined3d_color_rgb_mul_add(ambient
, &light
->ambient
, att
);
2960 update_light_diffuse_specular(diffuse
, specular
, &dir
, att
, material_shininess
,
2961 &normal_transformed
, &position_transformed_normalised
, light
, ls
);
2964 for (i
= 0; i
< ls
->parallel_point_light_count
; ++i
, ++index
)
2966 light
= &ls
->lights
[index
];
2968 wined3d_color_rgb_mul_add(ambient
, &light
->ambient
, 1.0f
);
2970 update_light_diffuse_specular(diffuse
, specular
, (const struct wined3d_vec3
*)&light
->position
,
2971 1.0f
, material_shininess
, &normal_transformed
, &position_transformed_normalised
, light
, ls
);
2975 static float wined3d_calculate_fog_factor(float fog_coord
, const struct lights_settings
*ls
)
2977 switch (ls
->fog_mode
)
2979 case WINED3D_FOG_NONE
:
2981 case WINED3D_FOG_LINEAR
:
2982 return (ls
->fog_end
- fog_coord
) / (ls
->fog_end
- ls
->fog_start
);
2983 case WINED3D_FOG_EXP
:
2984 return expf(-fog_coord
* ls
->fog_density
);
2985 case WINED3D_FOG_EXP2
:
2986 return expf(-fog_coord
* fog_coord
* ls
->fog_density
* ls
->fog_density
);
2988 ERR("Unhandled fog mode %#x.\n", ls
->fog_mode
);
2993 static void update_fog_factor(float *fog_factor
, struct lights_settings
*ls
)
2997 if (ls
->fog_mode
== WINED3D_FOG_NONE
)
3000 switch (ls
->fog_coord_mode
)
3002 case WINED3D_FFP_VS_FOG_RANGE
:
3003 fog_coord
= sqrtf(wined3d_vec3_dot((const struct wined3d_vec3
*)&ls
->position_transformed
,
3004 (const struct wined3d_vec3
*)&ls
->position_transformed
));
3007 case WINED3D_FFP_VS_FOG_DEPTH
:
3008 fog_coord
= fabsf(ls
->position_transformed
.z
);
3012 ERR("Unhandled fog coordinate mode %#x.\n", ls
->fog_coord_mode
);
3015 *fog_factor
= wined3d_calculate_fog_factor(fog_coord
, ls
);
3018 /* Context activation is done by the caller. */
3019 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3020 static HRESULT
process_vertices_strided(const struct wined3d_device
*device
, DWORD dwDestIndex
, DWORD dwCount
,
3021 const struct wined3d_stream_info
*stream_info
, struct wined3d_buffer
*dest
, DWORD flags
, DWORD dst_fvf
)
3023 enum wined3d_material_color_source diffuse_source
, specular_source
, ambient_source
, emissive_source
;
3024 const struct wined3d_color
*material_specular_state_colour
;
3025 struct wined3d_matrix mat
, proj_mat
, view_mat
, world_mat
;
3026 const struct wined3d_state
*state
= &device
->state
;
3027 const struct wined3d_format
*output_colour_format
;
3028 static const struct wined3d_color black
;
3029 struct wined3d_map_desc map_desc
;
3030 struct wined3d_box box
= {0};
3031 struct wined3d_viewport vp
;
3032 unsigned int texture_count
;
3033 struct lights_settings ls
;
3034 unsigned int vertex_size
;
3035 BOOL do_clip
, lighting
;
3041 if (!(stream_info
->use_map
& (1u << WINED3D_FFP_POSITION
)))
3043 ERR("Source has no position mask.\n");
3044 return WINED3DERR_INVALIDCALL
;
3047 if (state
->render_states
[WINED3D_RS_CLIPPING
])
3049 static BOOL warned
= FALSE
;
3051 * The clipping code is not quite correct. Some things need
3052 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3053 * so disable clipping for now.
3054 * (The graphics in Half-Life are broken, and my processvertices
3055 * test crashes with IDirect3DDevice3)
3062 FIXME("Clipping is broken and disabled for now\n");
3068 vertex_size
= wined3d_get_flexible_vertex_size(dst_fvf
);
3069 box
.left
= dwDestIndex
* vertex_size
;
3070 box
.right
= box
.left
+ dwCount
* vertex_size
;
3071 if (FAILED(hr
= wined3d_resource_map(&dest
->resource
, 0, &map_desc
, &box
, WINED3D_MAP_WRITE
)))
3073 WARN("Failed to map buffer, hr %#x.\n", hr
);
3076 dest_ptr
= map_desc
.data
;
3078 wined3d_device_get_transform(device
, WINED3D_TS_VIEW
, &view_mat
);
3079 wined3d_device_get_transform(device
, WINED3D_TS_PROJECTION
, &proj_mat
);
3080 wined3d_device_get_transform(device
, WINED3D_TS_WORLD_MATRIX(0), &world_mat
);
3082 TRACE("View mat:\n");
3083 TRACE("%.8e %.8e %.8e %.8e\n", view_mat
._11
, view_mat
._12
, view_mat
._13
, view_mat
._14
);
3084 TRACE("%.8e %.8e %.8e %.8e\n", view_mat
._21
, view_mat
._22
, view_mat
._23
, view_mat
._24
);
3085 TRACE("%.8e %.8e %.8e %.8e\n", view_mat
._31
, view_mat
._32
, view_mat
._33
, view_mat
._34
);
3086 TRACE("%.8e %.8e %.8e %.8e\n", view_mat
._41
, view_mat
._42
, view_mat
._43
, view_mat
._44
);
3088 TRACE("Proj mat:\n");
3089 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat
._11
, proj_mat
._12
, proj_mat
._13
, proj_mat
._14
);
3090 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat
._21
, proj_mat
._22
, proj_mat
._23
, proj_mat
._24
);
3091 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat
._31
, proj_mat
._32
, proj_mat
._33
, proj_mat
._34
);
3092 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat
._41
, proj_mat
._42
, proj_mat
._43
, proj_mat
._44
);
3094 TRACE("World mat:\n");
3095 TRACE("%.8e %.8e %.8e %.8e\n", world_mat
._11
, world_mat
._12
, world_mat
._13
, world_mat
._14
);
3096 TRACE("%.8e %.8e %.8e %.8e\n", world_mat
._21
, world_mat
._22
, world_mat
._23
, world_mat
._24
);
3097 TRACE("%.8e %.8e %.8e %.8e\n", world_mat
._31
, world_mat
._32
, world_mat
._33
, world_mat
._34
);
3098 TRACE("%.8e %.8e %.8e %.8e\n", world_mat
._41
, world_mat
._42
, world_mat
._43
, world_mat
._44
);
3100 /* Get the viewport */
3101 wined3d_device_get_viewports(device
, NULL
, &vp
);
3102 TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n",
3103 vp
.x
, vp
.y
, vp
.width
, vp
.height
, vp
.min_z
, vp
.max_z
);
3105 multiply_matrix(&mat
,&view_mat
,&world_mat
);
3106 multiply_matrix(&mat
,&proj_mat
,&mat
);
3108 texture_count
= (dst_fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
3110 lighting
= state
->render_states
[WINED3D_RS_LIGHTING
]
3111 && (dst_fvf
& (WINED3DFVF_DIFFUSE
| WINED3DFVF_SPECULAR
));
3112 wined3d_get_material_colour_source(&diffuse_source
, &emissive_source
,
3113 &ambient_source
, &specular_source
, state
, stream_info
);
3114 output_colour_format
= wined3d_get_format(device
->adapter
, WINED3DFMT_B8G8R8A8_UNORM
, 0);
3115 material_specular_state_colour
= state
->render_states
[WINED3D_RS_SPECULARENABLE
]
3116 ? &state
->material
.specular
: &black
;
3117 init_transformed_lights(&ls
, state
, device
->adapter
->d3d_info
.wined3d_creation_flags
3118 & WINED3D_LEGACY_FFP_LIGHTING
, lighting
);
3120 wined3d_viewport_get_z_range(&vp
, &min_z
, &max_z
);
3122 for (i
= 0; i
< dwCount
; ++i
)
3124 const struct wined3d_stream_info_element
*position_element
= &stream_info
->elements
[WINED3D_FFP_POSITION
];
3125 const float *p
= (const float *)&position_element
->data
.addr
[i
* position_element
->stride
];
3126 struct wined3d_color ambient
, diffuse
, specular
;
3127 struct wined3d_vec4 position
;
3128 unsigned int tex_index
;
3135 light_set_vertex_data(&ls
, &position
);
3137 if ( ((dst_fvf
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZ
) ||
3138 ((dst_fvf
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) ) {
3139 /* The position first */
3141 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
3143 /* Multiplication with world, view and projection matrix. */
3144 x
= (p
[0] * mat
._11
) + (p
[1] * mat
._21
) + (p
[2] * mat
._31
) + mat
._41
;
3145 y
= (p
[0] * mat
._12
) + (p
[1] * mat
._22
) + (p
[2] * mat
._32
) + mat
._42
;
3146 z
= (p
[0] * mat
._13
) + (p
[1] * mat
._23
) + (p
[2] * mat
._33
) + mat
._43
;
3147 rhw
= (p
[0] * mat
._14
) + (p
[1] * mat
._24
) + (p
[2] * mat
._34
) + mat
._44
;
3149 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
3151 /* WARNING: The following things are taken from d3d7 and were not yet checked
3152 * against d3d8 or d3d9!
3155 /* Clipping conditions: From msdn
3157 * A vertex is clipped if it does not match the following requirements
3161 * 0 < rhw ( Not in d3d7, but tested in d3d7)
3163 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3164 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3168 if (!do_clip
|| (-rhw
- eps
< x
&& -rhw
- eps
< y
&& -eps
< z
&& x
<= rhw
+ eps
3169 && y
<= rhw
+ eps
&& z
<= rhw
+ eps
&& rhw
> eps
))
3171 /* "Normal" viewport transformation (not clipped)
3172 * 1) The values are divided by rhw
3173 * 2) The y axis is negative, so multiply it with -1
3174 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3175 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3176 * 4) Multiply x with Width/2 and add Width/2
3177 * 5) The same for the height
3178 * 6) Add the viewpoint X and Y to the 2D coordinates and
3179 * The minimum Z value to z
3180 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3182 * Well, basically it's simply a linear transformation into viewport
3196 x
+= vp
.width
/ 2 + vp
.x
;
3197 y
+= vp
.height
/ 2 + vp
.y
;
3202 /* That vertex got clipped
3203 * Contrary to OpenGL it is not dropped completely, it just
3204 * undergoes a different calculation.
3206 TRACE("Vertex got clipped\n");
3213 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3214 * outside of the main vertex buffer memory. That needs some more
3219 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
3222 ( (float *) dest_ptr
)[0] = x
;
3223 ( (float *) dest_ptr
)[1] = y
;
3224 ( (float *) dest_ptr
)[2] = z
;
3225 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
3227 dest_ptr
+= 3 * sizeof(float);
3229 if ((dst_fvf
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
)
3230 dest_ptr
+= sizeof(float);
3233 if (dst_fvf
& WINED3DFVF_PSIZE
)
3234 dest_ptr
+= sizeof(DWORD
);
3236 if (dst_fvf
& WINED3DFVF_NORMAL
)
3238 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_NORMAL
];
3239 const float *normal
= (const float *)(element
->data
.addr
+ i
* element
->stride
);
3240 /* AFAIK this should go into the lighting information */
3241 FIXME("Didn't expect the destination to have a normal\n");
3242 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
3247 const struct wined3d_stream_info_element
*element
;
3248 struct wined3d_vec3
*normal
;
3250 if (stream_info
->use_map
& (1u << WINED3D_FFP_NORMAL
))
3252 element
= &stream_info
->elements
[WINED3D_FFP_NORMAL
];
3253 normal
= (struct wined3d_vec3
*)&element
->data
.addr
[i
* element
->stride
];
3259 compute_light(&ambient
, &diffuse
, &specular
, &ls
, normal
,
3260 state
->render_states
[WINED3D_RS_SPECULARENABLE
] ? state
->material
.power
: 0.0f
);
3263 if (dst_fvf
& WINED3DFVF_DIFFUSE
)
3265 struct wined3d_color material_diffuse
, material_ambient
, material_emissive
, diffuse_colour
;
3267 wined3d_colour_from_mcs(&material_diffuse
, diffuse_source
,
3268 &state
->material
.diffuse
, i
, stream_info
);
3272 wined3d_colour_from_mcs(&material_ambient
, ambient_source
,
3273 &state
->material
.ambient
, i
, stream_info
);
3274 wined3d_colour_from_mcs(&material_emissive
, emissive_source
,
3275 &state
->material
.emissive
, i
, stream_info
);
3277 diffuse_colour
.r
= ambient
.r
* material_ambient
.r
3278 + diffuse
.r
* material_diffuse
.r
+ material_emissive
.r
;
3279 diffuse_colour
.g
= ambient
.g
* material_ambient
.g
3280 + diffuse
.g
* material_diffuse
.g
+ material_emissive
.g
;
3281 diffuse_colour
.b
= ambient
.b
* material_ambient
.b
3282 + diffuse
.b
* material_diffuse
.b
+ material_emissive
.b
;
3283 diffuse_colour
.a
= material_diffuse
.a
;
3287 diffuse_colour
= material_diffuse
;
3289 wined3d_color_clamp(&diffuse_colour
, &diffuse_colour
, 0.0f
, 1.0f
);
3290 *((DWORD
*)dest_ptr
) = wined3d_format_convert_from_float(output_colour_format
, &diffuse_colour
);
3291 dest_ptr
+= sizeof(DWORD
);
3294 if (dst_fvf
& WINED3DFVF_SPECULAR
)
3296 struct wined3d_color material_specular
, specular_colour
;
3298 wined3d_colour_from_mcs(&material_specular
, specular_source
,
3299 material_specular_state_colour
, i
, stream_info
);
3303 specular_colour
.r
= specular
.r
* material_specular
.r
;
3304 specular_colour
.g
= specular
.g
* material_specular
.g
;
3305 specular_colour
.b
= specular
.b
* material_specular
.b
;
3306 specular_colour
.a
= ls
.legacy_lighting
? 0.0f
: material_specular
.a
;
3310 specular_colour
= material_specular
;
3312 update_fog_factor(&specular_colour
.a
, &ls
);
3313 wined3d_color_clamp(&specular_colour
, &specular_colour
, 0.0f
, 1.0f
);
3314 *((DWORD
*)dest_ptr
) = wined3d_format_convert_from_float(output_colour_format
, &specular_colour
);
3315 dest_ptr
+= sizeof(DWORD
);
3318 for (tex_index
= 0; tex_index
< texture_count
; ++tex_index
)
3320 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_TEXCOORD0
+ tex_index
];
3321 const float *tex_coord
= (const float *)(element
->data
.addr
+ i
* element
->stride
);
3322 if (!(stream_info
->use_map
& (1u << (WINED3D_FFP_TEXCOORD0
+ tex_index
))))
3324 ERR("No source texture, but destination requests one\n");
3325 dest_ptr
+= GET_TEXCOORD_SIZE_FROM_FVF(dst_fvf
, tex_index
) * sizeof(float);
3329 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(dst_fvf
, tex_index
) * sizeof(float));
3334 wined3d_resource_unmap(&dest
->resource
, 0);
3338 #undef copy_and_next
3340 HRESULT CDECL
wined3d_device_process_vertices(struct wined3d_device
*device
,
3341 UINT src_start_idx
, UINT dst_idx
, UINT vertex_count
, struct wined3d_buffer
*dst_buffer
,
3342 const struct wined3d_vertex_declaration
*declaration
, DWORD flags
, DWORD dst_fvf
)
3344 struct wined3d_state
*state
= &device
->state
;
3345 struct wined3d_stream_info stream_info
;
3346 struct wined3d_resource
*resource
;
3347 struct wined3d_box box
= {0};
3348 struct wined3d_shader
*vs
;
3353 TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, "
3354 "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n",
3355 device
, src_start_idx
, dst_idx
, vertex_count
,
3356 dst_buffer
, declaration
, flags
, dst_fvf
);
3359 FIXME("Output vertex declaration not implemented yet.\n");
3361 vs
= state
->shader
[WINED3D_SHADER_TYPE_VERTEX
];
3362 state
->shader
[WINED3D_SHADER_TYPE_VERTEX
] = NULL
;
3363 wined3d_stream_info_from_declaration(&stream_info
, state
, &device
->adapter
->d3d_info
);
3364 state
->shader
[WINED3D_SHADER_TYPE_VERTEX
] = vs
;
3366 /* We can't convert FROM a VBO, and vertex buffers used to source into
3367 * process_vertices() are unlikely to ever be used for drawing. Release
3368 * VBOs in those buffers and fix up the stream_info structure.
3370 * Also apply the start index. */
3371 for (i
= 0, map
= stream_info
.use_map
; map
; map
>>= 1, ++i
)
3373 struct wined3d_stream_info_element
*e
;
3374 struct wined3d_map_desc map_desc
;
3379 e
= &stream_info
.elements
[i
];
3380 resource
= &state
->streams
[e
->stream_idx
].buffer
->resource
;
3381 box
.left
= src_start_idx
* e
->stride
;
3382 box
.right
= box
.left
+ vertex_count
* e
->stride
;
3383 if (FAILED(wined3d_resource_map(resource
, 0, &map_desc
, &box
, WINED3D_MAP_READ
)))
3385 ERR("Failed to map resource.\n");
3386 for (j
= 0, map
= stream_info
.use_map
; map
&& j
< i
; map
>>= 1, ++j
)
3391 e
= &stream_info
.elements
[j
];
3392 resource
= &state
->streams
[e
->stream_idx
].buffer
->resource
;
3393 if (FAILED(wined3d_resource_unmap(resource
, 0)))
3394 ERR("Failed to unmap resource.\n");
3396 return WINED3DERR_INVALIDCALL
;
3398 e
->data
.buffer_object
= 0;
3399 e
->data
.addr
+= (ULONG_PTR
)map_desc
.data
;
3402 hr
= process_vertices_strided(device
, dst_idx
, vertex_count
,
3403 &stream_info
, dst_buffer
, flags
, dst_fvf
);
3405 for (i
= 0, map
= stream_info
.use_map
; map
; map
>>= 1, ++i
)
3410 resource
= &state
->streams
[stream_info
.elements
[i
].stream_idx
].buffer
->resource
;
3411 if (FAILED(wined3d_resource_unmap(resource
, 0)))
3412 ERR("Failed to unmap resource.\n");
3418 static void wined3d_device_set_texture_stage_state(struct wined3d_device
*device
,
3419 UINT stage
, enum wined3d_texture_stage_state state
, DWORD value
)
3421 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3423 TRACE("device %p, stage %u, state %s, value %#x.\n",
3424 device
, stage
, debug_d3dtexturestate(state
), value
);
3426 if (stage
>= d3d_info
->limits
.ffp_blend_stages
)
3428 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
3429 stage
, d3d_info
->limits
.ffp_blend_stages
- 1);
3433 if (value
== device
->state
.texture_states
[stage
][state
])
3435 TRACE("Application is setting the old value over, nothing to do.\n");
3439 device
->state
.texture_states
[stage
][state
] = value
;
3441 wined3d_cs_emit_set_texture_state(device
->cs
, stage
, state
, value
);
3444 static void wined3d_device_set_texture(struct wined3d_device
*device
,
3445 UINT stage
, struct wined3d_texture
*texture
)
3447 struct wined3d_texture
*prev
;
3449 TRACE("device %p, stage %u, texture %p.\n", device
, stage
, texture
);
3451 if (stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& stage
<= WINED3DVERTEXTEXTURESAMPLER3
)
3452 stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- WINED3D_MAX_FRAGMENT_SAMPLERS
);
3454 /* Windows accepts overflowing this array... we do not. */
3455 if (stage
>= ARRAY_SIZE(device
->state
.textures
))
3457 WARN("Ignoring invalid stage %u.\n", stage
);
3461 prev
= device
->state
.textures
[stage
];
3462 TRACE("Previous texture %p.\n", prev
);
3464 if (texture
== prev
)
3466 TRACE("App is setting the same texture again, nothing to do.\n");
3470 TRACE("Setting new texture to %p.\n", texture
);
3471 device
->state
.textures
[stage
] = texture
;
3474 wined3d_texture_incref(texture
);
3475 wined3d_cs_emit_set_texture(device
->cs
, stage
, texture
);
3477 wined3d_texture_decref(prev
);
3482 void CDECL
wined3d_device_apply_stateblock(struct wined3d_device
*device
,
3483 struct wined3d_stateblock
*stateblock
)
3485 const struct wined3d_stateblock_state
*state
= &stateblock
->stateblock_state
;
3486 const struct wined3d_saved_states
*changed
= &stateblock
->changed
;
3487 const unsigned int word_bit_count
= sizeof(DWORD
) * CHAR_BIT
;
3488 BOOL set_blend_state
, set_rasterizer_state
= FALSE
;
3489 struct wined3d_blend_state
*blend_state
;
3490 unsigned int i
, j
, start
, idx
;
3491 struct wined3d_color colour
;
3492 struct wined3d_range range
;
3495 TRACE("device %p, stateblock %p.\n", device
, stateblock
);
3497 if (changed
->vertexShader
)
3498 wined3d_device_set_vertex_shader(device
, state
->vs
);
3499 if (changed
->pixelShader
)
3500 wined3d_device_set_pixel_shader(device
, state
->ps
);
3502 for (start
= 0; ; start
= range
.offset
+ range
.size
)
3504 if (!wined3d_bitmap_get_range(changed
->vs_consts_f
, WINED3D_MAX_VS_CONSTS_F
, start
, &range
))
3507 wined3d_device_set_vs_consts_f(device
, range
.offset
, range
.size
, &state
->vs_consts_f
[range
.offset
]);
3510 map
= changed
->vertexShaderConstantsI
;
3511 for (start
= 0; ; start
= range
.offset
+ range
.size
)
3513 if (!wined3d_bitmap_get_range(&map
, WINED3D_MAX_CONSTS_I
, start
, &range
))
3516 wined3d_device_set_vs_consts_i(device
, range
.offset
, range
.size
, &state
->vs_consts_i
[range
.offset
]);
3519 map
= changed
->vertexShaderConstantsB
;
3520 for (start
= 0; ; start
= range
.offset
+ range
.size
)
3522 if (!wined3d_bitmap_get_range(&map
, WINED3D_MAX_CONSTS_B
, start
, &range
))
3525 wined3d_device_set_vs_consts_b(device
, range
.offset
, range
.size
, &state
->vs_consts_b
[range
.offset
]);
3528 for (start
= 0; ; start
= range
.offset
+ range
.size
)
3530 if (!wined3d_bitmap_get_range(changed
->ps_consts_f
, WINED3D_MAX_PS_CONSTS_F
, start
, &range
))
3533 wined3d_device_set_ps_consts_f(device
, range
.offset
, range
.size
, &state
->ps_consts_f
[range
.offset
]);
3536 map
= changed
->pixelShaderConstantsI
;
3537 for (start
= 0; ; start
= range
.offset
+ range
.size
)
3539 if (!wined3d_bitmap_get_range(&map
, WINED3D_MAX_CONSTS_I
, start
, &range
))
3542 wined3d_device_set_ps_consts_i(device
, range
.offset
, range
.size
, &state
->ps_consts_i
[range
.offset
]);
3545 map
= changed
->pixelShaderConstantsB
;
3546 for (start
= 0; ; start
= range
.offset
+ range
.size
)
3548 if (!wined3d_bitmap_get_range(&map
, WINED3D_MAX_CONSTS_B
, start
, &range
))
3551 wined3d_device_set_ps_consts_b(device
, range
.offset
, range
.size
, &state
->ps_consts_b
[range
.offset
]);
3554 if (changed
->lights
)
3556 for (i
= 0; i
< ARRAY_SIZE(state
->light_state
->light_map
); ++i
)
3558 const struct wined3d_light_info
*light
;
3560 LIST_FOR_EACH_ENTRY(light
, &state
->light_state
->light_map
[i
], struct wined3d_light_info
, entry
)
3562 wined3d_device_set_light(device
, light
->OriginalIndex
, &light
->OriginalParms
);
3563 wined3d_device_set_light_enable(device
, light
->OriginalIndex
, light
->glIndex
!= -1);
3568 if ((set_blend_state
= changed
->blend_state
3569 || wined3d_bitmap_is_set(changed
->renderState
, WINED3D_RS_ADAPTIVETESS_Y
)))
3571 blend_state
= state
->rs
[WINED3D_RS_ADAPTIVETESS_Y
] == WINED3DFMT_ATOC
3572 ? device
->blend_state_atoc_enabled
: state
->blend_state
;
3574 if (wined3d_bitmap_is_set(changed
->renderState
, WINED3D_RS_BLENDFACTOR
))
3575 wined3d_color_from_d3dcolor(&colour
, stateblock
->stateblock_state
.rs
[WINED3D_RS_BLENDFACTOR
]);
3577 wined3d_device_get_blend_state(device
, &colour
);
3579 wined3d_device_set_blend_state(device
, blend_state
, &colour
);
3582 for (i
= 0; i
< ARRAY_SIZE(changed
->renderState
); ++i
)
3584 map
= changed
->renderState
[i
];
3587 j
= wined3d_bit_scan(&map
);
3588 idx
= i
* word_bit_count
+ j
;
3592 case WINED3D_RS_BLENDFACTOR
:
3593 if (!set_blend_state
)
3595 blend_state
= wined3d_device_get_blend_state(device
, &colour
);
3596 wined3d_color_from_d3dcolor(&colour
, state
->rs
[idx
]);
3597 wined3d_device_set_blend_state(device
, blend_state
, &colour
);
3601 case WINED3D_RS_FILLMODE
:
3602 case WINED3D_RS_CULLMODE
:
3603 case WINED3D_RS_SLOPESCALEDEPTHBIAS
:
3604 set_rasterizer_state
= TRUE
;
3608 wined3d_device_set_render_state(device
, idx
, state
->rs
[idx
]);
3614 if (set_rasterizer_state
)
3616 struct wined3d_rasterizer_state
*rasterizer_state
;
3617 struct wined3d_rasterizer_state_desc desc
;
3618 struct wine_rb_entry
*entry
;
3625 desc
.fill_mode
= state
->rs
[WINED3D_RS_FILLMODE
];
3626 desc
.cull_mode
= state
->rs
[WINED3D_RS_CULLMODE
];
3627 desc
.front_ccw
= FALSE
;
3628 desc
.depth_bias_clamp
= 0.0f
;
3629 bias
.d
= state
->rs
[WINED3D_RS_SLOPESCALEDEPTHBIAS
];
3630 desc
.scale_bias
= bias
.f
;
3631 desc
.depth_clip
= TRUE
;
3633 if ((entry
= wine_rb_get(&device
->rasterizer_states
, &desc
)))
3635 rasterizer_state
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_rasterizer_state
, entry
);
3636 wined3d_device_set_rasterizer_state(device
, rasterizer_state
);
3638 else if (SUCCEEDED(wined3d_rasterizer_state_create(device
, &desc
, NULL
,
3639 &wined3d_null_parent_ops
, &rasterizer_state
)))
3641 wined3d_device_set_rasterizer_state(device
, rasterizer_state
);
3642 if (wine_rb_put(&device
->rasterizer_states
, &desc
, &rasterizer_state
->entry
) == -1)
3644 ERR("Failed to insert rasterizer state.\n");
3645 wined3d_rasterizer_state_decref(rasterizer_state
);
3650 for (i
= 0; i
< ARRAY_SIZE(changed
->textureState
); ++i
)
3652 map
= changed
->textureState
[i
];
3655 j
= wined3d_bit_scan(&map
);
3656 wined3d_device_set_texture_stage_state(device
, i
, j
, state
->texture_states
[i
][j
]);
3660 for (i
= 0; i
< ARRAY_SIZE(changed
->samplerState
); ++i
)
3663 if (stage
>= WINED3D_MAX_FRAGMENT_SAMPLERS
)
3664 stage
+= WINED3DVERTEXTEXTURESAMPLER0
- WINED3D_MAX_FRAGMENT_SAMPLERS
;
3665 map
= changed
->samplerState
[i
];
3668 j
= wined3d_bit_scan(&map
);
3669 wined3d_device_set_sampler_state(device
, stage
, j
, state
->sampler_states
[i
][j
]);
3673 if (changed
->transforms
)
3675 for (i
= 0; i
< ARRAY_SIZE(changed
->transform
); ++i
)
3677 map
= changed
->transform
[i
];
3680 j
= wined3d_bit_scan(&map
);
3681 idx
= i
* word_bit_count
+ j
;
3682 wined3d_device_set_transform(device
, idx
, &state
->transforms
[idx
]);
3687 if (changed
->indices
)
3688 wined3d_device_set_index_buffer(device
, state
->index_buffer
, state
->index_format
, 0);
3689 wined3d_device_set_base_vertex_index(device
, state
->base_vertex_index
);
3690 if (changed
->vertexDecl
)
3691 wined3d_device_set_vertex_declaration(device
, state
->vertex_declaration
);
3692 if (changed
->material
)
3693 wined3d_device_set_material(device
, &state
->material
);
3694 if (changed
->viewport
)
3695 wined3d_device_set_viewports(device
, 1, &state
->viewport
);
3696 if (changed
->scissorRect
)
3697 wined3d_device_set_scissor_rects(device
, 1, &state
->scissor_rect
);
3699 map
= changed
->streamSource
;
3702 i
= wined3d_bit_scan(&map
);
3703 wined3d_device_set_stream_source(device
, i
, state
->streams
[i
].buffer
,
3704 state
->streams
[i
].offset
, state
->streams
[i
].stride
);
3706 map
= changed
->streamFreq
;
3709 i
= wined3d_bit_scan(&map
);
3710 wined3d_device_set_stream_source_freq(device
, i
,
3711 state
->streams
[i
].frequency
| state
->streams
[i
].flags
);
3714 map
= changed
->textures
;
3717 i
= wined3d_bit_scan(&map
);
3719 if (stage
>= WINED3D_MAX_FRAGMENT_SAMPLERS
)
3720 stage
+= WINED3DVERTEXTEXTURESAMPLER0
- WINED3D_MAX_FRAGMENT_SAMPLERS
;
3721 wined3d_device_set_texture(device
, stage
, state
->textures
[i
]);
3724 map
= changed
->clipplane
;
3727 i
= wined3d_bit_scan(&map
);
3728 wined3d_device_set_clip_plane(device
, i
, &state
->clip_planes
[i
]);
3731 memset(&stateblock
->changed
, 0, sizeof(stateblock
->changed
));
3733 TRACE("Applied stateblock %p.\n", stateblock
);
3736 HRESULT CDECL
wined3d_device_get_device_caps(const struct wined3d_device
*device
, struct wined3d_caps
*caps
)
3738 TRACE("device %p, caps %p.\n", device
, caps
);
3740 return wined3d_get_device_caps(device
->wined3d
, device
->adapter
->ordinal
,
3741 device
->create_parms
.device_type
, caps
);
3744 HRESULT CDECL
wined3d_device_get_display_mode(const struct wined3d_device
*device
, UINT swapchain_idx
,
3745 struct wined3d_display_mode
*mode
, enum wined3d_display_rotation
*rotation
)
3747 struct wined3d_swapchain
*swapchain
;
3749 TRACE("device %p, swapchain_idx %u, mode %p, rotation %p.\n",
3750 device
, swapchain_idx
, mode
, rotation
);
3752 if (!(swapchain
= wined3d_device_get_swapchain(device
, swapchain_idx
)))
3753 return WINED3DERR_INVALIDCALL
;
3755 return wined3d_swapchain_get_display_mode(swapchain
, mode
, rotation
);
3758 HRESULT CDECL
wined3d_device_begin_scene(struct wined3d_device
*device
)
3760 /* At the moment we have no need for any functionality at the beginning
3762 TRACE("device %p.\n", device
);
3764 if (device
->inScene
)
3766 WARN("Already in scene, returning WINED3DERR_INVALIDCALL.\n");
3767 return WINED3DERR_INVALIDCALL
;
3769 device
->inScene
= TRUE
;
3773 HRESULT CDECL
wined3d_device_end_scene(struct wined3d_device
*device
)
3775 TRACE("device %p.\n", device
);
3777 if (!device
->inScene
)
3779 WARN("Not in scene, returning WINED3DERR_INVALIDCALL.\n");
3780 return WINED3DERR_INVALIDCALL
;
3783 device
->inScene
= FALSE
;
3787 HRESULT CDECL
wined3d_device_clear(struct wined3d_device
*device
, DWORD rect_count
,
3788 const RECT
*rects
, DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
3790 TRACE("device %p, rect_count %u, rects %p, flags %#x, color %s, depth %.8e, stencil %u.\n",
3791 device
, rect_count
, rects
, flags
, debug_color(color
), depth
, stencil
);
3793 if (!rect_count
&& rects
)
3795 WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects
);
3799 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
3801 struct wined3d_rendertarget_view
*ds
= device
->fb
.depth_stencil
;
3804 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
3805 /* TODO: What about depth stencil buffers without stencil bits? */
3806 return WINED3DERR_INVALIDCALL
;
3808 else if (flags
& WINED3DCLEAR_TARGET
)
3810 if (ds
->width
< device
->fb
.render_targets
[0]->width
3811 || ds
->height
< device
->fb
.render_targets
[0]->height
)
3813 WARN("Silently ignoring depth and target clear with mismatching sizes\n");
3819 wined3d_cs_emit_clear(device
->cs
, rect_count
, rects
, flags
, color
, depth
, stencil
);
3824 void CDECL
wined3d_device_set_predication(struct wined3d_device
*device
,
3825 struct wined3d_query
*predicate
, BOOL value
)
3827 struct wined3d_query
*prev
;
3829 TRACE("device %p, predicate %p, value %#x.\n", device
, predicate
, value
);
3831 prev
= device
->state
.predicate
;
3834 FIXME("Predicated rendering not implemented.\n");
3835 wined3d_query_incref(predicate
);
3837 device
->state
.predicate
= predicate
;
3838 device
->state
.predicate_value
= value
;
3839 wined3d_cs_emit_set_predication(device
->cs
, predicate
, value
);
3841 wined3d_query_decref(prev
);
3844 struct wined3d_query
* CDECL
wined3d_device_get_predication(struct wined3d_device
*device
, BOOL
*value
)
3846 TRACE("device %p, value %p.\n", device
, value
);
3849 *value
= device
->state
.predicate_value
;
3850 return device
->state
.predicate
;
3853 void CDECL
wined3d_device_dispatch_compute(struct wined3d_device
*device
,
3854 unsigned int group_count_x
, unsigned int group_count_y
, unsigned int group_count_z
)
3856 TRACE("device %p, group_count_x %u, group_count_y %u, group_count_z %u.\n",
3857 device
, group_count_x
, group_count_y
, group_count_z
);
3859 wined3d_cs_emit_dispatch(device
->cs
, group_count_x
, group_count_y
, group_count_z
);
3862 void CDECL
wined3d_device_dispatch_compute_indirect(struct wined3d_device
*device
,
3863 struct wined3d_buffer
*buffer
, unsigned int offset
)
3865 TRACE("device %p, buffer %p, offset %u.\n", device
, buffer
, offset
);
3867 wined3d_cs_emit_dispatch_indirect(device
->cs
, buffer
, offset
);
3870 void CDECL
wined3d_device_set_primitive_type(struct wined3d_device
*device
,
3871 enum wined3d_primitive_type primitive_type
, unsigned int patch_vertex_count
)
3873 TRACE("device %p, primitive_type %s, patch_vertex_count %u.\n",
3874 device
, debug_d3dprimitivetype(primitive_type
), patch_vertex_count
);
3876 device
->state
.gl_primitive_type
= gl_primitive_type_from_d3d(primitive_type
);
3877 device
->state
.gl_patch_vertices
= patch_vertex_count
;
3880 void CDECL
wined3d_device_get_primitive_type(const struct wined3d_device
*device
,
3881 enum wined3d_primitive_type
*primitive_type
, unsigned int *patch_vertex_count
)
3883 TRACE("device %p, primitive_type %p, patch_vertex_count %p.\n",
3884 device
, primitive_type
, patch_vertex_count
);
3886 *primitive_type
= d3d_primitive_type_from_gl(device
->state
.gl_primitive_type
);
3887 if (patch_vertex_count
)
3888 *patch_vertex_count
= device
->state
.gl_patch_vertices
;
3890 TRACE("Returning %s.\n", debug_d3dprimitivetype(*primitive_type
));
3893 HRESULT CDECL
wined3d_device_draw_primitive(struct wined3d_device
*device
, UINT start_vertex
, UINT vertex_count
)
3895 TRACE("device %p, start_vertex %u, vertex_count %u.\n", device
, start_vertex
, vertex_count
);
3897 wined3d_cs_emit_draw(device
->cs
, device
->state
.gl_primitive_type
, device
->state
.gl_patch_vertices
,
3898 0, start_vertex
, vertex_count
, 0, 0, FALSE
);
3903 void CDECL
wined3d_device_draw_primitive_instanced(struct wined3d_device
*device
,
3904 UINT start_vertex
, UINT vertex_count
, UINT start_instance
, UINT instance_count
)
3906 TRACE("device %p, start_vertex %u, vertex_count %u, start_instance %u, instance_count %u.\n",
3907 device
, start_vertex
, vertex_count
, start_instance
, instance_count
);
3909 wined3d_cs_emit_draw(device
->cs
, device
->state
.gl_primitive_type
, device
->state
.gl_patch_vertices
,
3910 0, start_vertex
, vertex_count
, start_instance
, instance_count
, FALSE
);
3913 void CDECL
wined3d_device_draw_primitive_instanced_indirect(struct wined3d_device
*device
,
3914 struct wined3d_buffer
*buffer
, unsigned int offset
)
3916 TRACE("device %p, buffer %p, offset %u.\n", device
, buffer
, offset
);
3918 wined3d_cs_emit_draw_indirect(device
->cs
, device
->state
.gl_primitive_type
, device
->state
.gl_patch_vertices
,
3919 buffer
, offset
, FALSE
);
3922 HRESULT CDECL
wined3d_device_draw_indexed_primitive(struct wined3d_device
*device
, UINT start_idx
, UINT index_count
)
3924 TRACE("device %p, start_idx %u, index_count %u.\n", device
, start_idx
, index_count
);
3926 if (!device
->state
.index_buffer
)
3928 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
3929 * without an index buffer set. (The first time at least...)
3930 * D3D8 simply dies, but I doubt it can do much harm to return
3931 * D3DERR_INVALIDCALL there as well. */
3932 WARN("Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL.\n");
3933 return WINED3DERR_INVALIDCALL
;
3936 wined3d_cs_emit_draw(device
->cs
, device
->state
.gl_primitive_type
, device
->state
.gl_patch_vertices
,
3937 device
->state
.base_vertex_index
, start_idx
, index_count
, 0, 0, TRUE
);
3942 void CDECL
wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device
*device
,
3943 UINT start_idx
, UINT index_count
, UINT start_instance
, UINT instance_count
)
3945 TRACE("device %p, start_idx %u, index_count %u, start_instance %u, instance_count %u.\n",
3946 device
, start_idx
, index_count
, start_instance
, instance_count
);
3948 wined3d_cs_emit_draw(device
->cs
, device
->state
.gl_primitive_type
, device
->state
.gl_patch_vertices
,
3949 device
->state
.base_vertex_index
, start_idx
, index_count
, start_instance
, instance_count
, TRUE
);
3952 void CDECL
wined3d_device_draw_indexed_primitive_instanced_indirect(struct wined3d_device
*device
,
3953 struct wined3d_buffer
*buffer
, unsigned int offset
)
3955 TRACE("device %p, buffer %p, offset %u.\n", device
, buffer
, offset
);
3957 wined3d_cs_emit_draw_indirect(device
->cs
, device
->state
.gl_primitive_type
, device
->state
.gl_patch_vertices
,
3958 buffer
, offset
, TRUE
);
3961 HRESULT CDECL
wined3d_device_update_texture(struct wined3d_device
*device
,
3962 struct wined3d_texture
*src_texture
, struct wined3d_texture
*dst_texture
)
3964 unsigned int src_size
, dst_size
, src_skip_levels
= 0;
3965 unsigned int src_level_count
, dst_level_count
;
3966 const struct wined3d_dirty_regions
*regions
;
3967 unsigned int layer_count
, level_count
, i
, j
;
3968 enum wined3d_resource_type type
;
3969 BOOL entire_texture
= TRUE
;
3970 struct wined3d_box box
;
3972 TRACE("device %p, src_texture %p, dst_texture %p.\n", device
, src_texture
, dst_texture
);
3974 /* Verify that the source and destination textures are non-NULL. */
3975 if (!src_texture
|| !dst_texture
)
3977 WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
3978 return WINED3DERR_INVALIDCALL
;
3981 if (src_texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_GPU
3982 || src_texture
->resource
.usage
& WINED3DUSAGE_SCRATCH
)
3984 WARN("Source resource is GPU accessible or a scratch resource.\n");
3985 return WINED3DERR_INVALIDCALL
;
3987 if (dst_texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_CPU
)
3989 WARN("Destination resource is CPU accessible.\n");
3990 return WINED3DERR_INVALIDCALL
;
3993 /* Verify that the source and destination textures are the same type. */
3994 type
= src_texture
->resource
.type
;
3995 if (dst_texture
->resource
.type
!= type
)
3997 WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
3998 return WINED3DERR_INVALIDCALL
;
4001 layer_count
= src_texture
->layer_count
;
4002 if (layer_count
!= dst_texture
->layer_count
)
4004 WARN("Source and destination have different layer counts.\n");
4005 return WINED3DERR_INVALIDCALL
;
4008 if (src_texture
->resource
.format
!= dst_texture
->resource
.format
)
4010 WARN("Source and destination formats do not match.\n");
4011 return WINED3DERR_INVALIDCALL
;
4014 src_level_count
= src_texture
->level_count
;
4015 dst_level_count
= dst_texture
->level_count
;
4016 level_count
= min(src_level_count
, dst_level_count
);
4018 src_size
= max(src_texture
->resource
.width
, src_texture
->resource
.height
);
4019 src_size
= max(src_size
, src_texture
->resource
.depth
);
4020 dst_size
= max(dst_texture
->resource
.width
, dst_texture
->resource
.height
);
4021 dst_size
= max(dst_size
, dst_texture
->resource
.depth
);
4022 while (src_size
> dst_size
)
4028 if (wined3d_texture_get_level_width(src_texture
, src_skip_levels
) != dst_texture
->resource
.width
4029 || wined3d_texture_get_level_height(src_texture
, src_skip_levels
) != dst_texture
->resource
.height
4030 || wined3d_texture_get_level_depth(src_texture
, src_skip_levels
) != dst_texture
->resource
.depth
)
4032 WARN("Source and destination dimensions do not match.\n");
4033 return WINED3DERR_INVALIDCALL
;
4036 if ((regions
= src_texture
->dirty_regions
))
4038 for (i
= 0; i
< layer_count
&& entire_texture
; ++i
)
4040 if (regions
[i
].box_count
>= WINED3D_MAX_DIRTY_REGION_COUNT
)
4043 entire_texture
= FALSE
;
4048 /* Update every surface level of the texture. */
4051 for (i
= 0; i
< level_count
; ++i
)
4053 wined3d_texture_get_level_box(dst_texture
, i
, &box
);
4054 for (j
= 0; j
< layer_count
; ++j
)
4056 wined3d_cs_emit_blt_sub_resource(device
->cs
,
4057 &dst_texture
->resource
, j
* dst_level_count
+ i
, &box
,
4058 &src_texture
->resource
, j
* src_level_count
+ i
+ src_skip_levels
, &box
,
4059 0, NULL
, WINED3D_TEXF_POINT
);
4065 unsigned int src_level
, box_count
, k
;
4066 const struct wined3d_box
*boxes
;
4067 struct wined3d_box b
;
4069 for (i
= 0; i
< layer_count
; ++i
)
4071 boxes
= regions
[i
].boxes
;
4072 box_count
= regions
[i
].box_count
;
4073 if (regions
[i
].box_count
>= WINED3D_MAX_DIRTY_REGION_COUNT
)
4077 wined3d_texture_get_level_box(dst_texture
, i
, &b
);
4080 for (j
= 0; j
< level_count
; ++j
)
4082 src_level
= j
+ src_skip_levels
;
4084 /* TODO: We could pass an array of boxes here to avoid
4085 * multiple context acquisitions for the same resource. */
4086 for (k
= 0; k
< box_count
; ++k
)
4091 box
.left
>>= src_level
;
4092 box
.top
>>= src_level
;
4093 box
.right
= min((box
.right
+ (1u << src_level
) - 1) >> src_level
,
4094 wined3d_texture_get_level_width(src_texture
, src_level
));
4095 box
.bottom
= min((box
.bottom
+ (1u << src_level
) - 1) >> src_level
,
4096 wined3d_texture_get_level_height(src_texture
, src_level
));
4097 box
.front
>>= src_level
;
4098 box
.back
= min((box
.back
+ (1u << src_level
) - 1) >> src_level
,
4099 wined3d_texture_get_level_depth(src_texture
, src_level
));
4102 wined3d_cs_emit_blt_sub_resource(device
->cs
,
4103 &dst_texture
->resource
, i
* dst_level_count
+ j
, &box
,
4104 &src_texture
->resource
, i
* src_level_count
+ src_level
, &box
,
4105 0, NULL
, WINED3D_TEXF_POINT
);
4111 wined3d_texture_clear_dirty_regions(src_texture
);
4116 HRESULT CDECL
wined3d_device_validate_device(const struct wined3d_device
*device
, DWORD
*num_passes
)
4118 const struct wined3d_state
*state
= &device
->state
;
4119 struct wined3d_texture
*texture
;
4122 TRACE("device %p, num_passes %p.\n", device
, num_passes
);
4124 for (i
= 0; i
< WINED3D_MAX_COMBINED_SAMPLERS
; ++i
)
4126 if (state
->sampler_states
[i
][WINED3D_SAMP_MIN_FILTER
] == WINED3D_TEXF_NONE
)
4128 WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
4129 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
4131 if (state
->sampler_states
[i
][WINED3D_SAMP_MAG_FILTER
] == WINED3D_TEXF_NONE
)
4133 WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
4134 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
4137 texture
= state
->textures
[i
];
4138 if (!texture
|| texture
->resource
.format_flags
& WINED3DFMT_FLAG_FILTERING
) continue;
4140 if (state
->sampler_states
[i
][WINED3D_SAMP_MAG_FILTER
] != WINED3D_TEXF_POINT
)
4142 WARN("Non-filterable texture and mag filter enabled on sampler %u, returning E_FAIL\n", i
);
4145 if (state
->sampler_states
[i
][WINED3D_SAMP_MIN_FILTER
] != WINED3D_TEXF_POINT
)
4147 WARN("Non-filterable texture and min filter enabled on sampler %u, returning E_FAIL\n", i
);
4150 if (state
->sampler_states
[i
][WINED3D_SAMP_MIP_FILTER
] != WINED3D_TEXF_NONE
4151 && state
->sampler_states
[i
][WINED3D_SAMP_MIP_FILTER
] != WINED3D_TEXF_POINT
)
4153 WARN("Non-filterable texture and mip filter enabled on sampler %u, returning E_FAIL\n", i
);
4158 if (state
->render_states
[WINED3D_RS_ZENABLE
] || state
->render_states
[WINED3D_RS_ZWRITEENABLE
]
4159 || state
->render_states
[WINED3D_RS_STENCILENABLE
])
4161 struct wined3d_rendertarget_view
*rt
= device
->fb
.render_targets
[0];
4162 struct wined3d_rendertarget_view
*ds
= device
->fb
.depth_stencil
;
4164 if (ds
&& rt
&& (ds
->width
< rt
->width
|| ds
->height
< rt
->height
))
4166 WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
4167 return WINED3DERR_CONFLICTINGRENDERSTATE
;
4171 /* return a sensible default */
4174 TRACE("returning D3D_OK\n");
4178 void CDECL
wined3d_device_set_software_vertex_processing(struct wined3d_device
*device
, BOOL software
)
4182 TRACE("device %p, software %#x.\n", device
, software
);
4186 FIXME("device %p, software %#x stub!\n", device
, software
);
4190 device
->softwareVertexProcessing
= software
;
4193 BOOL CDECL
wined3d_device_get_software_vertex_processing(const struct wined3d_device
*device
)
4197 TRACE("device %p.\n", device
);
4201 TRACE("device %p stub!\n", device
);
4205 return device
->softwareVertexProcessing
;
4208 HRESULT CDECL
wined3d_device_get_raster_status(const struct wined3d_device
*device
,
4209 UINT swapchain_idx
, struct wined3d_raster_status
*raster_status
)
4211 struct wined3d_swapchain
*swapchain
;
4213 TRACE("device %p, swapchain_idx %u, raster_status %p.\n",
4214 device
, swapchain_idx
, raster_status
);
4216 if (!(swapchain
= wined3d_device_get_swapchain(device
, swapchain_idx
)))
4217 return WINED3DERR_INVALIDCALL
;
4219 return wined3d_swapchain_get_raster_status(swapchain
, raster_status
);
4222 HRESULT CDECL
wined3d_device_set_npatch_mode(struct wined3d_device
*device
, float segments
)
4226 TRACE("device %p, segments %.8e.\n", device
, segments
);
4228 if (segments
!= 0.0f
)
4232 FIXME("device %p, segments %.8e stub!\n", device
, segments
);
4240 float CDECL
wined3d_device_get_npatch_mode(const struct wined3d_device
*device
)
4244 TRACE("device %p.\n", device
);
4248 FIXME("device %p stub!\n", device
);
4255 void CDECL
wined3d_device_copy_uav_counter(struct wined3d_device
*device
,
4256 struct wined3d_buffer
*dst_buffer
, unsigned int offset
, struct wined3d_unordered_access_view
*uav
)
4258 TRACE("device %p, dst_buffer %p, offset %u, uav %p.\n",
4259 device
, dst_buffer
, offset
, uav
);
4261 wined3d_cs_emit_copy_uav_counter(device
->cs
, dst_buffer
, offset
, uav
);
4264 void CDECL
wined3d_device_copy_resource(struct wined3d_device
*device
,
4265 struct wined3d_resource
*dst_resource
, struct wined3d_resource
*src_resource
)
4267 struct wined3d_texture
*dst_texture
, *src_texture
;
4268 struct wined3d_box box
;
4271 TRACE("device %p, dst_resource %p, src_resource %p.\n", device
, dst_resource
, src_resource
);
4273 if (src_resource
== dst_resource
)
4275 WARN("Source and destination are the same resource.\n");
4279 if (src_resource
->type
!= dst_resource
->type
)
4281 WARN("Resource types (%s / %s) don't match.\n",
4282 debug_d3dresourcetype(dst_resource
->type
),
4283 debug_d3dresourcetype(src_resource
->type
));
4287 if (src_resource
->width
!= dst_resource
->width
4288 || src_resource
->height
!= dst_resource
->height
4289 || src_resource
->depth
!= dst_resource
->depth
)
4291 WARN("Resource dimensions (%ux%ux%u / %ux%ux%u) don't match.\n",
4292 dst_resource
->width
, dst_resource
->height
, dst_resource
->depth
,
4293 src_resource
->width
, src_resource
->height
, src_resource
->depth
);
4297 if (src_resource
->format
->typeless_id
!= dst_resource
->format
->typeless_id
4298 || (!src_resource
->format
->typeless_id
&& src_resource
->format
->id
!= dst_resource
->format
->id
))
4300 WARN("Resource formats %s and %s are incompatible.\n",
4301 debug_d3dformat(dst_resource
->format
->id
),
4302 debug_d3dformat(src_resource
->format
->id
));
4306 if (dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
4308 wined3d_box_set(&box
, 0, 0, src_resource
->size
, 1, 0, 1);
4309 wined3d_cs_emit_blt_sub_resource(device
->cs
, dst_resource
, 0, &box
,
4310 src_resource
, 0, &box
, WINED3D_BLT_RAW
, NULL
, WINED3D_TEXF_POINT
);
4314 dst_texture
= texture_from_resource(dst_resource
);
4315 src_texture
= texture_from_resource(src_resource
);
4317 if (src_texture
->layer_count
!= dst_texture
->layer_count
4318 || src_texture
->level_count
!= dst_texture
->level_count
)
4320 WARN("Subresource layouts (%ux%u / %ux%u) don't match.\n",
4321 dst_texture
->layer_count
, dst_texture
->level_count
,
4322 src_texture
->layer_count
, src_texture
->level_count
);
4326 for (i
= 0; i
< dst_texture
->level_count
; ++i
)
4328 wined3d_texture_get_level_box(dst_texture
, i
, &box
);
4329 for (j
= 0; j
< dst_texture
->layer_count
; ++j
)
4331 unsigned int idx
= j
* dst_texture
->level_count
+ i
;
4333 wined3d_cs_emit_blt_sub_resource(device
->cs
, dst_resource
, idx
, &box
,
4334 src_resource
, idx
, &box
, WINED3D_BLT_RAW
, NULL
, WINED3D_TEXF_POINT
);
4339 HRESULT CDECL
wined3d_device_copy_sub_resource_region(struct wined3d_device
*device
,
4340 struct wined3d_resource
*dst_resource
, unsigned int dst_sub_resource_idx
, unsigned int dst_x
,
4341 unsigned int dst_y
, unsigned int dst_z
, struct wined3d_resource
*src_resource
,
4342 unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
, unsigned int flags
)
4344 struct wined3d_box dst_box
, b
;
4346 TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
4347 "src_resource %p, src_sub_resource_idx %u, src_box %s, flags %#x.\n",
4348 device
, dst_resource
, dst_sub_resource_idx
, dst_x
, dst_y
, dst_z
,
4349 src_resource
, src_sub_resource_idx
, debug_box(src_box
), flags
);
4352 FIXME("Ignoring flags %#x.\n", flags
);
4354 if (src_resource
== dst_resource
&& src_sub_resource_idx
== dst_sub_resource_idx
)
4356 WARN("Source and destination are the same sub-resource.\n");
4357 return WINED3DERR_INVALIDCALL
;
4360 if (src_resource
->format
->typeless_id
!= dst_resource
->format
->typeless_id
4361 || (!src_resource
->format
->typeless_id
&& src_resource
->format
->id
!= dst_resource
->format
->id
))
4363 WARN("Resource formats %s and %s are incompatible.\n",
4364 debug_d3dformat(dst_resource
->format
->id
),
4365 debug_d3dformat(src_resource
->format
->id
));
4366 return WINED3DERR_INVALIDCALL
;
4369 if (dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
4371 if (src_resource
->type
!= WINED3D_RTYPE_BUFFER
)
4373 WARN("Resource types (%s / %s) don't match.\n",
4374 debug_d3dresourcetype(dst_resource
->type
),
4375 debug_d3dresourcetype(src_resource
->type
));
4376 return WINED3DERR_INVALIDCALL
;
4379 if (dst_sub_resource_idx
)
4381 WARN("Invalid dst_sub_resource_idx %u.\n", dst_sub_resource_idx
);
4382 return WINED3DERR_INVALIDCALL
;
4385 if (src_sub_resource_idx
)
4387 WARN("Invalid src_sub_resource_idx %u.\n", src_sub_resource_idx
);
4388 return WINED3DERR_INVALIDCALL
;
4395 dst_w
= dst_resource
->size
- dst_x
;
4396 wined3d_box_set(&b
, 0, 0, min(src_resource
->size
, dst_w
), 1, 0, 1);
4399 else if ((src_box
->left
>= src_box
->right
4400 || src_box
->top
>= src_box
->bottom
4401 || src_box
->front
>= src_box
->back
))
4403 WARN("Invalid box %s specified.\n", debug_box(src_box
));
4404 return WINED3DERR_INVALIDCALL
;
4407 if (src_box
->right
> src_resource
->size
|| dst_x
>= dst_resource
->size
4408 || src_box
->right
- src_box
->left
> dst_resource
->size
- dst_x
)
4410 WARN("Invalid range specified, dst_offset %u, src_offset %u, size %u.\n",
4411 dst_x
, src_box
->left
, src_box
->right
- src_box
->left
);
4412 return WINED3DERR_INVALIDCALL
;
4415 wined3d_box_set(&dst_box
, dst_x
, 0, dst_x
+ (src_box
->right
- src_box
->left
), 1, 0, 1);
4419 struct wined3d_texture
*dst_texture
= texture_from_resource(dst_resource
);
4420 struct wined3d_texture
*src_texture
= texture_from_resource(src_resource
);
4421 unsigned int src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4423 if (dst_sub_resource_idx
>= dst_texture
->level_count
* dst_texture
->layer_count
)
4425 WARN("Invalid destination sub-resource %u.\n", dst_sub_resource_idx
);
4426 return WINED3DERR_INVALIDCALL
;
4429 if (src_sub_resource_idx
>= src_texture
->level_count
* src_texture
->layer_count
)
4431 WARN("Invalid source sub-resource %u.\n", src_sub_resource_idx
);
4432 return WINED3DERR_INVALIDCALL
;
4435 if (dst_texture
->sub_resources
[dst_sub_resource_idx
].map_count
)
4437 WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx
);
4438 return WINED3DERR_INVALIDCALL
;
4441 if (src_texture
->sub_resources
[src_sub_resource_idx
].map_count
)
4443 WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx
);
4444 return WINED3DERR_INVALIDCALL
;
4449 unsigned int src_w
, src_h
, src_d
, dst_w
, dst_h
, dst_d
, dst_level
;
4451 src_w
= wined3d_texture_get_level_width(src_texture
, src_level
);
4452 src_h
= wined3d_texture_get_level_height(src_texture
, src_level
);
4453 src_d
= wined3d_texture_get_level_depth(src_texture
, src_level
);
4455 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4456 dst_w
= wined3d_texture_get_level_width(dst_texture
, dst_level
) - dst_x
;
4457 dst_h
= wined3d_texture_get_level_height(dst_texture
, dst_level
) - dst_y
;
4458 dst_d
= wined3d_texture_get_level_depth(dst_texture
, dst_level
) - dst_z
;
4460 wined3d_box_set(&b
, 0, 0, min(src_w
, dst_w
), min(src_h
, dst_h
), 0, min(src_d
, dst_d
));
4463 else if (FAILED(wined3d_texture_check_box_dimensions(src_texture
, src_level
, src_box
)))
4465 WARN("Invalid source box %s.\n", debug_box(src_box
));
4466 return WINED3DERR_INVALIDCALL
;
4469 wined3d_box_set(&dst_box
, dst_x
, dst_y
, dst_x
+ (src_box
->right
- src_box
->left
),
4470 dst_y
+ (src_box
->bottom
- src_box
->top
), dst_z
, dst_z
+ (src_box
->back
- src_box
->front
));
4471 if (FAILED(wined3d_texture_check_box_dimensions(dst_texture
,
4472 dst_sub_resource_idx
% dst_texture
->level_count
, &dst_box
)))
4474 WARN("Invalid destination box %s.\n", debug_box(&dst_box
));
4475 return WINED3DERR_INVALIDCALL
;
4479 wined3d_cs_emit_blt_sub_resource(device
->cs
, dst_resource
, dst_sub_resource_idx
, &dst_box
,
4480 src_resource
, src_sub_resource_idx
, src_box
, WINED3D_BLT_RAW
, NULL
, WINED3D_TEXF_POINT
);
4485 void CDECL
wined3d_device_update_sub_resource(struct wined3d_device
*device
, struct wined3d_resource
*resource
,
4486 unsigned int sub_resource_idx
, const struct wined3d_box
*box
, const void *data
, unsigned int row_pitch
,
4487 unsigned int depth_pitch
, unsigned int flags
)
4489 unsigned int width
, height
, depth
;
4490 struct wined3d_box b
;
4492 TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u, "
4494 device
, resource
, sub_resource_idx
, debug_box(box
), data
, row_pitch
, depth_pitch
, flags
);
4497 FIXME("Ignoring flags %#x.\n", flags
);
4499 if (!(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
4501 WARN("Resource %p is not GPU accessible.\n", resource
);
4505 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
4507 if (sub_resource_idx
> 0)
4509 WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx
);
4513 width
= resource
->size
;
4519 struct wined3d_texture
*texture
= texture_from_resource(resource
);
4522 if (sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4524 WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx
);
4528 level
= sub_resource_idx
% texture
->level_count
;
4529 width
= wined3d_texture_get_level_width(texture
, level
);
4530 height
= wined3d_texture_get_level_height(texture
, level
);
4531 depth
= wined3d_texture_get_level_depth(texture
, level
);
4536 wined3d_box_set(&b
, 0, 0, width
, height
, 0, depth
);
4539 else if (box
->left
>= box
->right
|| box
->right
> width
4540 || box
->top
>= box
->bottom
|| box
->bottom
> height
4541 || box
->front
>= box
->back
|| box
->back
> depth
)
4543 WARN("Invalid box %s specified.\n", debug_box(box
));
4547 wined3d_resource_wait_idle(resource
);
4549 wined3d_cs_emit_update_sub_resource(device
->cs
, resource
, sub_resource_idx
, box
, data
, row_pitch
, depth_pitch
);
4552 void CDECL
wined3d_device_resolve_sub_resource(struct wined3d_device
*device
,
4553 struct wined3d_resource
*dst_resource
, unsigned int dst_sub_resource_idx
,
4554 struct wined3d_resource
*src_resource
, unsigned int src_sub_resource_idx
,
4555 enum wined3d_format_id format_id
)
4557 struct wined3d_texture
*dst_texture
, *src_texture
;
4558 unsigned int dst_level
, src_level
;
4559 RECT dst_rect
, src_rect
;
4561 TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, "
4562 "src_resource %p, src_sub_resource_idx %u, format %s.\n",
4563 device
, dst_resource
, dst_sub_resource_idx
,
4564 src_resource
, src_sub_resource_idx
, debug_d3dformat(format_id
));
4566 if (wined3d_format_is_typeless(dst_resource
->format
)
4567 || wined3d_format_is_typeless(src_resource
->format
))
4569 FIXME("Multisample resolve is not fully supported for typeless formats "
4570 "(dst_format %s, src_format %s, format %s).\n",
4571 debug_d3dformat(dst_resource
->format
->id
), debug_d3dformat(src_resource
->format
->id
),
4572 debug_d3dformat(format_id
));
4574 if (dst_resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
4576 WARN("Invalid destination resource type %s.\n", debug_d3dresourcetype(dst_resource
->type
));
4579 if (src_resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
4581 WARN("Invalid source resource type %s.\n", debug_d3dresourcetype(src_resource
->type
));
4585 dst_texture
= texture_from_resource(dst_resource
);
4586 src_texture
= texture_from_resource(src_resource
);
4588 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4589 SetRect(&dst_rect
, 0, 0, wined3d_texture_get_level_width(dst_texture
, dst_level
),
4590 wined3d_texture_get_level_height(dst_texture
, dst_level
));
4591 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4592 SetRect(&src_rect
, 0, 0, wined3d_texture_get_level_width(src_texture
, src_level
),
4593 wined3d_texture_get_level_height(src_texture
, src_level
));
4594 wined3d_texture_blt(dst_texture
, dst_sub_resource_idx
, &dst_rect
,
4595 src_texture
, src_sub_resource_idx
, &src_rect
, 0, NULL
, WINED3D_TEXF_POINT
);
4598 HRESULT CDECL
wined3d_device_clear_rendertarget_view(struct wined3d_device
*device
,
4599 struct wined3d_rendertarget_view
*view
, const RECT
*rect
, DWORD flags
,
4600 const struct wined3d_color
*color
, float depth
, DWORD stencil
)
4602 struct wined3d_resource
*resource
;
4605 TRACE("device %p, view %p, rect %s, flags %#x, color %s, depth %.8e, stencil %u.\n",
4606 device
, view
, wine_dbgstr_rect(rect
), flags
, debug_color(color
), depth
, stencil
);
4611 resource
= view
->resource
;
4612 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
4614 FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource
->type
));
4615 return WINED3DERR_INVALIDCALL
;
4618 if (view
->layer_count
!= max(1, resource
->depth
>> view
->desc
.u
.texture
.level_idx
))
4620 FIXME("Layered clears not implemented.\n");
4621 return WINED3DERR_INVALIDCALL
;
4626 SetRect(&r
, 0, 0, view
->width
, view
->height
);
4631 struct wined3d_box b
= {rect
->left
, rect
->top
, rect
->right
, rect
->bottom
, 0, 1};
4632 struct wined3d_texture
*texture
= texture_from_resource(view
->resource
);
4635 if (FAILED(hr
= wined3d_texture_check_box_dimensions(texture
,
4636 view
->sub_resource_idx
% texture
->level_count
, &b
)))
4640 wined3d_cs_emit_clear_rendertarget_view(device
->cs
, view
, rect
, flags
, color
, depth
, stencil
);
4645 void CDECL
wined3d_device_clear_unordered_access_view_uint(struct wined3d_device
*device
,
4646 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
)
4648 TRACE("device %p, view %p, clear_value %s.\n", device
, view
, debug_uvec4(clear_value
));
4650 wined3d_cs_emit_clear_unordered_access_view_uint(device
->cs
, view
, clear_value
);
4653 struct wined3d_rendertarget_view
* CDECL
wined3d_device_get_rendertarget_view(const struct wined3d_device
*device
,
4654 unsigned int view_idx
)
4656 unsigned int max_rt_count
;
4658 TRACE("device %p, view_idx %u.\n", device
, view_idx
);
4660 max_rt_count
= device
->adapter
->d3d_info
.limits
.max_rt_count
;
4661 if (view_idx
>= max_rt_count
)
4663 WARN("Only %u render targets are supported.\n", max_rt_count
);
4667 return device
->fb
.render_targets
[view_idx
];
4670 struct wined3d_rendertarget_view
* CDECL
wined3d_device_get_depth_stencil_view(const struct wined3d_device
*device
)
4672 TRACE("device %p.\n", device
);
4674 return device
->fb
.depth_stencil
;
4677 static void wined3d_unbind_srv_for_rtv(struct wined3d_device
*device
,
4678 const struct wined3d_rendertarget_view
*view
, BOOL dsv
)
4680 if (view
&& view
->resource
->srv_bind_count_device
)
4682 const struct wined3d_resource
*resource
= view
->resource
;
4683 const struct wined3d_shader_resource_view
*srv
;
4686 WARN("Application sets bound resource as render target.\n");
4688 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
4689 for (j
= 0; j
< MAX_SHADER_RESOURCE_VIEWS
; ++j
)
4690 if ((srv
= device
->state
.shader_resource_view
[i
][j
]) && srv
->resource
== resource
4691 && (!dsv
|| wined3d_dsv_srv_conflict(view
, srv
->format
)))
4692 wined3d_device_set_shader_resource_view(device
, i
, j
, NULL
);
4696 HRESULT CDECL
wined3d_device_set_rendertarget_view(struct wined3d_device
*device
,
4697 unsigned int view_idx
, struct wined3d_rendertarget_view
*view
, BOOL set_viewport
)
4699 struct wined3d_rendertarget_view
*prev
;
4700 unsigned int max_rt_count
;
4702 TRACE("device %p, view_idx %u, view %p, set_viewport %#x.\n",
4703 device
, view_idx
, view
, set_viewport
);
4705 max_rt_count
= device
->adapter
->d3d_info
.limits
.max_rt_count
;
4706 if (view_idx
>= max_rt_count
)
4708 WARN("Only %u render targets are supported.\n", max_rt_count
);
4709 return WINED3DERR_INVALIDCALL
;
4712 if (view
&& !(view
->resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
))
4714 WARN("View resource %p doesn't have render target bind flags.\n", view
->resource
);
4715 return WINED3DERR_INVALIDCALL
;
4718 /* Set the viewport and scissor rectangles, if requested. Tests show that
4719 * stateblock recording is ignored, the change goes directly into the
4720 * primary stateblock. */
4721 if (!view_idx
&& set_viewport
)
4723 struct wined3d_state
*state
= &device
->state
;
4725 state
->viewports
[0].x
= 0;
4726 state
->viewports
[0].y
= 0;
4727 state
->viewports
[0].width
= view
->width
;
4728 state
->viewports
[0].height
= view
->height
;
4729 state
->viewports
[0].min_z
= 0.0f
;
4730 state
->viewports
[0].max_z
= 1.0f
;
4731 state
->viewport_count
= 1;
4732 wined3d_cs_emit_set_viewports(device
->cs
, 1, state
->viewports
);
4734 SetRect(&state
->scissor_rects
[0], 0, 0, view
->width
, view
->height
);
4735 state
->scissor_rect_count
= 1;
4736 wined3d_cs_emit_set_scissor_rects(device
->cs
, 1, state
->scissor_rects
);
4739 prev
= device
->fb
.render_targets
[view_idx
];
4744 wined3d_rendertarget_view_incref(view
);
4745 device
->fb
.render_targets
[view_idx
] = view
;
4746 wined3d_cs_emit_set_rendertarget_view(device
->cs
, view_idx
, view
);
4747 /* Release after the assignment, to prevent device_resource_released()
4748 * from seeing the surface as still in use. */
4750 wined3d_rendertarget_view_decref(prev
);
4752 wined3d_unbind_srv_for_rtv(device
, view
, FALSE
);
4757 HRESULT CDECL
wined3d_device_set_depth_stencil_view(struct wined3d_device
*device
,
4758 struct wined3d_rendertarget_view
*view
)
4760 struct wined3d_rendertarget_view
*prev
;
4762 TRACE("device %p, view %p.\n", device
, view
);
4764 if (view
&& !(view
->resource
->bind_flags
& WINED3D_BIND_DEPTH_STENCIL
))
4766 WARN("View resource %p has incompatible %s bind flags.\n",
4767 view
->resource
, wined3d_debug_bind_flags(view
->resource
->bind_flags
));
4768 return WINED3DERR_INVALIDCALL
;
4771 prev
= device
->fb
.depth_stencil
;
4774 TRACE("Trying to do a NOP SetRenderTarget operation.\n");
4778 if ((device
->fb
.depth_stencil
= view
))
4779 wined3d_rendertarget_view_incref(view
);
4780 wined3d_cs_emit_set_depth_stencil_view(device
->cs
, view
);
4782 wined3d_rendertarget_view_decref(prev
);
4784 wined3d_unbind_srv_for_rtv(device
, view
, TRUE
);
4789 static struct wined3d_texture
*wined3d_device_create_cursor_texture(struct wined3d_device
*device
,
4790 struct wined3d_texture
*cursor_image
, unsigned int sub_resource_idx
)
4792 unsigned int texture_level
= sub_resource_idx
% cursor_image
->level_count
;
4793 struct wined3d_sub_resource_data data
;
4794 struct wined3d_resource_desc desc
;
4795 struct wined3d_map_desc map_desc
;
4796 struct wined3d_texture
*texture
;
4799 if (FAILED(wined3d_resource_map(&cursor_image
->resource
, sub_resource_idx
, &map_desc
, NULL
, WINED3D_MAP_READ
)))
4801 ERR("Failed to map source texture.\n");
4805 data
.data
= map_desc
.data
;
4806 data
.row_pitch
= map_desc
.row_pitch
;
4807 data
.slice_pitch
= map_desc
.slice_pitch
;
4809 desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
4810 desc
.format
= WINED3DFMT_B8G8R8A8_UNORM
;
4811 desc
.multisample_type
= WINED3D_MULTISAMPLE_NONE
;
4812 desc
.multisample_quality
= 0;
4813 desc
.usage
= WINED3DUSAGE_DYNAMIC
;
4814 desc
.bind_flags
= 0;
4815 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
4816 desc
.width
= wined3d_texture_get_level_width(cursor_image
, texture_level
);
4817 desc
.height
= wined3d_texture_get_level_height(cursor_image
, texture_level
);
4821 hr
= wined3d_texture_create(device
, &desc
, 1, 1, 0, &data
, NULL
, &wined3d_null_parent_ops
, &texture
);
4822 wined3d_resource_unmap(&cursor_image
->resource
, sub_resource_idx
);
4825 ERR("Failed to create cursor texture.\n");
4832 HRESULT CDECL
wined3d_device_set_cursor_properties(struct wined3d_device
*device
,
4833 UINT x_hotspot
, UINT y_hotspot
, struct wined3d_texture
*texture
, unsigned int sub_resource_idx
)
4835 unsigned int texture_level
= sub_resource_idx
% texture
->level_count
;
4836 unsigned int cursor_width
, cursor_height
;
4837 struct wined3d_display_mode mode
;
4838 struct wined3d_map_desc map_desc
;
4841 TRACE("device %p, x_hotspot %u, y_hotspot %u, texture %p, sub_resource_idx %u.\n",
4842 device
, x_hotspot
, y_hotspot
, texture
, sub_resource_idx
);
4844 if (sub_resource_idx
>= texture
->level_count
* texture
->layer_count
4845 || texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
4846 return WINED3DERR_INVALIDCALL
;
4848 if (device
->cursor_texture
)
4850 wined3d_texture_decref(device
->cursor_texture
);
4851 device
->cursor_texture
= NULL
;
4854 if (texture
->resource
.format
->id
!= WINED3DFMT_B8G8R8A8_UNORM
)
4856 WARN("Texture %p has invalid format %s.\n",
4857 texture
, debug_d3dformat(texture
->resource
.format
->id
));
4858 return WINED3DERR_INVALIDCALL
;
4861 if (FAILED(hr
= wined3d_get_adapter_display_mode(device
->wined3d
, device
->adapter
->ordinal
, &mode
, NULL
)))
4863 ERR("Failed to get display mode, hr %#x.\n", hr
);
4864 return WINED3DERR_INVALIDCALL
;
4867 cursor_width
= wined3d_texture_get_level_width(texture
, texture_level
);
4868 cursor_height
= wined3d_texture_get_level_height(texture
, texture_level
);
4869 if (cursor_width
> mode
.width
|| cursor_height
> mode
.height
)
4871 WARN("Texture %p, sub-resource %u dimensions are %ux%u, but screen dimensions are %ux%u.\n",
4872 texture
, sub_resource_idx
, cursor_width
, cursor_height
, mode
.width
, mode
.height
);
4873 return WINED3DERR_INVALIDCALL
;
4876 /* TODO: MSDN: Cursor sizes must be a power of 2 */
4878 /* Do not store the surface's pointer because the application may
4879 * release it after setting the cursor image. Windows doesn't
4880 * addref the set surface, so we can't do this either without
4881 * creating circular refcount dependencies. */
4882 if (!(device
->cursor_texture
= wined3d_device_create_cursor_texture(device
, texture
, sub_resource_idx
)))
4884 ERR("Failed to create cursor texture.\n");
4885 return WINED3DERR_INVALIDCALL
;
4888 if (cursor_width
== 32 && cursor_height
== 32)
4890 UINT mask_size
= cursor_width
* cursor_height
/ 8;
4891 ICONINFO cursor_info
;
4895 /* 32-bit user32 cursors ignore the alpha channel if it's all
4896 * zeroes, and use the mask instead. Fill the mask with all ones
4897 * to ensure we still get a fully transparent cursor. */
4898 if (!(mask_bits
= heap_alloc(mask_size
)))
4899 return E_OUTOFMEMORY
;
4900 memset(mask_bits
, 0xff, mask_size
);
4902 wined3d_resource_map(&texture
->resource
, sub_resource_idx
, &map_desc
, NULL
,
4903 WINED3D_MAP_NO_DIRTY_UPDATE
| WINED3D_MAP_READ
);
4904 cursor_info
.fIcon
= FALSE
;
4905 cursor_info
.xHotspot
= x_hotspot
;
4906 cursor_info
.yHotspot
= y_hotspot
;
4907 cursor_info
.hbmMask
= CreateBitmap(cursor_width
, cursor_height
, 1, 1, mask_bits
);
4908 cursor_info
.hbmColor
= CreateBitmap(cursor_width
, cursor_height
, 1, 32, map_desc
.data
);
4909 wined3d_resource_unmap(&texture
->resource
, sub_resource_idx
);
4911 /* Create our cursor and clean up. */
4912 cursor
= CreateIconIndirect(&cursor_info
);
4913 if (cursor_info
.hbmMask
)
4914 DeleteObject(cursor_info
.hbmMask
);
4915 if (cursor_info
.hbmColor
)
4916 DeleteObject(cursor_info
.hbmColor
);
4917 if (device
->hardwareCursor
)
4918 DestroyCursor(device
->hardwareCursor
);
4919 device
->hardwareCursor
= cursor
;
4920 if (device
->bCursorVisible
)
4923 heap_free(mask_bits
);
4926 TRACE("New cursor dimensions are %ux%u.\n", cursor_width
, cursor_height
);
4927 device
->cursorWidth
= cursor_width
;
4928 device
->cursorHeight
= cursor_height
;
4929 device
->xHotSpot
= x_hotspot
;
4930 device
->yHotSpot
= y_hotspot
;
4935 void CDECL
wined3d_device_set_cursor_position(struct wined3d_device
*device
,
4936 int x_screen_space
, int y_screen_space
, DWORD flags
)
4938 TRACE("device %p, x %d, y %d, flags %#x.\n",
4939 device
, x_screen_space
, y_screen_space
, flags
);
4941 device
->xScreenSpace
= x_screen_space
;
4942 device
->yScreenSpace
= y_screen_space
;
4944 if (device
->hardwareCursor
)
4948 GetCursorPos( &pt
);
4949 if (x_screen_space
== pt
.x
&& y_screen_space
== pt
.y
)
4951 SetCursorPos( x_screen_space
, y_screen_space
);
4953 /* Switch to the software cursor if position diverges from the hardware one. */
4954 GetCursorPos( &pt
);
4955 if (x_screen_space
!= pt
.x
|| y_screen_space
!= pt
.y
)
4957 if (device
->bCursorVisible
) SetCursor( NULL
);
4958 DestroyCursor( device
->hardwareCursor
);
4959 device
->hardwareCursor
= 0;
4964 BOOL CDECL
wined3d_device_show_cursor(struct wined3d_device
*device
, BOOL show
)
4966 BOOL oldVisible
= device
->bCursorVisible
;
4968 TRACE("device %p, show %#x.\n", device
, show
);
4971 * When ShowCursor is first called it should make the cursor appear at the OS's last
4972 * known cursor position.
4974 if (show
&& !oldVisible
)
4978 device
->xScreenSpace
= pt
.x
;
4979 device
->yScreenSpace
= pt
.y
;
4982 if (device
->hardwareCursor
)
4984 device
->bCursorVisible
= show
;
4986 SetCursor(device
->hardwareCursor
);
4990 else if (device
->cursor_texture
)
4992 device
->bCursorVisible
= show
;
4998 void CDECL
wined3d_device_evict_managed_resources(struct wined3d_device
*device
)
5000 struct wined3d_resource
*resource
, *cursor
;
5002 TRACE("device %p.\n", device
);
5004 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &device
->resources
, struct wined3d_resource
, resource_list_entry
)
5006 TRACE("Checking resource %p for eviction.\n", resource
);
5008 if (wined3d_resource_access_is_managed(resource
->access
) && !resource
->map_count
)
5010 TRACE("Evicting %p.\n", resource
);
5011 wined3d_cs_emit_unload_resource(device
->cs
, resource
);
5016 static void update_swapchain_flags(struct wined3d_texture
*texture
)
5018 unsigned int flags
= texture
->swapchain
->state
.desc
.flags
;
5020 if (flags
& WINED3D_SWAPCHAIN_LOCKABLE_BACKBUFFER
)
5021 texture
->resource
.access
|= WINED3D_RESOURCE_ACCESS_MAP_R
| WINED3D_RESOURCE_ACCESS_MAP_W
;
5023 texture
->resource
.access
&= ~(WINED3D_RESOURCE_ACCESS_MAP_R
| WINED3D_RESOURCE_ACCESS_MAP_W
);
5025 if (flags
& WINED3D_SWAPCHAIN_GDI_COMPATIBLE
)
5026 texture
->flags
|= WINED3D_TEXTURE_GET_DC
;
5028 texture
->flags
&= ~WINED3D_TEXTURE_GET_DC
;
5031 HRESULT CDECL
wined3d_device_reset(struct wined3d_device
*device
,
5032 const struct wined3d_swapchain_desc
*swapchain_desc
, const struct wined3d_display_mode
*mode
,
5033 wined3d_device_reset_cb callback
, BOOL reset_state
)
5035 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
5036 struct wined3d_swapchain_state
*swapchain_state
;
5037 struct wined3d_swapchain_desc
*current_desc
;
5038 struct wined3d_resource
*resource
, *cursor
;
5039 struct wined3d_rendertarget_view
*view
;
5040 struct wined3d_swapchain
*swapchain
;
5041 struct wined3d_view_desc view_desc
;
5042 BOOL backbuffer_resized
, windowed
;
5043 struct wined3d_output
*output
;
5044 HRESULT hr
= WINED3D_OK
;
5047 TRACE("device %p, swapchain_desc %p, mode %p, callback %p, reset_state %#x.\n",
5048 device
, swapchain_desc
, mode
, callback
, reset_state
);
5050 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
5052 if (!(swapchain
= wined3d_device_get_swapchain(device
, 0)))
5054 ERR("Failed to get the first implicit swapchain.\n");
5055 return WINED3DERR_INVALIDCALL
;
5057 swapchain_state
= &swapchain
->state
;
5058 current_desc
= &swapchain_state
->desc
;
5062 if (device
->logo_texture
)
5064 wined3d_texture_decref(device
->logo_texture
);
5065 device
->logo_texture
= NULL
;
5067 if (device
->cursor_texture
)
5069 wined3d_texture_decref(device
->cursor_texture
);
5070 device
->cursor_texture
= NULL
;
5072 state_unbind_resources(&device
->state
);
5075 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
5077 wined3d_device_set_rendertarget_view(device
, i
, NULL
, FALSE
);
5079 wined3d_device_set_depth_stencil_view(device
, NULL
);
5083 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &device
->resources
, struct wined3d_resource
, resource_list_entry
)
5085 TRACE("Enumerating resource %p.\n", resource
);
5086 if (FAILED(hr
= callback(resource
)))
5091 TRACE("New params:\n");
5092 TRACE("backbuffer_width %u\n", swapchain_desc
->backbuffer_width
);
5093 TRACE("backbuffer_height %u\n", swapchain_desc
->backbuffer_height
);
5094 TRACE("backbuffer_format %s\n", debug_d3dformat(swapchain_desc
->backbuffer_format
));
5095 TRACE("backbuffer_count %u\n", swapchain_desc
->backbuffer_count
);
5096 TRACE("multisample_type %#x\n", swapchain_desc
->multisample_type
);
5097 TRACE("multisample_quality %u\n", swapchain_desc
->multisample_quality
);
5098 TRACE("swap_effect %#x\n", swapchain_desc
->swap_effect
);
5099 TRACE("device_window %p\n", swapchain_desc
->device_window
);
5100 TRACE("windowed %#x\n", swapchain_desc
->windowed
);
5101 TRACE("enable_auto_depth_stencil %#x\n", swapchain_desc
->enable_auto_depth_stencil
);
5102 if (swapchain_desc
->enable_auto_depth_stencil
)
5103 TRACE("auto_depth_stencil_format %s\n", debug_d3dformat(swapchain_desc
->auto_depth_stencil_format
));
5104 TRACE("flags %#x\n", swapchain_desc
->flags
);
5105 TRACE("refresh_rate %u\n", swapchain_desc
->refresh_rate
);
5106 TRACE("auto_restore_display_mode %#x\n", swapchain_desc
->auto_restore_display_mode
);
5108 if (swapchain_desc
->backbuffer_bind_flags
&& swapchain_desc
->backbuffer_bind_flags
!= WINED3D_BIND_RENDER_TARGET
)
5109 FIXME("Got unexpected backbuffer bind flags %#x.\n", swapchain_desc
->backbuffer_bind_flags
);
5111 if (swapchain_desc
->swap_effect
!= WINED3D_SWAP_EFFECT_DISCARD
5112 && swapchain_desc
->swap_effect
!= WINED3D_SWAP_EFFECT_SEQUENTIAL
5113 && swapchain_desc
->swap_effect
!= WINED3D_SWAP_EFFECT_COPY
)
5114 FIXME("Unimplemented swap effect %#x.\n", swapchain_desc
->swap_effect
);
5116 /* No special treatment of these parameters. Just store them */
5117 current_desc
->swap_effect
= swapchain_desc
->swap_effect
;
5118 current_desc
->enable_auto_depth_stencil
= swapchain_desc
->enable_auto_depth_stencil
;
5119 current_desc
->auto_depth_stencil_format
= swapchain_desc
->auto_depth_stencil_format
;
5120 current_desc
->refresh_rate
= swapchain_desc
->refresh_rate
;
5121 current_desc
->auto_restore_display_mode
= swapchain_desc
->auto_restore_display_mode
;
5123 if (swapchain_desc
->device_window
&& swapchain_desc
->device_window
!= current_desc
->device_window
)
5125 TRACE("Changing the device window from %p to %p.\n",
5126 current_desc
->device_window
, swapchain_desc
->device_window
);
5127 current_desc
->device_window
= swapchain_desc
->device_window
;
5128 swapchain_state
->device_window
= swapchain_desc
->device_window
;
5129 wined3d_swapchain_set_window(swapchain
, NULL
);
5132 backbuffer_resized
= swapchain_desc
->backbuffer_width
!= current_desc
->backbuffer_width
5133 || swapchain_desc
->backbuffer_height
!= current_desc
->backbuffer_height
;
5134 windowed
= current_desc
->windowed
;
5136 if (!swapchain_desc
->windowed
!= !windowed
|| swapchain
->reapply_mode
5137 || mode
|| (!swapchain_desc
->windowed
&& backbuffer_resized
))
5139 /* Switch from windowed to fullscreen. */
5140 if (windowed
&& !swapchain_desc
->windowed
)
5142 HWND focus_window
= device
->create_parms
.focus_window
;
5145 focus_window
= swapchain
->state
.device_window
;
5146 if (FAILED(hr
= wined3d_device_acquire_focus_window(device
, focus_window
)))
5148 ERR("Failed to acquire focus window, hr %#x.\n", hr
);
5153 if (!(output
= wined3d_swapchain_get_output(swapchain
)))
5155 ERR("Failed to get output from swapchain %p.\n", swapchain
);
5158 if (FAILED(hr
= wined3d_swapchain_state_set_fullscreen(&swapchain
->state
,
5159 swapchain_desc
, device
->wined3d
, output
, mode
)))
5162 /* Switch from fullscreen to windowed. */
5163 if (!windowed
&& swapchain_desc
->windowed
)
5164 wined3d_device_release_focus_window(device
);
5166 else if (!swapchain_desc
->windowed
)
5168 DWORD style
= swapchain_state
->style
;
5169 DWORD exstyle
= swapchain_state
->exstyle
;
5170 /* If we're in fullscreen, and the mode wasn't changed, we have to get
5171 * the window back into the right position. Some applications
5172 * (Battlefield 2, Guild Wars) move it and then call Reset() to clean
5173 * up their mess. Guild Wars also loses the device during that. */
5174 swapchain_state
->style
= 0;
5175 swapchain_state
->exstyle
= 0;
5176 wined3d_swapchain_state_setup_fullscreen(swapchain_state
, swapchain_state
->device_window
,
5177 swapchain_desc
->backbuffer_width
, swapchain_desc
->backbuffer_height
);
5178 swapchain_state
->style
= style
;
5179 swapchain_state
->exstyle
= exstyle
;
5182 if (FAILED(hr
= wined3d_swapchain_resize_buffers(swapchain
, swapchain_desc
->backbuffer_count
,
5183 swapchain_desc
->backbuffer_width
, swapchain_desc
->backbuffer_height
, swapchain_desc
->backbuffer_format
,
5184 swapchain_desc
->multisample_type
, swapchain_desc
->multisample_quality
)))
5187 if (swapchain_desc
->flags
!= current_desc
->flags
)
5189 current_desc
->flags
= swapchain_desc
->flags
;
5191 update_swapchain_flags(swapchain
->front_buffer
);
5192 for (i
= 0; i
< current_desc
->backbuffer_count
; ++i
)
5194 update_swapchain_flags(swapchain
->back_buffers
[i
]);
5198 if ((view
= device
->auto_depth_stencil_view
))
5200 device
->auto_depth_stencil_view
= NULL
;
5201 wined3d_rendertarget_view_decref(view
);
5203 if (current_desc
->enable_auto_depth_stencil
)
5205 struct wined3d_resource_desc texture_desc
;
5206 struct wined3d_texture
*texture
;
5208 TRACE("Creating the depth stencil buffer.\n");
5210 texture_desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
5211 texture_desc
.format
= current_desc
->auto_depth_stencil_format
;
5212 texture_desc
.multisample_type
= current_desc
->multisample_type
;
5213 texture_desc
.multisample_quality
= current_desc
->multisample_quality
;
5214 texture_desc
.usage
= 0;
5215 texture_desc
.bind_flags
= WINED3D_BIND_DEPTH_STENCIL
;
5216 texture_desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
5217 texture_desc
.width
= current_desc
->backbuffer_width
;
5218 texture_desc
.height
= current_desc
->backbuffer_height
;
5219 texture_desc
.depth
= 1;
5220 texture_desc
.size
= 0;
5222 if (FAILED(hr
= device
->device_parent
->ops
->create_swapchain_texture(device
->device_parent
,
5223 device
->device_parent
, &texture_desc
, 0, &texture
)))
5225 ERR("Failed to create the auto depth/stencil surface, hr %#x.\n", hr
);
5226 return WINED3DERR_INVALIDCALL
;
5229 view_desc
.format_id
= texture
->resource
.format
->id
;
5230 view_desc
.flags
= 0;
5231 view_desc
.u
.texture
.level_idx
= 0;
5232 view_desc
.u
.texture
.level_count
= 1;
5233 view_desc
.u
.texture
.layer_idx
= 0;
5234 view_desc
.u
.texture
.layer_count
= 1;
5235 hr
= wined3d_rendertarget_view_create(&view_desc
, &texture
->resource
,
5236 NULL
, &wined3d_null_parent_ops
, &device
->auto_depth_stencil_view
);
5237 wined3d_texture_decref(texture
);
5240 ERR("Failed to create rendertarget view, hr %#x.\n", hr
);
5244 wined3d_device_set_depth_stencil_view(device
, device
->auto_depth_stencil_view
);
5247 if ((view
= device
->back_buffer_view
))
5249 device
->back_buffer_view
= NULL
;
5250 wined3d_rendertarget_view_decref(view
);
5252 if (current_desc
->backbuffer_count
&& current_desc
->backbuffer_bind_flags
& WINED3D_BIND_RENDER_TARGET
)
5254 struct wined3d_resource
*back_buffer
= &swapchain
->back_buffers
[0]->resource
;
5256 view_desc
.format_id
= back_buffer
->format
->id
;
5257 view_desc
.flags
= 0;
5258 view_desc
.u
.texture
.level_idx
= 0;
5259 view_desc
.u
.texture
.level_count
= 1;
5260 view_desc
.u
.texture
.layer_idx
= 0;
5261 view_desc
.u
.texture
.layer_count
= 1;
5262 if (FAILED(hr
= wined3d_rendertarget_view_create(&view_desc
, back_buffer
,
5263 NULL
, &wined3d_null_parent_ops
, &device
->back_buffer_view
)))
5265 ERR("Failed to create rendertarget view, hr %#x.\n", hr
);
5270 wine_rb_clear(&device
->samplers
, device_free_sampler
, NULL
);
5274 TRACE("Resetting state.\n");
5275 wined3d_cs_emit_reset_state(device
->cs
);
5276 state_cleanup(&device
->state
);
5278 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &device
->resources
, struct wined3d_resource
, resource_list_entry
)
5280 TRACE("Unloading resource %p.\n", resource
);
5281 wined3d_cs_emit_unload_resource(device
->cs
, resource
);
5284 if (device
->d3d_initialized
)
5285 device
->adapter
->adapter_ops
->adapter_uninit_3d(device
);
5287 memset(&device
->state
, 0, sizeof(device
->state
));
5288 state_init(&device
->state
, &device
->fb
, &device
->adapter
->d3d_info
, WINED3D_STATE_INIT_DEFAULT
);
5290 device_init_swapchain_state(device
, swapchain
);
5291 if (wined3d_settings
.logo
)
5292 device_load_logo(device
, wined3d_settings
.logo
);
5294 else if ((view
= device
->back_buffer_view
))
5295 wined3d_device_set_rendertarget_view(device
, 0, view
, FALSE
);
5297 if (device
->d3d_initialized
&& reset_state
)
5298 hr
= device
->adapter
->adapter_ops
->adapter_init_3d(device
);
5300 /* All done. There is no need to reload resources or shaders, this will happen automatically on the
5306 HRESULT CDECL
wined3d_device_set_dialog_box_mode(struct wined3d_device
*device
, BOOL enable_dialogs
)
5308 TRACE("device %p, enable_dialogs %#x.\n", device
, enable_dialogs
);
5310 if (!enable_dialogs
) FIXME("Dialogs cannot be disabled yet.\n");
5316 void CDECL
wined3d_device_get_creation_parameters(const struct wined3d_device
*device
,
5317 struct wined3d_device_creation_parameters
*parameters
)
5319 TRACE("device %p, parameters %p.\n", device
, parameters
);
5321 *parameters
= device
->create_parms
;
5324 struct wined3d
* CDECL
wined3d_device_get_wined3d(const struct wined3d_device
*device
)
5326 TRACE("device %p.\n", device
);
5328 return device
->wined3d
;
5331 enum wined3d_feature_level CDECL
wined3d_device_get_feature_level(const struct wined3d_device
*device
)
5333 TRACE("device %p.\n", device
);
5335 return device
->feature_level
;
5338 void CDECL
wined3d_device_set_gamma_ramp(const struct wined3d_device
*device
,
5339 UINT swapchain_idx
, DWORD flags
, const struct wined3d_gamma_ramp
*ramp
)
5341 struct wined3d_swapchain
*swapchain
;
5343 TRACE("device %p, swapchain_idx %u, flags %#x, ramp %p.\n",
5344 device
, swapchain_idx
, flags
, ramp
);
5346 if ((swapchain
= wined3d_device_get_swapchain(device
, swapchain_idx
)))
5347 wined3d_swapchain_set_gamma_ramp(swapchain
, flags
, ramp
);
5350 void CDECL
wined3d_device_get_gamma_ramp(const struct wined3d_device
*device
,
5351 UINT swapchain_idx
, struct wined3d_gamma_ramp
*ramp
)
5353 struct wined3d_swapchain
*swapchain
;
5355 TRACE("device %p, swapchain_idx %u, ramp %p.\n",
5356 device
, swapchain_idx
, ramp
);
5358 if ((swapchain
= wined3d_device_get_swapchain(device
, swapchain_idx
)))
5359 wined3d_swapchain_get_gamma_ramp(swapchain
, ramp
);
5362 void device_resource_add(struct wined3d_device
*device
, struct wined3d_resource
*resource
)
5364 TRACE("device %p, resource %p.\n", device
, resource
);
5366 wined3d_not_from_cs(device
->cs
);
5368 list_add_head(&device
->resources
, &resource
->resource_list_entry
);
5371 static void device_resource_remove(struct wined3d_device
*device
, struct wined3d_resource
*resource
)
5373 TRACE("device %p, resource %p.\n", device
, resource
);
5375 wined3d_not_from_cs(device
->cs
);
5377 list_remove(&resource
->resource_list_entry
);
5380 void device_resource_released(struct wined3d_device
*device
, struct wined3d_resource
*resource
)
5382 enum wined3d_resource_type type
= resource
->type
;
5383 struct wined3d_rendertarget_view
*rtv
;
5386 TRACE("device %p, resource %p, type %s.\n", device
, resource
, debug_d3dresourcetype(type
));
5388 if (device
->d3d_initialized
)
5390 for (i
= 0; i
< ARRAY_SIZE(device
->fb
.render_targets
); ++i
)
5392 if ((rtv
= device
->fb
.render_targets
[i
]) && rtv
->resource
== resource
)
5393 ERR("Resource %p is still in use as render target %u.\n", resource
, i
);
5396 if ((rtv
= device
->fb
.depth_stencil
) && rtv
->resource
== resource
)
5397 ERR("Resource %p is still in use as depth/stencil buffer.\n", resource
);
5402 case WINED3D_RTYPE_TEXTURE_1D
:
5403 case WINED3D_RTYPE_TEXTURE_2D
:
5404 case WINED3D_RTYPE_TEXTURE_3D
:
5405 for (i
= 0; i
< WINED3D_MAX_COMBINED_SAMPLERS
; ++i
)
5407 if (&device
->state
.textures
[i
]->resource
== resource
)
5409 ERR("Texture resource %p is still in use, stage %u.\n", resource
, i
);
5410 device
->state
.textures
[i
] = NULL
;
5415 case WINED3D_RTYPE_BUFFER
:
5416 for (i
= 0; i
< WINED3D_MAX_STREAMS
; ++i
)
5418 if (&device
->state
.streams
[i
].buffer
->resource
== resource
)
5420 ERR("Buffer resource %p is still in use, stream %u.\n", resource
, i
);
5421 device
->state
.streams
[i
].buffer
= NULL
;
5425 if (&device
->state
.index_buffer
->resource
== resource
)
5427 ERR("Buffer resource %p is still in use as index buffer.\n", resource
);
5428 device
->state
.index_buffer
= NULL
;
5436 /* Remove the resource from the resourceStore */
5437 device_resource_remove(device
, resource
);
5439 TRACE("Resource released.\n");
5442 static int wined3d_sampler_compare(const void *key
, const struct wine_rb_entry
*entry
)
5444 const struct wined3d_sampler
*sampler
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_sampler
, entry
);
5446 return memcmp(&sampler
->desc
, key
, sizeof(sampler
->desc
));
5449 static int wined3d_rasterizer_state_compare(const void *key
, const struct wine_rb_entry
*entry
)
5451 const struct wined3d_rasterizer_state
*state
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_rasterizer_state
, entry
);
5453 return memcmp(&state
->desc
, key
, sizeof(state
->desc
));
5456 static BOOL
wined3d_select_feature_level(const struct wined3d_adapter
*adapter
,
5457 const enum wined3d_feature_level
*levels
, unsigned int level_count
,
5458 enum wined3d_feature_level
*selected_level
)
5460 const struct wined3d_d3d_info
*d3d_info
= &adapter
->d3d_info
;
5463 for (i
= 0; i
< level_count
; ++i
)
5465 if (levels
[i
] && d3d_info
->feature_level
>= levels
[i
])
5467 *selected_level
= levels
[i
];
5472 FIXME_(winediag
)("None of the requested D3D feature levels is supported on this GPU "
5473 "with the current shader backend.\n");
5477 HRESULT
wined3d_device_init(struct wined3d_device
*device
, struct wined3d
*wined3d
,
5478 unsigned int adapter_idx
, enum wined3d_device_type device_type
, HWND focus_window
, unsigned int flags
,
5479 BYTE surface_alignment
, const enum wined3d_feature_level
*levels
, unsigned int level_count
,
5480 struct wined3d_device_parent
*device_parent
)
5482 struct wined3d_adapter
*adapter
= wined3d
->adapters
[adapter_idx
];
5483 const struct wined3d_fragment_pipe_ops
*fragment_pipeline
;
5484 const struct wined3d_vertex_pipe_ops
*vertex_pipeline
;
5485 struct wined3d_blend_state_desc blend_state_desc
;
5489 if (!wined3d_select_feature_level(adapter
, levels
, level_count
, &device
->feature_level
))
5492 TRACE("Device feature level %s.\n", wined3d_debug_feature_level(device
->feature_level
));
5495 device
->wined3d
= wined3d
;
5496 wined3d_incref(device
->wined3d
);
5497 device
->adapter
= adapter
;
5498 device
->device_parent
= device_parent
;
5499 list_init(&device
->resources
);
5500 list_init(&device
->shaders
);
5501 device
->surface_alignment
= surface_alignment
;
5503 /* Save the creation parameters. */
5504 device
->create_parms
.adapter_idx
= adapter_idx
;
5505 device
->create_parms
.device_type
= device_type
;
5506 device
->create_parms
.focus_window
= focus_window
;
5507 device
->create_parms
.flags
= flags
;
5509 device
->shader_backend
= adapter
->shader_backend
;
5511 vertex_pipeline
= adapter
->vertex_pipe
;
5513 fragment_pipeline
= adapter
->fragment_pipe
;
5515 wine_rb_init(&device
->samplers
, wined3d_sampler_compare
);
5516 wine_rb_init(&device
->rasterizer_states
, wined3d_rasterizer_state_compare
);
5518 if (vertex_pipeline
->vp_states
&& fragment_pipeline
->states
5519 && FAILED(hr
= compile_state_table(device
->state_table
, device
->multistate_funcs
,
5520 &adapter
->d3d_info
, adapter
->gl_info
.supported
, vertex_pipeline
,
5521 fragment_pipeline
, misc_state_template
)))
5523 ERR("Failed to compile state table, hr %#x.\n", hr
);
5524 wine_rb_destroy(&device
->samplers
, NULL
, NULL
);
5525 wine_rb_destroy(&device
->rasterizer_states
, NULL
, NULL
);
5526 wined3d_decref(device
->wined3d
);
5530 state_init(&device
->state
, &device
->fb
, &adapter
->d3d_info
, WINED3D_STATE_INIT_DEFAULT
);
5532 device
->max_frame_latency
= 3;
5534 if (!(device
->cs
= wined3d_cs_create(device
)))
5536 WARN("Failed to create command stream.\n");
5537 state_cleanup(&device
->state
);
5542 memset(&blend_state_desc
, 0, sizeof(blend_state_desc
));
5543 blend_state_desc
.alpha_to_coverage
= TRUE
;
5545 if (FAILED(hr
= wined3d_blend_state_create(device
, &blend_state_desc
,
5546 NULL
, &wined3d_null_parent_ops
, &device
->blend_state_atoc_enabled
)))
5548 ERR("Failed to create blend state object, hr %#x.\n", hr
);
5549 wined3d_cs_destroy(device
->cs
);
5550 state_cleanup(&device
->state
);
5557 for (i
= 0; i
< ARRAY_SIZE(device
->multistate_funcs
); ++i
)
5559 heap_free(device
->multistate_funcs
[i
]);
5561 wine_rb_destroy(&device
->samplers
, NULL
, NULL
);
5562 wine_rb_destroy(&device
->rasterizer_states
, NULL
, NULL
);
5563 wined3d_decref(device
->wined3d
);
5567 void device_invalidate_state(const struct wined3d_device
*device
, unsigned int state_id
)
5569 unsigned int representative
, i
, idx
, shift
;
5570 struct wined3d_context
*context
;
5572 wined3d_from_cs(device
->cs
);
5574 if (STATE_IS_COMPUTE(state_id
))
5576 for (i
= 0; i
< device
->context_count
; ++i
)
5577 context_invalidate_compute_state(device
->contexts
[i
], state_id
);
5581 representative
= device
->state_table
[state_id
].representative
;
5582 idx
= representative
/ (sizeof(*context
->dirty_graphics_states
) * CHAR_BIT
);
5583 shift
= representative
& ((sizeof(*context
->dirty_graphics_states
) * CHAR_BIT
) - 1);
5584 for (i
= 0; i
< device
->context_count
; ++i
)
5586 device
->contexts
[i
]->dirty_graphics_states
[idx
] |= (1u << shift
);
5590 LRESULT
device_process_message(struct wined3d_device
*device
, HWND window
, BOOL unicode
,
5591 UINT message
, WPARAM wparam
, LPARAM lparam
, WNDPROC proc
)
5593 if (message
== WM_DESTROY
)
5595 TRACE("unregister window %p.\n", window
);
5596 wined3d_unregister_window(window
);
5598 if (InterlockedCompareExchangePointer((void **)&device
->focus_window
, NULL
, window
) != window
)
5599 ERR("Window %p is not the focus window for device %p.\n", window
, device
);
5601 else if (message
== WM_DISPLAYCHANGE
)
5603 device
->device_parent
->ops
->mode_changed(device
->device_parent
);
5605 else if (message
== WM_ACTIVATEAPP
)
5607 unsigned int i
= device
->swapchain_count
;
5609 /* Deactivating the implicit swapchain may cause the application
5610 * (e.g. Deus Ex: GOTY) to destroy the device, so take care to
5611 * deactivate the implicit swapchain last, and to avoid accessing the
5612 * "device" pointer afterwards. */
5614 wined3d_swapchain_activate(device
->swapchains
[i
], wparam
);
5616 else if (message
== WM_SYSCOMMAND
)
5618 if (wparam
== SC_RESTORE
&& device
->wined3d
->flags
& WINED3D_HANDLE_RESTORE
)
5621 DefWindowProcW(window
, message
, wparam
, lparam
);
5623 DefWindowProcA(window
, message
, wparam
, lparam
);
5628 return CallWindowProcW(proc
, window
, message
, wparam
, lparam
);
5630 return CallWindowProcA(proc
, window
, message
, wparam
, lparam
);