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_surface_decref(device
->onscreen_depth_stencil
);
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
->depth_size
!= op
->view
->format
->depth_size
)
451 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
454 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
457 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs
*cs
, struct wined3d_rendertarget_view
*view
)
459 struct wined3d_cs_set_depth_stencil_view
*op
;
461 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
462 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
468 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
470 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
472 cs
->state
.vertex_declaration
= op
->declaration
;
473 device_invalidate_state(cs
->device
, STATE_VDECL
);
476 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs
*cs
, struct wined3d_vertex_declaration
*declaration
)
478 struct wined3d_cs_set_vertex_declaration
*op
;
480 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
481 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
482 op
->declaration
= declaration
;
487 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs
*cs
, const void *data
)
489 const struct wined3d_cs_set_stream_source
*op
= data
;
490 struct wined3d_stream_state
*stream
;
491 struct wined3d_buffer
*prev
;
493 stream
= &cs
->state
.streams
[op
->stream_idx
];
494 prev
= stream
->buffer
;
495 stream
->buffer
= op
->buffer
;
496 stream
->offset
= op
->offset
;
497 stream
->stride
= op
->stride
;
500 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
502 InterlockedDecrement(&prev
->resource
.bind_count
);
504 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
507 void wined3d_cs_emit_set_stream_source(struct wined3d_cs
*cs
, UINT stream_idx
,
508 struct wined3d_buffer
*buffer
, UINT offset
, UINT stride
)
510 struct wined3d_cs_set_stream_source
*op
;
512 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
513 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE
;
514 op
->stream_idx
= stream_idx
;
522 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs
*cs
, const void *data
)
524 const struct wined3d_cs_set_stream_source_freq
*op
= data
;
525 struct wined3d_stream_state
*stream
;
527 stream
= &cs
->state
.streams
[op
->stream_idx
];
528 stream
->frequency
= op
->frequency
;
529 stream
->flags
= op
->flags
;
531 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
534 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs
*cs
, UINT stream_idx
, UINT frequency
, UINT flags
)
536 struct wined3d_cs_set_stream_source_freq
*op
;
538 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
539 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
;
540 op
->stream_idx
= stream_idx
;
541 op
->frequency
= frequency
;
547 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs
*cs
, const void *data
)
549 const struct wined3d_cs_set_stream_output
*op
= data
;
550 struct wined3d_stream_output
*stream
;
551 struct wined3d_buffer
*prev
;
553 stream
= &cs
->state
.stream_output
[op
->stream_idx
];
554 prev
= stream
->buffer
;
555 stream
->buffer
= op
->buffer
;
556 stream
->offset
= op
->offset
;
559 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
561 InterlockedDecrement(&prev
->resource
.bind_count
);
564 void wined3d_cs_emit_set_stream_output(struct wined3d_cs
*cs
, UINT stream_idx
,
565 struct wined3d_buffer
*buffer
, UINT offset
)
567 struct wined3d_cs_set_stream_output
*op
;
569 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
570 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUT
;
571 op
->stream_idx
= stream_idx
;
578 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
580 const struct wined3d_cs_set_index_buffer
*op
= data
;
581 struct wined3d_buffer
*prev
;
583 prev
= cs
->state
.index_buffer
;
584 cs
->state
.index_buffer
= op
->buffer
;
585 cs
->state
.index_format
= op
->format_id
;
588 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
590 InterlockedDecrement(&prev
->resource
.bind_count
);
592 device_invalidate_state(cs
->device
, STATE_INDEXBUFFER
);
595 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs
*cs
, struct wined3d_buffer
*buffer
,
596 enum wined3d_format_id format_id
)
598 struct wined3d_cs_set_index_buffer
*op
;
600 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
601 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
603 op
->format_id
= format_id
;
608 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs
*cs
, const void *data
)
610 const struct wined3d_cs_set_constant_buffer
*op
= data
;
611 struct wined3d_buffer
*prev
;
613 prev
= cs
->state
.cb
[op
->type
][op
->cb_idx
];
614 cs
->state
.cb
[op
->type
][op
->cb_idx
] = op
->buffer
;
617 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
619 InterlockedDecrement(&prev
->resource
.bind_count
);
621 device_invalidate_state(cs
->device
, STATE_CONSTANT_BUFFER(op
->type
));
624 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
625 UINT cb_idx
, struct wined3d_buffer
*buffer
)
627 struct wined3d_cs_set_constant_buffer
*op
;
629 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
630 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFER
;
638 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
640 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
641 const struct wined3d_cs_set_texture
*op
= data
;
642 struct wined3d_texture
*prev
;
643 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
645 prev
= cs
->state
.textures
[op
->stage
];
646 cs
->state
.textures
[op
->stage
] = op
->texture
;
650 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
651 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
652 unsigned int old_fmt_flags
= prev
? prev
->resource
.format_flags
: 0;
653 unsigned int new_fmt_flags
= op
->texture
->resource
.format_flags
;
655 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
656 op
->texture
->sampler
= op
->stage
;
658 if (!prev
|| op
->texture
->target
!= prev
->target
659 || !is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
660 || (new_fmt_flags
& WINED3DFMT_FLAG_SHADOW
) != (old_fmt_flags
& WINED3DFMT_FLAG_SHADOW
))
661 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
663 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
665 /* The source arguments for color and alpha ops have different
666 * meanings when a NULL texture is bound, so the COLOR_OP and
667 * ALPHA_OP have to be dirtified. */
668 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
669 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
672 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
673 new_use_color_key
= TRUE
;
678 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
682 /* Search for other stages the texture is bound to. Shouldn't
683 * happen if applications bind textures to a single stage only. */
684 TRACE("Searching for other stages the texture is bound to.\n");
685 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
687 if (cs
->state
.textures
[i
] == prev
)
689 TRACE("Texture is also bound to stage %u.\n", i
);
696 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
698 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
699 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
702 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
703 old_use_color_key
= TRUE
;
706 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->stage
));
708 if (new_use_color_key
!= old_use_color_key
)
709 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
711 if (new_use_color_key
)
712 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
715 void wined3d_cs_emit_set_texture(struct wined3d_cs
*cs
, UINT stage
, struct wined3d_texture
*texture
)
717 struct wined3d_cs_set_texture
*op
;
719 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
720 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
722 op
->texture
= texture
;
727 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs
*cs
, const void *data
)
729 const struct wined3d_cs_set_shader_resource_view
*op
= data
;
731 cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
] = op
->view
;
732 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
735 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
736 UINT view_idx
, struct wined3d_shader_resource_view
*view
)
738 struct wined3d_cs_set_shader_resource_view
*op
;
740 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
741 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
;
743 op
->view_idx
= view_idx
;
749 static void wined3d_cs_exec_set_sampler(struct wined3d_cs
*cs
, const void *data
)
751 const struct wined3d_cs_set_sampler
*op
= data
;
753 cs
->state
.sampler
[op
->type
][op
->sampler_idx
] = op
->sampler
;
754 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
757 void wined3d_cs_emit_set_sampler(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
758 UINT sampler_idx
, struct wined3d_sampler
*sampler
)
760 struct wined3d_cs_set_sampler
*op
;
762 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
763 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER
;
765 op
->sampler_idx
= sampler_idx
;
766 op
->sampler
= sampler
;
771 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
773 const struct wined3d_cs_set_shader
*op
= data
;
775 cs
->state
.shader
[op
->type
] = op
->shader
;
776 device_invalidate_state(cs
->device
, STATE_SHADER(op
->type
));
777 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
780 void wined3d_cs_emit_set_shader(struct wined3d_cs
*cs
, enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
782 struct wined3d_cs_set_shader
*op
;
784 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
785 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
792 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
794 const struct wined3d_cs_set_render_state
*op
= data
;
796 cs
->state
.render_states
[op
->state
] = op
->value
;
797 device_invalidate_state(cs
->device
, STATE_RENDER(op
->state
));
800 void wined3d_cs_emit_set_render_state(struct wined3d_cs
*cs
, enum wined3d_render_state state
, DWORD value
)
802 struct wined3d_cs_set_render_state
*op
;
804 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
805 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
812 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
814 const struct wined3d_cs_set_texture_state
*op
= data
;
816 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
817 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
820 void wined3d_cs_emit_set_texture_state(struct wined3d_cs
*cs
, UINT stage
,
821 enum wined3d_texture_stage_state state
, DWORD value
)
823 struct wined3d_cs_set_texture_state
*op
;
825 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
826 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
834 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
836 const struct wined3d_cs_set_sampler_state
*op
= data
;
838 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
839 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->sampler_idx
));
842 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs
*cs
, UINT sampler_idx
,
843 enum wined3d_sampler_state state
, DWORD value
)
845 struct wined3d_cs_set_sampler_state
*op
;
847 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
848 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
849 op
->sampler_idx
= sampler_idx
;
856 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
858 const struct wined3d_cs_set_transform
*op
= data
;
860 cs
->state
.transforms
[op
->state
] = *op
->matrix
;
861 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->device
->adapter
->gl_info
.limits
.blends
))
862 device_invalidate_state(cs
->device
, STATE_TRANSFORM(op
->state
));
865 void wined3d_cs_emit_set_transform(struct wined3d_cs
*cs
, enum wined3d_transform_state state
,
866 const struct wined3d_matrix
*matrix
)
868 struct wined3d_cs_set_transform
*op
;
870 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
871 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
878 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
880 const struct wined3d_cs_set_clip_plane
*op
= data
;
882 cs
->state
.clip_planes
[op
->plane_idx
] = *op
->plane
;
883 device_invalidate_state(cs
->device
, STATE_CLIPPLANE(op
->plane_idx
));
886 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs
*cs
, UINT plane_idx
, const struct wined3d_vec4
*plane
)
888 struct wined3d_cs_set_clip_plane
*op
;
890 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
891 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
892 op
->plane_idx
= plane_idx
;
898 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
900 const struct wined3d_cs_set_color_key
*op
= data
;
901 struct wined3d_texture
*texture
= op
->texture
;
905 switch (op
->flags
& ~WINED3D_CKEY_COLORSPACE
)
907 case WINED3D_CKEY_DST_BLT
:
908 texture
->async
.dst_blt_color_key
= op
->color_key
;
909 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
912 case WINED3D_CKEY_DST_OVERLAY
:
913 texture
->async
.dst_overlay_color_key
= op
->color_key
;
914 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
917 case WINED3D_CKEY_SRC_BLT
:
918 if (texture
== cs
->state
.textures
[0])
920 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
921 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
922 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
925 texture
->async
.src_blt_color_key
= op
->color_key
;
926 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
929 case WINED3D_CKEY_SRC_OVERLAY
:
930 texture
->async
.src_overlay_color_key
= op
->color_key
;
931 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
937 switch (op
->flags
& ~WINED3D_CKEY_COLORSPACE
)
939 case WINED3D_CKEY_DST_BLT
:
940 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
943 case WINED3D_CKEY_DST_OVERLAY
:
944 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
947 case WINED3D_CKEY_SRC_BLT
:
948 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
949 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
951 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
954 case WINED3D_CKEY_SRC_OVERLAY
:
955 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
961 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
962 WORD flags
, const struct wined3d_color_key
*color_key
)
964 struct wined3d_cs_set_color_key
*op
;
966 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
967 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
968 op
->texture
= texture
;
972 op
->color_key
= *color_key
;
981 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
983 const struct wined3d_cs_set_material
*op
= data
;
985 cs
->state
.material
= *op
->material
;
986 device_invalidate_state(cs
->device
, STATE_MATERIAL
);
989 void wined3d_cs_emit_set_material(struct wined3d_cs
*cs
, const struct wined3d_material
*material
)
991 struct wined3d_cs_set_material
*op
;
993 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
994 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
995 op
->material
= material
;
1000 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
1002 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
1005 state_cleanup(&cs
->state
);
1006 memset(&cs
->state
, 0, sizeof(cs
->state
));
1007 if (FAILED(hr
= state_init(&cs
->state
, &cs
->fb
, &adapter
->gl_info
, &adapter
->d3d_info
,
1008 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
)))
1009 ERR("Failed to initialize CS state, hr %#x.\n", hr
);
1012 void wined3d_cs_emit_reset_state(struct wined3d_cs
*cs
)
1014 struct wined3d_cs_reset_state
*op
;
1016 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1017 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
1019 cs
->ops
->submit(cs
);
1022 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
1024 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
1025 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
1026 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
1027 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
1028 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport
,
1029 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect
,
1030 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view
,
1031 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
1032 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
1033 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source
,
1034 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq
,
1035 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output
,
1036 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
1037 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer
,
1038 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
1039 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view
,
1040 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler
,
1041 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
1042 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
1043 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
1044 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
1045 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
1046 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
1047 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
1048 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
1049 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
1052 static void *wined3d_cs_st_require_space(struct wined3d_cs
*cs
, size_t size
)
1054 if (size
> cs
->data_size
)
1058 size
= max( size
, cs
->data_size
* 2 );
1059 if (!(new_data
= HeapReAlloc(GetProcessHeap(), 0, cs
->data
, size
)))
1062 cs
->data_size
= size
;
1063 cs
->data
= new_data
;
1069 static void wined3d_cs_st_submit(struct wined3d_cs
*cs
)
1071 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)cs
->data
;
1073 wined3d_cs_op_handlers
[opcode
](cs
, cs
->data
);
1076 static const struct wined3d_cs_ops wined3d_cs_st_ops
=
1078 wined3d_cs_st_require_space
,
1079 wined3d_cs_st_submit
,
1082 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
)
1084 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
1085 struct wined3d_cs
*cs
;
1087 if (!(cs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cs
))))
1090 if (!(cs
->fb
.render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1091 sizeof(*cs
->fb
.render_targets
) * gl_info
->limits
.buffers
)))
1093 HeapFree(GetProcessHeap(), 0, cs
);
1097 if (FAILED(state_init(&cs
->state
, &cs
->fb
, gl_info
, &device
->adapter
->d3d_info
,
1098 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
)))
1100 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1101 HeapFree(GetProcessHeap(), 0, cs
);
1105 cs
->ops
= &wined3d_cs_st_ops
;
1106 cs
->device
= device
;
1108 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
1109 if (!(cs
->data
= HeapAlloc(GetProcessHeap(), 0, cs
->data_size
)))
1111 HeapFree(GetProcessHeap(), 0, cs
);
1118 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
1120 state_cleanup(&cs
->state
);
1121 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1122 HeapFree(GetProcessHeap(), 0, cs
->data
);
1123 HeapFree(GetProcessHeap(), 0, cs
);