2 * Copyright 2013 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
25 #define WINED3D_INITIAL_CS_SIZE 4096
29 WINED3D_CS_OP_PRESENT
,
32 WINED3D_CS_OP_SET_PREDICATION
,
33 WINED3D_CS_OP_SET_VIEWPORT
,
34 WINED3D_CS_OP_SET_SCISSOR_RECT
,
35 WINED3D_CS_OP_SET_RENDERTARGET_VIEW
,
36 WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
,
37 WINED3D_CS_OP_SET_VERTEX_DECLARATION
,
38 WINED3D_CS_OP_SET_STREAM_SOURCE
,
39 WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
,
40 WINED3D_CS_OP_SET_STREAM_OUTPUT
,
41 WINED3D_CS_OP_SET_INDEX_BUFFER
,
42 WINED3D_CS_OP_SET_CONSTANT_BUFFER
,
43 WINED3D_CS_OP_SET_TEXTURE
,
44 WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
,
45 WINED3D_CS_OP_SET_SAMPLER
,
46 WINED3D_CS_OP_SET_SHADER
,
47 WINED3D_CS_OP_SET_RENDER_STATE
,
48 WINED3D_CS_OP_SET_TEXTURE_STATE
,
49 WINED3D_CS_OP_SET_SAMPLER_STATE
,
50 WINED3D_CS_OP_SET_TRANSFORM
,
51 WINED3D_CS_OP_SET_CLIP_PLANE
,
52 WINED3D_CS_OP_SET_COLOR_KEY
,
53 WINED3D_CS_OP_SET_MATERIAL
,
54 WINED3D_CS_OP_RESET_STATE
,
57 struct wined3d_cs_present
59 enum wined3d_cs_op opcode
;
60 HWND dst_window_override
;
61 struct wined3d_swapchain
*swapchain
;
64 const RGNDATA
*dirty_region
;
68 struct wined3d_cs_clear
70 enum wined3d_cs_op opcode
;
74 const struct wined3d_color
*color
;
79 struct wined3d_cs_draw
81 enum wined3d_cs_op opcode
;
89 struct wined3d_cs_set_predication
91 enum wined3d_cs_op opcode
;
92 struct wined3d_query
*predicate
;
96 struct wined3d_cs_set_viewport
98 enum wined3d_cs_op opcode
;
99 const struct wined3d_viewport
*viewport
;
102 struct wined3d_cs_set_scissor_rect
104 enum wined3d_cs_op opcode
;
108 struct wined3d_cs_set_rendertarget_view
110 enum wined3d_cs_op opcode
;
111 unsigned int view_idx
;
112 struct wined3d_rendertarget_view
*view
;
115 struct wined3d_cs_set_depth_stencil_view
117 enum wined3d_cs_op opcode
;
118 struct wined3d_rendertarget_view
*view
;
121 struct wined3d_cs_set_vertex_declaration
123 enum wined3d_cs_op opcode
;
124 struct wined3d_vertex_declaration
*declaration
;
127 struct wined3d_cs_set_stream_source
129 enum wined3d_cs_op opcode
;
131 struct wined3d_buffer
*buffer
;
136 struct wined3d_cs_set_stream_source_freq
138 enum wined3d_cs_op opcode
;
144 struct wined3d_cs_set_stream_output
146 enum wined3d_cs_op opcode
;
148 struct wined3d_buffer
*buffer
;
152 struct wined3d_cs_set_index_buffer
154 enum wined3d_cs_op opcode
;
155 struct wined3d_buffer
*buffer
;
156 enum wined3d_format_id format_id
;
159 struct wined3d_cs_set_constant_buffer
161 enum wined3d_cs_op opcode
;
162 enum wined3d_shader_type type
;
164 struct wined3d_buffer
*buffer
;
167 struct wined3d_cs_set_texture
169 enum wined3d_cs_op opcode
;
171 struct wined3d_texture
*texture
;
174 struct wined3d_cs_set_color_key
176 enum wined3d_cs_op opcode
;
177 struct wined3d_texture
*texture
;
180 struct wined3d_color_key color_key
;
183 struct wined3d_cs_set_shader_resource_view
185 enum wined3d_cs_op opcode
;
186 enum wined3d_shader_type type
;
188 struct wined3d_shader_resource_view
*view
;
191 struct wined3d_cs_set_sampler
193 enum wined3d_cs_op opcode
;
194 enum wined3d_shader_type type
;
196 struct wined3d_sampler
*sampler
;
199 struct wined3d_cs_set_shader
201 enum wined3d_cs_op opcode
;
202 enum wined3d_shader_type type
;
203 struct wined3d_shader
*shader
;
206 struct wined3d_cs_set_render_state
208 enum wined3d_cs_op opcode
;
209 enum wined3d_render_state state
;
213 struct wined3d_cs_set_texture_state
215 enum wined3d_cs_op opcode
;
217 enum wined3d_texture_stage_state state
;
221 struct wined3d_cs_set_sampler_state
223 enum wined3d_cs_op opcode
;
225 enum wined3d_sampler_state state
;
229 struct wined3d_cs_set_transform
231 enum wined3d_cs_op opcode
;
232 enum wined3d_transform_state state
;
233 const struct wined3d_matrix
*matrix
;
236 struct wined3d_cs_set_clip_plane
238 enum wined3d_cs_op opcode
;
240 const struct wined3d_vec4
*plane
;
243 struct wined3d_cs_set_material
245 enum wined3d_cs_op opcode
;
246 const struct wined3d_material
*material
;
249 struct wined3d_cs_reset_state
251 enum wined3d_cs_op opcode
;
254 static void wined3d_cs_exec_present(struct wined3d_cs
*cs
, const void *data
)
256 const struct wined3d_cs_present
*op
= data
;
257 struct wined3d_swapchain
*swapchain
;
259 swapchain
= op
->swapchain
;
260 wined3d_swapchain_set_window(swapchain
, op
->dst_window_override
);
262 swapchain
->swapchain_ops
->swapchain_present(swapchain
,
263 op
->src_rect
, op
->dst_rect
, op
->dirty_region
, op
->flags
);
266 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
267 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
,
268 const RGNDATA
*dirty_region
, DWORD flags
)
270 struct wined3d_cs_present
*op
;
272 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
273 op
->opcode
= WINED3D_CS_OP_PRESENT
;
274 op
->dst_window_override
= dst_window_override
;
275 op
->swapchain
= swapchain
;
276 op
->src_rect
= src_rect
;
277 op
->dst_rect
= dst_rect
;
278 op
->dirty_region
= dirty_region
;
284 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
286 const struct wined3d_cs_clear
*op
= data
;
287 struct wined3d_device
*device
;
291 wined3d_get_draw_rect(&device
->state
, &draw_rect
);
292 device_clear_render_targets(device
, device
->adapter
->gl_info
.limits
.buffers
,
293 &device
->fb
, op
->rect_count
, op
->rects
, &draw_rect
, op
->flags
,
294 op
->color
, op
->depth
, op
->stencil
);
297 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
298 DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
300 struct wined3d_cs_clear
*op
;
302 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
303 op
->opcode
= WINED3D_CS_OP_CLEAR
;
304 op
->rect_count
= rect_count
;
309 op
->stencil
= stencil
;
314 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
316 const struct wined3d_cs_draw
*op
= data
;
318 draw_primitive(cs
->device
, op
->start_idx
, op
->index_count
,
319 op
->start_instance
, op
->instance_count
, op
->indexed
);
322 void wined3d_cs_emit_draw(struct wined3d_cs
*cs
, UINT start_idx
, UINT index_count
,
323 UINT start_instance
, UINT instance_count
, BOOL indexed
)
325 struct wined3d_cs_draw
*op
;
327 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
328 op
->opcode
= WINED3D_CS_OP_DRAW
;
329 op
->start_idx
= start_idx
;
330 op
->index_count
= index_count
;
331 op
->start_instance
= start_instance
;
332 op
->instance_count
= instance_count
;
333 op
->indexed
= indexed
;
338 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
340 const struct wined3d_cs_set_predication
*op
= data
;
342 cs
->state
.predicate
= op
->predicate
;
343 cs
->state
.predicate_value
= op
->value
;
346 void wined3d_cs_emit_set_predication(struct wined3d_cs
*cs
, struct wined3d_query
*predicate
, BOOL value
)
348 struct wined3d_cs_set_predication
*op
;
350 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
351 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
352 op
->predicate
= predicate
;
358 static void wined3d_cs_exec_set_viewport(struct wined3d_cs
*cs
, const void *data
)
360 const struct wined3d_cs_set_viewport
*op
= data
;
362 cs
->state
.viewport
= *op
->viewport
;
363 device_invalidate_state(cs
->device
, STATE_VIEWPORT
);
366 void wined3d_cs_emit_set_viewport(struct wined3d_cs
*cs
, const struct wined3d_viewport
*viewport
)
368 struct wined3d_cs_set_viewport
*op
;
370 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
371 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORT
;
372 op
->viewport
= viewport
;
377 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs
*cs
, const void *data
)
379 const struct wined3d_cs_set_scissor_rect
*op
= data
;
381 cs
->state
.scissor_rect
= *op
->rect
;
382 device_invalidate_state(cs
->device
, STATE_SCISSORRECT
);
385 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs
*cs
, const RECT
*rect
)
387 struct wined3d_cs_set_scissor_rect
*op
;
389 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
390 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECT
;
396 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs
*cs
, const void *data
)
398 const struct wined3d_cs_set_rendertarget_view
*op
= data
;
400 cs
->state
.fb
->render_targets
[op
->view_idx
] = op
->view
;
401 device_invalidate_state(cs
->device
, STATE_FRAMEBUFFER
);
404 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs
*cs
, unsigned int view_idx
,
405 struct wined3d_rendertarget_view
*view
)
407 struct wined3d_cs_set_rendertarget_view
*op
;
409 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
410 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEW
;
411 op
->view_idx
= view_idx
;
417 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
419 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
420 struct wined3d_device
*device
= cs
->device
;
421 struct wined3d_rendertarget_view
*prev
;
423 if ((prev
= cs
->state
.fb
->depth_stencil
))
425 struct wined3d_surface
*prev_surface
= wined3d_rendertarget_view_get_surface(prev
);
427 if (prev_surface
&& (device
->swapchains
[0]->desc
.flags
& WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
428 || prev_surface
->flags
& SFLAG_DISCARD
))
430 surface_modify_ds_location(prev_surface
, WINED3D_LOCATION_DISCARDED
, prev
->width
, prev
->height
);
431 if (prev_surface
== device
->onscreen_depth_stencil
)
433 wined3d_texture_decref(device
->onscreen_depth_stencil
->container
);
434 device
->onscreen_depth_stencil
= NULL
;
439 cs
->fb
.depth_stencil
= op
->view
;
441 if (!prev
!= !op
->view
)
443 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
444 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_ZENABLE
));
445 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILENABLE
));
446 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK
));
447 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
449 else if (prev
&& (prev
->format_flags
& WINED3DFMT_FLAG_FLOAT
)
450 != (op
->view
->format_flags
& WINED3DFMT_FLAG_FLOAT
))
452 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
455 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
458 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs
*cs
, struct wined3d_rendertarget_view
*view
)
460 struct wined3d_cs_set_depth_stencil_view
*op
;
462 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
463 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
469 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
471 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
473 cs
->state
.vertex_declaration
= op
->declaration
;
474 device_invalidate_state(cs
->device
, STATE_VDECL
);
477 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs
*cs
, struct wined3d_vertex_declaration
*declaration
)
479 struct wined3d_cs_set_vertex_declaration
*op
;
481 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
482 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
483 op
->declaration
= declaration
;
488 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs
*cs
, const void *data
)
490 const struct wined3d_cs_set_stream_source
*op
= data
;
491 struct wined3d_stream_state
*stream
;
492 struct wined3d_buffer
*prev
;
494 stream
= &cs
->state
.streams
[op
->stream_idx
];
495 prev
= stream
->buffer
;
496 stream
->buffer
= op
->buffer
;
497 stream
->offset
= op
->offset
;
498 stream
->stride
= op
->stride
;
501 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
503 InterlockedDecrement(&prev
->resource
.bind_count
);
505 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
508 void wined3d_cs_emit_set_stream_source(struct wined3d_cs
*cs
, UINT stream_idx
,
509 struct wined3d_buffer
*buffer
, UINT offset
, UINT stride
)
511 struct wined3d_cs_set_stream_source
*op
;
513 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
514 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE
;
515 op
->stream_idx
= stream_idx
;
523 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs
*cs
, const void *data
)
525 const struct wined3d_cs_set_stream_source_freq
*op
= data
;
526 struct wined3d_stream_state
*stream
;
528 stream
= &cs
->state
.streams
[op
->stream_idx
];
529 stream
->frequency
= op
->frequency
;
530 stream
->flags
= op
->flags
;
532 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
535 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs
*cs
, UINT stream_idx
, UINT frequency
, UINT flags
)
537 struct wined3d_cs_set_stream_source_freq
*op
;
539 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
540 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
;
541 op
->stream_idx
= stream_idx
;
542 op
->frequency
= frequency
;
548 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs
*cs
, const void *data
)
550 const struct wined3d_cs_set_stream_output
*op
= data
;
551 struct wined3d_stream_output
*stream
;
552 struct wined3d_buffer
*prev
;
554 stream
= &cs
->state
.stream_output
[op
->stream_idx
];
555 prev
= stream
->buffer
;
556 stream
->buffer
= op
->buffer
;
557 stream
->offset
= op
->offset
;
560 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
562 InterlockedDecrement(&prev
->resource
.bind_count
);
565 void wined3d_cs_emit_set_stream_output(struct wined3d_cs
*cs
, UINT stream_idx
,
566 struct wined3d_buffer
*buffer
, UINT offset
)
568 struct wined3d_cs_set_stream_output
*op
;
570 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
571 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUT
;
572 op
->stream_idx
= stream_idx
;
579 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
581 const struct wined3d_cs_set_index_buffer
*op
= data
;
582 struct wined3d_buffer
*prev
;
584 prev
= cs
->state
.index_buffer
;
585 cs
->state
.index_buffer
= op
->buffer
;
586 cs
->state
.index_format
= op
->format_id
;
589 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
591 InterlockedDecrement(&prev
->resource
.bind_count
);
593 device_invalidate_state(cs
->device
, STATE_INDEXBUFFER
);
596 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs
*cs
, struct wined3d_buffer
*buffer
,
597 enum wined3d_format_id format_id
)
599 struct wined3d_cs_set_index_buffer
*op
;
601 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
602 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
604 op
->format_id
= format_id
;
609 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs
*cs
, const void *data
)
611 const struct wined3d_cs_set_constant_buffer
*op
= data
;
612 struct wined3d_buffer
*prev
;
614 prev
= cs
->state
.cb
[op
->type
][op
->cb_idx
];
615 cs
->state
.cb
[op
->type
][op
->cb_idx
] = op
->buffer
;
618 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
620 InterlockedDecrement(&prev
->resource
.bind_count
);
622 device_invalidate_state(cs
->device
, STATE_CONSTANT_BUFFER(op
->type
));
625 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
626 UINT cb_idx
, struct wined3d_buffer
*buffer
)
628 struct wined3d_cs_set_constant_buffer
*op
;
630 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
631 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFER
;
639 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
641 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
642 const struct wined3d_cs_set_texture
*op
= data
;
643 struct wined3d_texture
*prev
;
644 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
646 prev
= cs
->state
.textures
[op
->stage
];
647 cs
->state
.textures
[op
->stage
] = op
->texture
;
651 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
652 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
653 unsigned int old_fmt_flags
= prev
? prev
->resource
.format_flags
: 0;
654 unsigned int new_fmt_flags
= op
->texture
->resource
.format_flags
;
656 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
657 op
->texture
->sampler
= op
->stage
;
659 if (!prev
|| op
->texture
->target
!= prev
->target
660 || !is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
661 || (new_fmt_flags
& WINED3DFMT_FLAG_SHADOW
) != (old_fmt_flags
& WINED3DFMT_FLAG_SHADOW
))
662 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
664 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
666 /* The source arguments for color and alpha ops have different
667 * meanings when a NULL texture is bound, so the COLOR_OP and
668 * ALPHA_OP have to be dirtified. */
669 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
670 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
673 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
674 new_use_color_key
= TRUE
;
679 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
683 /* Search for other stages the texture is bound to. Shouldn't
684 * happen if applications bind textures to a single stage only. */
685 TRACE("Searching for other stages the texture is bound to.\n");
686 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
688 if (cs
->state
.textures
[i
] == prev
)
690 TRACE("Texture is also bound to stage %u.\n", i
);
697 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
699 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
700 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
703 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
704 old_use_color_key
= TRUE
;
707 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->stage
));
709 if (new_use_color_key
!= old_use_color_key
)
710 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
712 if (new_use_color_key
)
713 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
716 void wined3d_cs_emit_set_texture(struct wined3d_cs
*cs
, UINT stage
, struct wined3d_texture
*texture
)
718 struct wined3d_cs_set_texture
*op
;
720 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
721 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
723 op
->texture
= texture
;
728 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs
*cs
, const void *data
)
730 const struct wined3d_cs_set_shader_resource_view
*op
= data
;
732 cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
] = op
->view
;
733 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
736 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
737 UINT view_idx
, struct wined3d_shader_resource_view
*view
)
739 struct wined3d_cs_set_shader_resource_view
*op
;
741 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
742 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
;
744 op
->view_idx
= view_idx
;
750 static void wined3d_cs_exec_set_sampler(struct wined3d_cs
*cs
, const void *data
)
752 const struct wined3d_cs_set_sampler
*op
= data
;
754 cs
->state
.sampler
[op
->type
][op
->sampler_idx
] = op
->sampler
;
755 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
758 void wined3d_cs_emit_set_sampler(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
759 UINT sampler_idx
, struct wined3d_sampler
*sampler
)
761 struct wined3d_cs_set_sampler
*op
;
763 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
764 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER
;
766 op
->sampler_idx
= sampler_idx
;
767 op
->sampler
= sampler
;
772 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
774 const struct wined3d_cs_set_shader
*op
= data
;
776 cs
->state
.shader
[op
->type
] = op
->shader
;
777 device_invalidate_state(cs
->device
, STATE_SHADER(op
->type
));
778 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
781 void wined3d_cs_emit_set_shader(struct wined3d_cs
*cs
, enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
783 struct wined3d_cs_set_shader
*op
;
785 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
786 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
793 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
795 const struct wined3d_cs_set_render_state
*op
= data
;
797 cs
->state
.render_states
[op
->state
] = op
->value
;
798 device_invalidate_state(cs
->device
, STATE_RENDER(op
->state
));
801 void wined3d_cs_emit_set_render_state(struct wined3d_cs
*cs
, enum wined3d_render_state state
, DWORD value
)
803 struct wined3d_cs_set_render_state
*op
;
805 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
806 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
813 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
815 const struct wined3d_cs_set_texture_state
*op
= data
;
817 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
818 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
821 void wined3d_cs_emit_set_texture_state(struct wined3d_cs
*cs
, UINT stage
,
822 enum wined3d_texture_stage_state state
, DWORD value
)
824 struct wined3d_cs_set_texture_state
*op
;
826 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
827 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
835 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
837 const struct wined3d_cs_set_sampler_state
*op
= data
;
839 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
840 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->sampler_idx
));
843 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs
*cs
, UINT sampler_idx
,
844 enum wined3d_sampler_state state
, DWORD value
)
846 struct wined3d_cs_set_sampler_state
*op
;
848 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
849 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
850 op
->sampler_idx
= sampler_idx
;
857 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
859 const struct wined3d_cs_set_transform
*op
= data
;
861 cs
->state
.transforms
[op
->state
] = *op
->matrix
;
862 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
863 device_invalidate_state(cs
->device
, STATE_TRANSFORM(op
->state
));
866 void wined3d_cs_emit_set_transform(struct wined3d_cs
*cs
, enum wined3d_transform_state state
,
867 const struct wined3d_matrix
*matrix
)
869 struct wined3d_cs_set_transform
*op
;
871 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
872 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
879 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
881 const struct wined3d_cs_set_clip_plane
*op
= data
;
883 cs
->state
.clip_planes
[op
->plane_idx
] = *op
->plane
;
884 device_invalidate_state(cs
->device
, STATE_CLIPPLANE(op
->plane_idx
));
887 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs
*cs
, UINT plane_idx
, const struct wined3d_vec4
*plane
)
889 struct wined3d_cs_set_clip_plane
*op
;
891 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
892 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
893 op
->plane_idx
= plane_idx
;
899 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
901 const struct wined3d_cs_set_color_key
*op
= data
;
902 struct wined3d_texture
*texture
= op
->texture
;
908 case WINED3D_CKEY_DST_BLT
:
909 texture
->async
.dst_blt_color_key
= op
->color_key
;
910 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
913 case WINED3D_CKEY_DST_OVERLAY
:
914 texture
->async
.dst_overlay_color_key
= op
->color_key
;
915 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
918 case WINED3D_CKEY_SRC_BLT
:
919 if (texture
== cs
->state
.textures
[0])
921 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
922 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
923 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
926 texture
->async
.src_blt_color_key
= op
->color_key
;
927 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
930 case WINED3D_CKEY_SRC_OVERLAY
:
931 texture
->async
.src_overlay_color_key
= op
->color_key
;
932 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
940 case WINED3D_CKEY_DST_BLT
:
941 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
944 case WINED3D_CKEY_DST_OVERLAY
:
945 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
948 case WINED3D_CKEY_SRC_BLT
:
949 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
950 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
952 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
955 case WINED3D_CKEY_SRC_OVERLAY
:
956 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
962 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
963 WORD flags
, const struct wined3d_color_key
*color_key
)
965 struct wined3d_cs_set_color_key
*op
;
967 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
968 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
969 op
->texture
= texture
;
973 op
->color_key
= *color_key
;
982 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
984 const struct wined3d_cs_set_material
*op
= data
;
986 cs
->state
.material
= *op
->material
;
987 device_invalidate_state(cs
->device
, STATE_MATERIAL
);
990 void wined3d_cs_emit_set_material(struct wined3d_cs
*cs
, const struct wined3d_material
*material
)
992 struct wined3d_cs_set_material
*op
;
994 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
995 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
996 op
->material
= material
;
1001 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
1003 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
1006 state_cleanup(&cs
->state
);
1007 memset(&cs
->state
, 0, sizeof(cs
->state
));
1008 if (FAILED(hr
= state_init(&cs
->state
, &cs
->fb
, &adapter
->gl_info
, &adapter
->d3d_info
,
1009 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
)))
1010 ERR("Failed to initialize CS state, hr %#x.\n", hr
);
1013 void wined3d_cs_emit_reset_state(struct wined3d_cs
*cs
)
1015 struct wined3d_cs_reset_state
*op
;
1017 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1018 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
1020 cs
->ops
->submit(cs
);
1023 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
1025 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
1026 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
1027 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
1028 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
1029 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport
,
1030 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect
,
1031 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view
,
1032 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
1033 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
1034 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source
,
1035 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq
,
1036 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output
,
1037 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
1038 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer
,
1039 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
1040 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view
,
1041 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler
,
1042 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
1043 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
1044 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
1045 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
1046 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
1047 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
1048 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
1049 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
1050 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
1053 static void *wined3d_cs_st_require_space(struct wined3d_cs
*cs
, size_t size
)
1055 if (size
> cs
->data_size
)
1059 size
= max( size
, cs
->data_size
* 2 );
1060 if (!(new_data
= HeapReAlloc(GetProcessHeap(), 0, cs
->data
, size
)))
1063 cs
->data_size
= size
;
1064 cs
->data
= new_data
;
1070 static void wined3d_cs_st_submit(struct wined3d_cs
*cs
)
1072 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)cs
->data
;
1074 wined3d_cs_op_handlers
[opcode
](cs
, cs
->data
);
1077 static const struct wined3d_cs_ops wined3d_cs_st_ops
=
1079 wined3d_cs_st_require_space
,
1080 wined3d_cs_st_submit
,
1083 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
)
1085 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
1086 struct wined3d_cs
*cs
;
1088 if (!(cs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cs
))))
1091 if (!(cs
->fb
.render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1092 sizeof(*cs
->fb
.render_targets
) * gl_info
->limits
.buffers
)))
1094 HeapFree(GetProcessHeap(), 0, cs
);
1098 if (FAILED(state_init(&cs
->state
, &cs
->fb
, gl_info
, &device
->adapter
->d3d_info
,
1099 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
)))
1101 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1102 HeapFree(GetProcessHeap(), 0, cs
);
1106 cs
->ops
= &wined3d_cs_st_ops
;
1107 cs
->device
= device
;
1109 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
1110 if (!(cs
->data
= HeapAlloc(GetProcessHeap(), 0, cs
->data_size
)))
1112 HeapFree(GetProcessHeap(), 0, cs
);
1119 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
1121 state_cleanup(&cs
->state
);
1122 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1123 HeapFree(GetProcessHeap(), 0, cs
->data
);
1124 HeapFree(GetProcessHeap(), 0, cs
);