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
;
67 struct wined3d_cs_clear
69 enum wined3d_cs_op opcode
;
71 struct wined3d_color color
;
74 unsigned int rect_count
;
78 struct wined3d_cs_draw
80 enum wined3d_cs_op opcode
;
88 struct wined3d_cs_set_predication
90 enum wined3d_cs_op opcode
;
91 struct wined3d_query
*predicate
;
95 struct wined3d_cs_set_viewport
97 enum wined3d_cs_op opcode
;
98 struct wined3d_viewport viewport
;
101 struct wined3d_cs_set_scissor_rect
103 enum wined3d_cs_op opcode
;
107 struct wined3d_cs_set_rendertarget_view
109 enum wined3d_cs_op opcode
;
110 unsigned int view_idx
;
111 struct wined3d_rendertarget_view
*view
;
114 struct wined3d_cs_set_depth_stencil_view
116 enum wined3d_cs_op opcode
;
117 struct wined3d_rendertarget_view
*view
;
120 struct wined3d_cs_set_vertex_declaration
122 enum wined3d_cs_op opcode
;
123 struct wined3d_vertex_declaration
*declaration
;
126 struct wined3d_cs_set_stream_source
128 enum wined3d_cs_op opcode
;
130 struct wined3d_buffer
*buffer
;
135 struct wined3d_cs_set_stream_source_freq
137 enum wined3d_cs_op opcode
;
143 struct wined3d_cs_set_stream_output
145 enum wined3d_cs_op opcode
;
147 struct wined3d_buffer
*buffer
;
151 struct wined3d_cs_set_index_buffer
153 enum wined3d_cs_op opcode
;
154 struct wined3d_buffer
*buffer
;
155 enum wined3d_format_id format_id
;
158 struct wined3d_cs_set_constant_buffer
160 enum wined3d_cs_op opcode
;
161 enum wined3d_shader_type type
;
163 struct wined3d_buffer
*buffer
;
166 struct wined3d_cs_set_texture
168 enum wined3d_cs_op opcode
;
170 struct wined3d_texture
*texture
;
173 struct wined3d_cs_set_color_key
175 enum wined3d_cs_op opcode
;
176 struct wined3d_texture
*texture
;
179 struct wined3d_color_key color_key
;
182 struct wined3d_cs_set_shader_resource_view
184 enum wined3d_cs_op opcode
;
185 enum wined3d_shader_type type
;
187 struct wined3d_shader_resource_view
*view
;
190 struct wined3d_cs_set_sampler
192 enum wined3d_cs_op opcode
;
193 enum wined3d_shader_type type
;
195 struct wined3d_sampler
*sampler
;
198 struct wined3d_cs_set_shader
200 enum wined3d_cs_op opcode
;
201 enum wined3d_shader_type type
;
202 struct wined3d_shader
*shader
;
205 struct wined3d_cs_set_render_state
207 enum wined3d_cs_op opcode
;
208 enum wined3d_render_state state
;
212 struct wined3d_cs_set_texture_state
214 enum wined3d_cs_op opcode
;
216 enum wined3d_texture_stage_state state
;
220 struct wined3d_cs_set_sampler_state
222 enum wined3d_cs_op opcode
;
224 enum wined3d_sampler_state state
;
228 struct wined3d_cs_set_transform
230 enum wined3d_cs_op opcode
;
231 enum wined3d_transform_state state
;
232 struct wined3d_matrix matrix
;
235 struct wined3d_cs_set_clip_plane
237 enum wined3d_cs_op opcode
;
239 struct wined3d_vec4 plane
;
242 struct wined3d_cs_set_material
244 enum wined3d_cs_op opcode
;
245 struct wined3d_material material
;
248 struct wined3d_cs_reset_state
250 enum wined3d_cs_op opcode
;
253 static void wined3d_cs_exec_present(struct wined3d_cs
*cs
, const void *data
)
255 const struct wined3d_cs_present
*op
= data
;
256 struct wined3d_swapchain
*swapchain
;
258 swapchain
= op
->swapchain
;
259 wined3d_swapchain_set_window(swapchain
, op
->dst_window_override
);
261 swapchain
->swapchain_ops
->swapchain_present(swapchain
, &op
->src_rect
, &op
->dst_rect
, op
->flags
);
264 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
265 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
, DWORD flags
)
267 struct wined3d_cs_present
*op
;
269 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
270 op
->opcode
= WINED3D_CS_OP_PRESENT
;
271 op
->dst_window_override
= dst_window_override
;
272 op
->swapchain
= swapchain
;
273 op
->src_rect
= *src_rect
;
274 op
->dst_rect
= *dst_rect
;
280 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
282 const struct wined3d_cs_clear
*op
= data
;
283 struct wined3d_device
*device
;
287 wined3d_get_draw_rect(&device
->state
, &draw_rect
);
288 device_clear_render_targets(device
, device
->adapter
->gl_info
.limits
.buffers
,
289 &device
->fb
, op
->rect_count
, op
->rects
, &draw_rect
, op
->flags
,
290 &op
->color
, op
->depth
, op
->stencil
);
293 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
294 DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
296 struct wined3d_cs_clear
*op
;
298 op
= cs
->ops
->require_space(cs
, FIELD_OFFSET(struct wined3d_cs_clear
, rects
[rect_count
]));
299 op
->opcode
= WINED3D_CS_OP_CLEAR
;
303 op
->stencil
= stencil
;
304 op
->rect_count
= rect_count
;
305 memcpy(op
->rects
, rects
, sizeof(*rects
) * rect_count
);
310 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
312 const struct wined3d_cs_draw
*op
= data
;
314 draw_primitive(cs
->device
, &cs
->device
->state
, op
->start_idx
, op
->index_count
,
315 op
->start_instance
, op
->instance_count
, op
->indexed
);
318 void wined3d_cs_emit_draw(struct wined3d_cs
*cs
, UINT start_idx
, UINT index_count
,
319 UINT start_instance
, UINT instance_count
, BOOL indexed
)
321 struct wined3d_cs_draw
*op
;
323 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
324 op
->opcode
= WINED3D_CS_OP_DRAW
;
325 op
->start_idx
= start_idx
;
326 op
->index_count
= index_count
;
327 op
->start_instance
= start_instance
;
328 op
->instance_count
= instance_count
;
329 op
->indexed
= indexed
;
334 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
336 const struct wined3d_cs_set_predication
*op
= data
;
338 cs
->state
.predicate
= op
->predicate
;
339 cs
->state
.predicate_value
= op
->value
;
342 void wined3d_cs_emit_set_predication(struct wined3d_cs
*cs
, struct wined3d_query
*predicate
, BOOL value
)
344 struct wined3d_cs_set_predication
*op
;
346 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
347 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
348 op
->predicate
= predicate
;
354 static void wined3d_cs_exec_set_viewport(struct wined3d_cs
*cs
, const void *data
)
356 const struct wined3d_cs_set_viewport
*op
= data
;
358 cs
->state
.viewport
= op
->viewport
;
359 device_invalidate_state(cs
->device
, STATE_VIEWPORT
);
362 void wined3d_cs_emit_set_viewport(struct wined3d_cs
*cs
, const struct wined3d_viewport
*viewport
)
364 struct wined3d_cs_set_viewport
*op
;
366 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
367 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORT
;
368 op
->viewport
= *viewport
;
373 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs
*cs
, const void *data
)
375 const struct wined3d_cs_set_scissor_rect
*op
= data
;
377 cs
->state
.scissor_rect
= op
->rect
;
378 device_invalidate_state(cs
->device
, STATE_SCISSORRECT
);
381 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs
*cs
, const RECT
*rect
)
383 struct wined3d_cs_set_scissor_rect
*op
;
385 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
386 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECT
;
392 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs
*cs
, const void *data
)
394 const struct wined3d_cs_set_rendertarget_view
*op
= data
;
396 cs
->state
.fb
->render_targets
[op
->view_idx
] = op
->view
;
397 device_invalidate_state(cs
->device
, STATE_FRAMEBUFFER
);
400 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs
*cs
, unsigned int view_idx
,
401 struct wined3d_rendertarget_view
*view
)
403 struct wined3d_cs_set_rendertarget_view
*op
;
405 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
406 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEW
;
407 op
->view_idx
= view_idx
;
413 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
415 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
416 struct wined3d_device
*device
= cs
->device
;
417 struct wined3d_rendertarget_view
*prev
;
419 if ((prev
= cs
->state
.fb
->depth_stencil
))
421 struct wined3d_surface
*prev_surface
= wined3d_rendertarget_view_get_surface(prev
);
423 if (prev_surface
&& (device
->swapchains
[0]->desc
.flags
& WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
424 || prev_surface
->container
->flags
& WINED3D_TEXTURE_DISCARD
))
426 surface_modify_ds_location(prev_surface
, WINED3D_LOCATION_DISCARDED
, prev
->width
, prev
->height
);
427 if (prev_surface
== device
->onscreen_depth_stencil
)
429 wined3d_texture_decref(device
->onscreen_depth_stencil
->container
);
430 device
->onscreen_depth_stencil
= NULL
;
435 cs
->fb
.depth_stencil
= op
->view
;
437 if (!prev
!= !op
->view
)
439 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
440 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_ZENABLE
));
441 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILENABLE
));
442 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK
));
443 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
445 else if (prev
&& (prev
->format_flags
& WINED3DFMT_FLAG_FLOAT
)
446 != (op
->view
->format_flags
& WINED3DFMT_FLAG_FLOAT
))
448 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
451 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
454 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs
*cs
, struct wined3d_rendertarget_view
*view
)
456 struct wined3d_cs_set_depth_stencil_view
*op
;
458 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
459 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
465 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
467 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
469 cs
->state
.vertex_declaration
= op
->declaration
;
470 device_invalidate_state(cs
->device
, STATE_VDECL
);
473 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs
*cs
, struct wined3d_vertex_declaration
*declaration
)
475 struct wined3d_cs_set_vertex_declaration
*op
;
477 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
478 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
479 op
->declaration
= declaration
;
484 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs
*cs
, const void *data
)
486 const struct wined3d_cs_set_stream_source
*op
= data
;
487 struct wined3d_stream_state
*stream
;
488 struct wined3d_buffer
*prev
;
490 stream
= &cs
->state
.streams
[op
->stream_idx
];
491 prev
= stream
->buffer
;
492 stream
->buffer
= op
->buffer
;
493 stream
->offset
= op
->offset
;
494 stream
->stride
= op
->stride
;
497 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
499 InterlockedDecrement(&prev
->resource
.bind_count
);
501 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
504 void wined3d_cs_emit_set_stream_source(struct wined3d_cs
*cs
, UINT stream_idx
,
505 struct wined3d_buffer
*buffer
, UINT offset
, UINT stride
)
507 struct wined3d_cs_set_stream_source
*op
;
509 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
510 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE
;
511 op
->stream_idx
= stream_idx
;
519 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs
*cs
, const void *data
)
521 const struct wined3d_cs_set_stream_source_freq
*op
= data
;
522 struct wined3d_stream_state
*stream
;
524 stream
= &cs
->state
.streams
[op
->stream_idx
];
525 stream
->frequency
= op
->frequency
;
526 stream
->flags
= op
->flags
;
528 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
531 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs
*cs
, UINT stream_idx
, UINT frequency
, UINT flags
)
533 struct wined3d_cs_set_stream_source_freq
*op
;
535 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
536 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
;
537 op
->stream_idx
= stream_idx
;
538 op
->frequency
= frequency
;
544 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs
*cs
, const void *data
)
546 const struct wined3d_cs_set_stream_output
*op
= data
;
547 struct wined3d_stream_output
*stream
;
548 struct wined3d_buffer
*prev
;
550 stream
= &cs
->state
.stream_output
[op
->stream_idx
];
551 prev
= stream
->buffer
;
552 stream
->buffer
= op
->buffer
;
553 stream
->offset
= op
->offset
;
556 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
558 InterlockedDecrement(&prev
->resource
.bind_count
);
561 void wined3d_cs_emit_set_stream_output(struct wined3d_cs
*cs
, UINT stream_idx
,
562 struct wined3d_buffer
*buffer
, UINT offset
)
564 struct wined3d_cs_set_stream_output
*op
;
566 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
567 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUT
;
568 op
->stream_idx
= stream_idx
;
575 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
577 const struct wined3d_cs_set_index_buffer
*op
= data
;
578 struct wined3d_buffer
*prev
;
580 prev
= cs
->state
.index_buffer
;
581 cs
->state
.index_buffer
= op
->buffer
;
582 cs
->state
.index_format
= op
->format_id
;
585 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
587 InterlockedDecrement(&prev
->resource
.bind_count
);
589 device_invalidate_state(cs
->device
, STATE_INDEXBUFFER
);
592 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs
*cs
, struct wined3d_buffer
*buffer
,
593 enum wined3d_format_id format_id
)
595 struct wined3d_cs_set_index_buffer
*op
;
597 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
598 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
600 op
->format_id
= format_id
;
605 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs
*cs
, const void *data
)
607 const struct wined3d_cs_set_constant_buffer
*op
= data
;
608 struct wined3d_buffer
*prev
;
610 prev
= cs
->state
.cb
[op
->type
][op
->cb_idx
];
611 cs
->state
.cb
[op
->type
][op
->cb_idx
] = op
->buffer
;
614 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
616 InterlockedDecrement(&prev
->resource
.bind_count
);
618 device_invalidate_state(cs
->device
, STATE_CONSTANT_BUFFER(op
->type
));
621 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
622 UINT cb_idx
, struct wined3d_buffer
*buffer
)
624 struct wined3d_cs_set_constant_buffer
*op
;
626 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
627 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFER
;
635 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
637 const struct wined3d_gl_info
*gl_info
= &cs
->device
->adapter
->gl_info
;
638 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
639 const struct wined3d_cs_set_texture
*op
= data
;
640 struct wined3d_texture
*prev
;
641 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
643 prev
= cs
->state
.textures
[op
->stage
];
644 cs
->state
.textures
[op
->stage
] = op
->texture
;
648 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
649 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
650 unsigned int old_fmt_flags
= prev
? prev
->resource
.format_flags
: 0;
651 unsigned int new_fmt_flags
= op
->texture
->resource
.format_flags
;
653 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
654 op
->texture
->sampler
= op
->stage
;
656 if (!prev
|| op
->texture
->target
!= prev
->target
657 || (!is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
658 && !(can_use_texture_swizzle(gl_info
, new_format
) && can_use_texture_swizzle(gl_info
, old_format
)))
659 || (new_fmt_flags
& WINED3DFMT_FLAG_SHADOW
) != (old_fmt_flags
& WINED3DFMT_FLAG_SHADOW
))
660 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
662 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
664 /* The source arguments for color and alpha ops have different
665 * meanings when a NULL texture is bound, so the COLOR_OP and
666 * ALPHA_OP have to be dirtified. */
667 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
668 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
671 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
672 new_use_color_key
= TRUE
;
677 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
681 /* Search for other stages the texture is bound to. Shouldn't
682 * happen if applications bind textures to a single stage only. */
683 TRACE("Searching for other stages the texture is bound to.\n");
684 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
686 if (cs
->state
.textures
[i
] == prev
)
688 TRACE("Texture is also bound to stage %u.\n", i
);
695 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
697 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
698 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
701 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
702 old_use_color_key
= TRUE
;
705 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->stage
));
707 if (new_use_color_key
!= old_use_color_key
)
708 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
710 if (new_use_color_key
)
711 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
714 void wined3d_cs_emit_set_texture(struct wined3d_cs
*cs
, UINT stage
, struct wined3d_texture
*texture
)
716 struct wined3d_cs_set_texture
*op
;
718 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
719 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
721 op
->texture
= texture
;
726 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs
*cs
, const void *data
)
728 const struct wined3d_cs_set_shader_resource_view
*op
= data
;
730 cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
] = op
->view
;
731 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
734 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
735 UINT view_idx
, struct wined3d_shader_resource_view
*view
)
737 struct wined3d_cs_set_shader_resource_view
*op
;
739 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
740 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
;
742 op
->view_idx
= view_idx
;
748 static void wined3d_cs_exec_set_sampler(struct wined3d_cs
*cs
, const void *data
)
750 const struct wined3d_cs_set_sampler
*op
= data
;
752 cs
->state
.sampler
[op
->type
][op
->sampler_idx
] = op
->sampler
;
753 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
756 void wined3d_cs_emit_set_sampler(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
757 UINT sampler_idx
, struct wined3d_sampler
*sampler
)
759 struct wined3d_cs_set_sampler
*op
;
761 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
762 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER
;
764 op
->sampler_idx
= sampler_idx
;
765 op
->sampler
= sampler
;
770 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
772 const struct wined3d_cs_set_shader
*op
= data
;
774 cs
->state
.shader
[op
->type
] = op
->shader
;
775 device_invalidate_state(cs
->device
, STATE_SHADER(op
->type
));
776 device_invalidate_state(cs
->device
, STATE_SHADER_RESOURCE_BINDING
);
779 void wined3d_cs_emit_set_shader(struct wined3d_cs
*cs
, enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
781 struct wined3d_cs_set_shader
*op
;
783 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
784 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
791 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
793 const struct wined3d_cs_set_render_state
*op
= data
;
795 cs
->state
.render_states
[op
->state
] = op
->value
;
796 device_invalidate_state(cs
->device
, STATE_RENDER(op
->state
));
799 void wined3d_cs_emit_set_render_state(struct wined3d_cs
*cs
, enum wined3d_render_state state
, DWORD value
)
801 struct wined3d_cs_set_render_state
*op
;
803 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
804 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
811 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
813 const struct wined3d_cs_set_texture_state
*op
= data
;
815 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
816 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
819 void wined3d_cs_emit_set_texture_state(struct wined3d_cs
*cs
, UINT stage
,
820 enum wined3d_texture_stage_state state
, DWORD value
)
822 struct wined3d_cs_set_texture_state
*op
;
824 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
825 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
833 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
835 const struct wined3d_cs_set_sampler_state
*op
= data
;
837 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
838 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->sampler_idx
));
841 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs
*cs
, UINT sampler_idx
,
842 enum wined3d_sampler_state state
, DWORD value
)
844 struct wined3d_cs_set_sampler_state
*op
;
846 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
847 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
848 op
->sampler_idx
= sampler_idx
;
855 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
857 const struct wined3d_cs_set_transform
*op
= data
;
859 cs
->state
.transforms
[op
->state
] = op
->matrix
;
860 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
861 device_invalidate_state(cs
->device
, STATE_TRANSFORM(op
->state
));
864 void wined3d_cs_emit_set_transform(struct wined3d_cs
*cs
, enum wined3d_transform_state state
,
865 const struct wined3d_matrix
*matrix
)
867 struct wined3d_cs_set_transform
*op
;
869 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
870 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
872 op
->matrix
= *matrix
;
877 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
879 const struct wined3d_cs_set_clip_plane
*op
= data
;
881 cs
->state
.clip_planes
[op
->plane_idx
] = op
->plane
;
882 device_invalidate_state(cs
->device
, STATE_CLIPPLANE(op
->plane_idx
));
885 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs
*cs
, UINT plane_idx
, const struct wined3d_vec4
*plane
)
887 struct wined3d_cs_set_clip_plane
*op
;
889 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
890 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
891 op
->plane_idx
= plane_idx
;
897 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
899 const struct wined3d_cs_set_color_key
*op
= data
;
900 struct wined3d_texture
*texture
= op
->texture
;
906 case WINED3D_CKEY_DST_BLT
:
907 texture
->async
.dst_blt_color_key
= op
->color_key
;
908 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
911 case WINED3D_CKEY_DST_OVERLAY
:
912 texture
->async
.dst_overlay_color_key
= op
->color_key
;
913 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
916 case WINED3D_CKEY_SRC_BLT
:
917 if (texture
== cs
->state
.textures
[0])
919 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
920 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
921 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
924 texture
->async
.src_blt_color_key
= op
->color_key
;
925 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
928 case WINED3D_CKEY_SRC_OVERLAY
:
929 texture
->async
.src_overlay_color_key
= op
->color_key
;
930 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
938 case WINED3D_CKEY_DST_BLT
:
939 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
942 case WINED3D_CKEY_DST_OVERLAY
:
943 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
946 case WINED3D_CKEY_SRC_BLT
:
947 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
948 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
950 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
953 case WINED3D_CKEY_SRC_OVERLAY
:
954 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
960 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
961 WORD flags
, const struct wined3d_color_key
*color_key
)
963 struct wined3d_cs_set_color_key
*op
;
965 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
966 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
967 op
->texture
= texture
;
971 op
->color_key
= *color_key
;
980 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
982 const struct wined3d_cs_set_material
*op
= data
;
984 cs
->state
.material
= op
->material
;
985 device_invalidate_state(cs
->device
, STATE_MATERIAL
);
988 void wined3d_cs_emit_set_material(struct wined3d_cs
*cs
, const struct wined3d_material
*material
)
990 struct wined3d_cs_set_material
*op
;
992 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
993 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
994 op
->material
= *material
;
999 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
1001 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
1004 state_cleanup(&cs
->state
);
1005 memset(&cs
->state
, 0, sizeof(cs
->state
));
1006 if (FAILED(hr
= state_init(&cs
->state
, &cs
->fb
, &adapter
->gl_info
, &adapter
->d3d_info
,
1007 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
)))
1008 ERR("Failed to initialize CS state, hr %#x.\n", hr
);
1011 void wined3d_cs_emit_reset_state(struct wined3d_cs
*cs
)
1013 struct wined3d_cs_reset_state
*op
;
1015 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1016 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
1018 cs
->ops
->submit(cs
);
1021 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
1023 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
1024 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
1025 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
1026 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
1027 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport
,
1028 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect
,
1029 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view
,
1030 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
1031 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
1032 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source
,
1033 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq
,
1034 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output
,
1035 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
1036 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer
,
1037 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
1038 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view
,
1039 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler
,
1040 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
1041 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
1042 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
1043 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
1044 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
1045 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
1046 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
1047 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
1048 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
1051 static void *wined3d_cs_st_require_space(struct wined3d_cs
*cs
, size_t size
)
1053 if (size
> cs
->data_size
)
1057 size
= max( size
, cs
->data_size
* 2 );
1058 if (!(new_data
= HeapReAlloc(GetProcessHeap(), 0, cs
->data
, size
)))
1061 cs
->data_size
= size
;
1062 cs
->data
= new_data
;
1068 static void wined3d_cs_st_submit(struct wined3d_cs
*cs
)
1070 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)cs
->data
;
1072 wined3d_cs_op_handlers
[opcode
](cs
, cs
->data
);
1075 static const struct wined3d_cs_ops wined3d_cs_st_ops
=
1077 wined3d_cs_st_require_space
,
1078 wined3d_cs_st_submit
,
1081 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
)
1083 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
1084 struct wined3d_cs
*cs
;
1086 if (!(cs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cs
))))
1089 if (!(cs
->fb
.render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1090 sizeof(*cs
->fb
.render_targets
) * gl_info
->limits
.buffers
)))
1092 HeapFree(GetProcessHeap(), 0, cs
);
1096 if (FAILED(state_init(&cs
->state
, &cs
->fb
, gl_info
, &device
->adapter
->d3d_info
,
1097 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
)))
1099 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1100 HeapFree(GetProcessHeap(), 0, cs
);
1104 cs
->ops
= &wined3d_cs_st_ops
;
1105 cs
->device
= device
;
1107 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
1108 if (!(cs
->data
= HeapAlloc(GetProcessHeap(), 0, cs
->data_size
)))
1110 HeapFree(GetProcessHeap(), 0, cs
);
1117 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
1119 state_cleanup(&cs
->state
);
1120 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1121 HeapFree(GetProcessHeap(), 0, cs
->data
);
1122 HeapFree(GetProcessHeap(), 0, cs
);