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
,
31 WINED3D_CS_OP_DISPATCH
,
33 WINED3D_CS_OP_SET_PREDICATION
,
34 WINED3D_CS_OP_SET_VIEWPORT
,
35 WINED3D_CS_OP_SET_SCISSOR_RECT
,
36 WINED3D_CS_OP_SET_RENDERTARGET_VIEW
,
37 WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
,
38 WINED3D_CS_OP_SET_VERTEX_DECLARATION
,
39 WINED3D_CS_OP_SET_STREAM_SOURCE
,
40 WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
,
41 WINED3D_CS_OP_SET_STREAM_OUTPUT
,
42 WINED3D_CS_OP_SET_INDEX_BUFFER
,
43 WINED3D_CS_OP_SET_CONSTANT_BUFFER
,
44 WINED3D_CS_OP_SET_TEXTURE
,
45 WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
,
46 WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW
,
47 WINED3D_CS_OP_SET_SAMPLER
,
48 WINED3D_CS_OP_SET_SHADER
,
49 WINED3D_CS_OP_SET_RASTERIZER_STATE
,
50 WINED3D_CS_OP_SET_RENDER_STATE
,
51 WINED3D_CS_OP_SET_TEXTURE_STATE
,
52 WINED3D_CS_OP_SET_SAMPLER_STATE
,
53 WINED3D_CS_OP_SET_TRANSFORM
,
54 WINED3D_CS_OP_SET_CLIP_PLANE
,
55 WINED3D_CS_OP_SET_COLOR_KEY
,
56 WINED3D_CS_OP_SET_MATERIAL
,
57 WINED3D_CS_OP_SET_LIGHT
,
58 WINED3D_CS_OP_SET_LIGHT_ENABLE
,
59 WINED3D_CS_OP_RESET_STATE
,
60 WINED3D_CS_OP_CALLBACK
,
61 WINED3D_CS_OP_QUERY_ISSUE
,
62 WINED3D_CS_OP_PRELOAD_RESOURCE
,
63 WINED3D_CS_OP_UNLOAD_RESOURCE
,
68 struct wined3d_cs_present
70 enum wined3d_cs_op opcode
;
71 HWND dst_window_override
;
72 struct wined3d_swapchain
*swapchain
;
78 struct wined3d_cs_clear
80 enum wined3d_cs_op opcode
;
82 struct wined3d_color color
;
85 unsigned int rect_count
;
89 struct wined3d_cs_dispatch
91 enum wined3d_cs_op opcode
;
92 unsigned int group_count_x
;
93 unsigned int group_count_y
;
94 unsigned int group_count_z
;
97 struct wined3d_cs_draw
99 enum wined3d_cs_op opcode
;
101 unsigned int start_idx
;
102 unsigned int index_count
;
103 unsigned int start_instance
;
104 unsigned int instance_count
;
108 struct wined3d_cs_set_predication
110 enum wined3d_cs_op opcode
;
111 struct wined3d_query
*predicate
;
115 struct wined3d_cs_set_viewport
117 enum wined3d_cs_op opcode
;
118 struct wined3d_viewport viewport
;
121 struct wined3d_cs_set_scissor_rect
123 enum wined3d_cs_op opcode
;
127 struct wined3d_cs_set_rendertarget_view
129 enum wined3d_cs_op opcode
;
130 unsigned int view_idx
;
131 struct wined3d_rendertarget_view
*view
;
134 struct wined3d_cs_set_depth_stencil_view
136 enum wined3d_cs_op opcode
;
137 struct wined3d_rendertarget_view
*view
;
140 struct wined3d_cs_set_vertex_declaration
142 enum wined3d_cs_op opcode
;
143 struct wined3d_vertex_declaration
*declaration
;
146 struct wined3d_cs_set_stream_source
148 enum wined3d_cs_op opcode
;
150 struct wined3d_buffer
*buffer
;
155 struct wined3d_cs_set_stream_source_freq
157 enum wined3d_cs_op opcode
;
163 struct wined3d_cs_set_stream_output
165 enum wined3d_cs_op opcode
;
167 struct wined3d_buffer
*buffer
;
171 struct wined3d_cs_set_index_buffer
173 enum wined3d_cs_op opcode
;
174 struct wined3d_buffer
*buffer
;
175 enum wined3d_format_id format_id
;
179 struct wined3d_cs_set_constant_buffer
181 enum wined3d_cs_op opcode
;
182 enum wined3d_shader_type type
;
184 struct wined3d_buffer
*buffer
;
187 struct wined3d_cs_set_texture
189 enum wined3d_cs_op opcode
;
191 struct wined3d_texture
*texture
;
194 struct wined3d_cs_set_color_key
196 enum wined3d_cs_op opcode
;
197 struct wined3d_texture
*texture
;
200 struct wined3d_color_key color_key
;
203 struct wined3d_cs_set_shader_resource_view
205 enum wined3d_cs_op opcode
;
206 enum wined3d_shader_type type
;
208 struct wined3d_shader_resource_view
*view
;
211 struct wined3d_cs_set_unordered_access_view
213 enum wined3d_cs_op opcode
;
214 enum wined3d_pipeline pipeline
;
215 unsigned int view_idx
;
216 struct wined3d_unordered_access_view
*view
;
219 struct wined3d_cs_set_sampler
221 enum wined3d_cs_op opcode
;
222 enum wined3d_shader_type type
;
224 struct wined3d_sampler
*sampler
;
227 struct wined3d_cs_set_shader
229 enum wined3d_cs_op opcode
;
230 enum wined3d_shader_type type
;
231 struct wined3d_shader
*shader
;
234 struct wined3d_cs_set_rasterizer_state
236 enum wined3d_cs_op opcode
;
237 struct wined3d_rasterizer_state
*state
;
240 struct wined3d_cs_set_render_state
242 enum wined3d_cs_op opcode
;
243 enum wined3d_render_state state
;
247 struct wined3d_cs_set_texture_state
249 enum wined3d_cs_op opcode
;
251 enum wined3d_texture_stage_state state
;
255 struct wined3d_cs_set_sampler_state
257 enum wined3d_cs_op opcode
;
259 enum wined3d_sampler_state state
;
263 struct wined3d_cs_set_transform
265 enum wined3d_cs_op opcode
;
266 enum wined3d_transform_state state
;
267 struct wined3d_matrix matrix
;
270 struct wined3d_cs_set_clip_plane
272 enum wined3d_cs_op opcode
;
274 struct wined3d_vec4 plane
;
277 struct wined3d_cs_set_material
279 enum wined3d_cs_op opcode
;
280 struct wined3d_material material
;
283 struct wined3d_cs_set_light
285 enum wined3d_cs_op opcode
;
286 struct wined3d_light_info light
;
289 struct wined3d_cs_set_light_enable
291 enum wined3d_cs_op opcode
;
296 struct wined3d_cs_reset_state
298 enum wined3d_cs_op opcode
;
301 struct wined3d_cs_callback
303 enum wined3d_cs_op opcode
;
304 void (*callback
)(void *object
);
308 struct wined3d_cs_query_issue
310 enum wined3d_cs_op opcode
;
311 struct wined3d_query
*query
;
315 struct wined3d_cs_preload_resource
317 enum wined3d_cs_op opcode
;
318 struct wined3d_resource
*resource
;
321 struct wined3d_cs_unload_resource
323 enum wined3d_cs_op opcode
;
324 struct wined3d_resource
*resource
;
327 struct wined3d_cs_map
329 enum wined3d_cs_op opcode
;
330 struct wined3d_resource
*resource
;
331 unsigned int sub_resource_idx
;
332 struct wined3d_map_desc
*map_desc
;
333 const struct wined3d_box
*box
;
338 struct wined3d_cs_unmap
340 enum wined3d_cs_op opcode
;
341 struct wined3d_resource
*resource
;
342 unsigned int sub_resource_idx
;
346 static void wined3d_cs_exec_present(struct wined3d_cs
*cs
, const void *data
)
348 const struct wined3d_cs_present
*op
= data
;
349 struct wined3d_swapchain
*swapchain
;
352 swapchain
= op
->swapchain
;
353 wined3d_swapchain_set_window(swapchain
, op
->dst_window_override
);
355 swapchain
->swapchain_ops
->swapchain_present(swapchain
, &op
->src_rect
, &op
->dst_rect
, op
->flags
);
357 wined3d_resource_release(&swapchain
->front_buffer
->resource
);
358 for (i
= 0; i
< swapchain
->desc
.backbuffer_count
; ++i
)
360 wined3d_resource_release(&swapchain
->back_buffers
[i
]->resource
);
364 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
365 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
, DWORD flags
)
367 struct wined3d_cs_present
*op
;
370 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
371 op
->opcode
= WINED3D_CS_OP_PRESENT
;
372 op
->dst_window_override
= dst_window_override
;
373 op
->swapchain
= swapchain
;
374 op
->src_rect
= *src_rect
;
375 op
->dst_rect
= *dst_rect
;
378 wined3d_resource_acquire(&swapchain
->front_buffer
->resource
);
379 for (i
= 0; i
< swapchain
->desc
.backbuffer_count
; ++i
)
381 wined3d_resource_acquire(&swapchain
->back_buffers
[i
]->resource
);
387 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
389 const struct wined3d_cs_clear
*op
= data
;
390 const struct wined3d_state
*state
;
391 struct wined3d_device
*device
;
396 state
= &device
->state
;
397 wined3d_get_draw_rect(state
, &draw_rect
);
398 device_clear_render_targets(device
, device
->adapter
->gl_info
.limits
.buffers
,
399 &device
->fb
, op
->rect_count
, op
->rects
, &draw_rect
, op
->flags
,
400 &op
->color
, op
->depth
, op
->stencil
);
402 if (op
->flags
& WINED3DCLEAR_TARGET
)
404 for (i
= 0; i
< device
->adapter
->gl_info
.limits
.buffers
; ++i
)
406 if (state
->fb
->render_targets
[i
])
407 wined3d_resource_release(state
->fb
->render_targets
[i
]->resource
);
410 if (op
->flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
411 wined3d_resource_release(state
->fb
->depth_stencil
->resource
);
414 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
415 DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
417 const struct wined3d_state
*state
= &cs
->device
->state
;
418 struct wined3d_cs_clear
*op
;
421 op
= cs
->ops
->require_space(cs
, FIELD_OFFSET(struct wined3d_cs_clear
, rects
[rect_count
]));
422 op
->opcode
= WINED3D_CS_OP_CLEAR
;
426 op
->stencil
= stencil
;
427 op
->rect_count
= rect_count
;
428 memcpy(op
->rects
, rects
, sizeof(*rects
) * rect_count
);
430 if (flags
& WINED3DCLEAR_TARGET
)
432 for (i
= 0; i
< cs
->device
->adapter
->gl_info
.limits
.buffers
; ++i
)
434 if (state
->fb
->render_targets
[i
])
435 wined3d_resource_acquire(state
->fb
->render_targets
[i
]->resource
);
438 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
439 wined3d_resource_acquire(state
->fb
->depth_stencil
->resource
);
444 static void acquire_shader_resources(const struct wined3d_state
*state
, unsigned int shader_mask
)
446 struct wined3d_shader_sampler_map_entry
*entry
;
447 struct wined3d_shader_resource_view
*view
;
448 struct wined3d_shader
*shader
;
451 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
453 if (!(shader_mask
& (1u << i
)))
456 if (!(shader
= state
->shader
[i
]))
459 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
462 wined3d_resource_acquire(&state
->cb
[i
][j
]->resource
);
465 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
467 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
469 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
472 wined3d_resource_acquire(view
->resource
);
477 static void release_shader_resources(const struct wined3d_state
*state
, unsigned int shader_mask
)
479 struct wined3d_shader_sampler_map_entry
*entry
;
480 struct wined3d_shader_resource_view
*view
;
481 struct wined3d_shader
*shader
;
484 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
486 if (!(shader_mask
& (1u << i
)))
489 if (!(shader
= state
->shader
[i
]))
492 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
495 wined3d_resource_release(&state
->cb
[i
][j
]->resource
);
498 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
500 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
502 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
505 wined3d_resource_release(view
->resource
);
510 static void acquire_unordered_access_resources(const struct wined3d_shader
*shader
,
511 struct wined3d_unordered_access_view
* const *views
)
518 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
520 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
526 wined3d_resource_acquire(views
[i
]->resource
);
530 static void release_unordered_access_resources(const struct wined3d_shader
*shader
,
531 struct wined3d_unordered_access_view
* const *views
)
538 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
540 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
546 wined3d_resource_release(views
[i
]->resource
);
550 static void wined3d_cs_exec_dispatch(struct wined3d_cs
*cs
, const void *data
)
552 struct wined3d_state
*state
= &cs
->device
->state
;
553 const struct wined3d_cs_dispatch
*op
= data
;
555 dispatch_compute(cs
->device
, state
,
556 op
->group_count_x
, op
->group_count_y
, op
->group_count_z
);
558 release_shader_resources(state
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
559 release_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
560 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
563 void wined3d_cs_emit_dispatch(struct wined3d_cs
*cs
,
564 unsigned int group_count_x
, unsigned int group_count_y
, unsigned int group_count_z
)
566 const struct wined3d_state
*state
= &cs
->device
->state
;
567 struct wined3d_cs_dispatch
*op
;
569 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
570 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
571 op
->group_count_x
= group_count_x
;
572 op
->group_count_y
= group_count_y
;
573 op
->group_count_z
= group_count_z
;
575 acquire_shader_resources(state
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
576 acquire_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
577 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
582 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
584 struct wined3d_state
*state
= &cs
->device
->state
;
585 const struct wined3d_cs_draw
*op
= data
;
588 if (!cs
->device
->adapter
->gl_info
.supported
[ARB_DRAW_ELEMENTS_BASE_VERTEX
]
589 && state
->load_base_vertex_index
!= op
->base_vertex_idx
)
591 state
->load_base_vertex_index
= op
->base_vertex_idx
;
592 device_invalidate_state(cs
->device
, STATE_BASEVERTEXINDEX
);
595 draw_primitive(cs
->device
, state
, op
->base_vertex_idx
, op
->start_idx
,
596 op
->index_count
, op
->start_instance
, op
->instance_count
, op
->indexed
);
599 wined3d_resource_release(&state
->index_buffer
->resource
);
600 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
602 if (state
->streams
[i
].buffer
)
603 wined3d_resource_release(&state
->streams
[i
].buffer
->resource
);
605 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
607 if (state
->textures
[i
])
608 wined3d_resource_release(&state
->textures
[i
]->resource
);
610 for (i
= 0; i
< cs
->device
->adapter
->gl_info
.limits
.buffers
; ++i
)
612 if (state
->fb
->render_targets
[i
])
613 wined3d_resource_release(state
->fb
->render_targets
[i
]->resource
);
615 if (state
->fb
->depth_stencil
)
616 wined3d_resource_release(state
->fb
->depth_stencil
->resource
);
617 release_shader_resources(state
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
618 release_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
619 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
622 void wined3d_cs_emit_draw(struct wined3d_cs
*cs
, int base_vertex_idx
, unsigned int start_idx
,
623 unsigned int index_count
, unsigned int start_instance
, unsigned int instance_count
, BOOL indexed
)
625 const struct wined3d_state
*state
= &cs
->device
->state
;
626 struct wined3d_cs_draw
*op
;
629 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
630 op
->opcode
= WINED3D_CS_OP_DRAW
;
631 op
->base_vertex_idx
= base_vertex_idx
;
632 op
->start_idx
= start_idx
;
633 op
->index_count
= index_count
;
634 op
->start_instance
= start_instance
;
635 op
->instance_count
= instance_count
;
636 op
->indexed
= indexed
;
639 wined3d_resource_acquire(&state
->index_buffer
->resource
);
640 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
642 if (state
->streams
[i
].buffer
)
643 wined3d_resource_acquire(&state
->streams
[i
].buffer
->resource
);
645 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
647 if (state
->textures
[i
])
648 wined3d_resource_acquire(&state
->textures
[i
]->resource
);
650 for (i
= 0; i
< cs
->device
->adapter
->gl_info
.limits
.buffers
; ++i
)
652 if (state
->fb
->render_targets
[i
])
653 wined3d_resource_acquire(state
->fb
->render_targets
[i
]->resource
);
655 if (state
->fb
->depth_stencil
)
656 wined3d_resource_acquire(state
->fb
->depth_stencil
->resource
);
657 acquire_shader_resources(state
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
658 acquire_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
659 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
664 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
666 const struct wined3d_cs_set_predication
*op
= data
;
668 cs
->state
.predicate
= op
->predicate
;
669 cs
->state
.predicate_value
= op
->value
;
672 void wined3d_cs_emit_set_predication(struct wined3d_cs
*cs
, struct wined3d_query
*predicate
, BOOL value
)
674 struct wined3d_cs_set_predication
*op
;
676 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
677 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
678 op
->predicate
= predicate
;
684 static void wined3d_cs_exec_set_viewport(struct wined3d_cs
*cs
, const void *data
)
686 const struct wined3d_cs_set_viewport
*op
= data
;
688 cs
->state
.viewport
= op
->viewport
;
689 device_invalidate_state(cs
->device
, STATE_VIEWPORT
);
692 void wined3d_cs_emit_set_viewport(struct wined3d_cs
*cs
, const struct wined3d_viewport
*viewport
)
694 struct wined3d_cs_set_viewport
*op
;
696 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
697 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORT
;
698 op
->viewport
= *viewport
;
703 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs
*cs
, const void *data
)
705 const struct wined3d_cs_set_scissor_rect
*op
= data
;
707 cs
->state
.scissor_rect
= op
->rect
;
708 device_invalidate_state(cs
->device
, STATE_SCISSORRECT
);
711 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs
*cs
, const RECT
*rect
)
713 struct wined3d_cs_set_scissor_rect
*op
;
715 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
716 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECT
;
722 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs
*cs
, const void *data
)
724 const struct wined3d_cs_set_rendertarget_view
*op
= data
;
726 cs
->state
.fb
->render_targets
[op
->view_idx
] = op
->view
;
727 device_invalidate_state(cs
->device
, STATE_FRAMEBUFFER
);
730 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs
*cs
, unsigned int view_idx
,
731 struct wined3d_rendertarget_view
*view
)
733 struct wined3d_cs_set_rendertarget_view
*op
;
735 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
736 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEW
;
737 op
->view_idx
= view_idx
;
743 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
745 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
746 struct wined3d_device
*device
= cs
->device
;
747 struct wined3d_rendertarget_view
*prev
;
749 if ((prev
= cs
->state
.fb
->depth_stencil
))
751 struct wined3d_surface
*prev_surface
= wined3d_rendertarget_view_get_surface(prev
);
753 if (prev_surface
&& (device
->swapchains
[0]->desc
.flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
754 || prev_surface
->container
->flags
& WINED3D_TEXTURE_DISCARD
))
756 wined3d_texture_validate_location(prev_surface
->container
,
757 prev
->sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
761 cs
->fb
.depth_stencil
= op
->view
;
763 if (!prev
!= !op
->view
)
765 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
766 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_ZENABLE
));
767 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILENABLE
));
768 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK
));
769 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
771 else if (prev
&& (prev
->format_flags
& WINED3DFMT_FLAG_FLOAT
)
772 != (op
->view
->format_flags
& WINED3DFMT_FLAG_FLOAT
))
774 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
777 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
780 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs
*cs
, struct wined3d_rendertarget_view
*view
)
782 struct wined3d_cs_set_depth_stencil_view
*op
;
784 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
785 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
791 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
793 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
795 cs
->state
.vertex_declaration
= op
->declaration
;
796 device_invalidate_state(cs
->device
, STATE_VDECL
);
799 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs
*cs
, struct wined3d_vertex_declaration
*declaration
)
801 struct wined3d_cs_set_vertex_declaration
*op
;
803 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
804 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
805 op
->declaration
= declaration
;
810 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs
*cs
, const void *data
)
812 const struct wined3d_cs_set_stream_source
*op
= data
;
813 struct wined3d_stream_state
*stream
;
814 struct wined3d_buffer
*prev
;
816 stream
= &cs
->state
.streams
[op
->stream_idx
];
817 prev
= stream
->buffer
;
818 stream
->buffer
= op
->buffer
;
819 stream
->offset
= op
->offset
;
820 stream
->stride
= op
->stride
;
823 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
825 InterlockedDecrement(&prev
->resource
.bind_count
);
827 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
830 void wined3d_cs_emit_set_stream_source(struct wined3d_cs
*cs
, UINT stream_idx
,
831 struct wined3d_buffer
*buffer
, UINT offset
, UINT stride
)
833 struct wined3d_cs_set_stream_source
*op
;
835 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
836 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE
;
837 op
->stream_idx
= stream_idx
;
845 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs
*cs
, const void *data
)
847 const struct wined3d_cs_set_stream_source_freq
*op
= data
;
848 struct wined3d_stream_state
*stream
;
850 stream
= &cs
->state
.streams
[op
->stream_idx
];
851 stream
->frequency
= op
->frequency
;
852 stream
->flags
= op
->flags
;
854 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
857 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs
*cs
, UINT stream_idx
, UINT frequency
, UINT flags
)
859 struct wined3d_cs_set_stream_source_freq
*op
;
861 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
862 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
;
863 op
->stream_idx
= stream_idx
;
864 op
->frequency
= frequency
;
870 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs
*cs
, const void *data
)
872 const struct wined3d_cs_set_stream_output
*op
= data
;
873 struct wined3d_stream_output
*stream
;
874 struct wined3d_buffer
*prev
;
876 stream
= &cs
->state
.stream_output
[op
->stream_idx
];
877 prev
= stream
->buffer
;
878 stream
->buffer
= op
->buffer
;
879 stream
->offset
= op
->offset
;
882 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
884 InterlockedDecrement(&prev
->resource
.bind_count
);
887 void wined3d_cs_emit_set_stream_output(struct wined3d_cs
*cs
, UINT stream_idx
,
888 struct wined3d_buffer
*buffer
, UINT offset
)
890 struct wined3d_cs_set_stream_output
*op
;
892 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
893 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUT
;
894 op
->stream_idx
= stream_idx
;
901 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
903 const struct wined3d_cs_set_index_buffer
*op
= data
;
904 struct wined3d_buffer
*prev
;
906 prev
= cs
->state
.index_buffer
;
907 cs
->state
.index_buffer
= op
->buffer
;
908 cs
->state
.index_format
= op
->format_id
;
909 cs
->state
.index_offset
= op
->offset
;
912 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
914 InterlockedDecrement(&prev
->resource
.bind_count
);
916 device_invalidate_state(cs
->device
, STATE_INDEXBUFFER
);
919 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs
*cs
, struct wined3d_buffer
*buffer
,
920 enum wined3d_format_id format_id
, unsigned int offset
)
922 struct wined3d_cs_set_index_buffer
*op
;
924 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
925 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
927 op
->format_id
= format_id
;
933 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs
*cs
, const void *data
)
935 const struct wined3d_cs_set_constant_buffer
*op
= data
;
936 struct wined3d_buffer
*prev
;
938 prev
= cs
->state
.cb
[op
->type
][op
->cb_idx
];
939 cs
->state
.cb
[op
->type
][op
->cb_idx
] = op
->buffer
;
942 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
944 InterlockedDecrement(&prev
->resource
.bind_count
);
946 device_invalidate_state(cs
->device
, STATE_CONSTANT_BUFFER(op
->type
));
949 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
950 UINT cb_idx
, struct wined3d_buffer
*buffer
)
952 struct wined3d_cs_set_constant_buffer
*op
;
954 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
955 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFER
;
963 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
965 const struct wined3d_gl_info
*gl_info
= &cs
->device
->adapter
->gl_info
;
966 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
967 const struct wined3d_cs_set_texture
*op
= data
;
968 struct wined3d_texture
*prev
;
969 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
971 prev
= cs
->state
.textures
[op
->stage
];
972 cs
->state
.textures
[op
->stage
] = op
->texture
;
976 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
977 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
978 unsigned int old_fmt_flags
= prev
? prev
->resource
.format_flags
: 0;
979 unsigned int new_fmt_flags
= op
->texture
->resource
.format_flags
;
981 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
982 op
->texture
->sampler
= op
->stage
;
984 if (!prev
|| op
->texture
->target
!= prev
->target
985 || (!is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
986 && !(can_use_texture_swizzle(gl_info
, new_format
) && can_use_texture_swizzle(gl_info
, old_format
)))
987 || (new_fmt_flags
& WINED3DFMT_FLAG_SHADOW
) != (old_fmt_flags
& WINED3DFMT_FLAG_SHADOW
))
988 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
990 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
992 /* The source arguments for color and alpha ops have different
993 * meanings when a NULL texture is bound, so the COLOR_OP and
994 * ALPHA_OP have to be dirtified. */
995 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
996 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
999 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1000 new_use_color_key
= TRUE
;
1005 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
1009 /* Search for other stages the texture is bound to. Shouldn't
1010 * happen if applications bind textures to a single stage only. */
1011 TRACE("Searching for other stages the texture is bound to.\n");
1012 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
1014 if (cs
->state
.textures
[i
] == prev
)
1016 TRACE("Texture is also bound to stage %u.\n", i
);
1023 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1025 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1026 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1029 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1030 old_use_color_key
= TRUE
;
1033 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->stage
));
1035 if (new_use_color_key
!= old_use_color_key
)
1036 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1038 if (new_use_color_key
)
1039 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
1042 void wined3d_cs_emit_set_texture(struct wined3d_cs
*cs
, UINT stage
, struct wined3d_texture
*texture
)
1044 struct wined3d_cs_set_texture
*op
;
1046 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1047 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
1049 op
->texture
= texture
;
1051 cs
->ops
->submit(cs
);
1054 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs
*cs
, const void *data
)
1056 const struct wined3d_cs_set_shader_resource_view
*op
= data
;
1057 struct wined3d_shader_resource_view
*prev
;
1059 prev
= cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
];
1060 cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
] = op
->view
;
1063 InterlockedIncrement(&op
->view
->resource
->bind_count
);
1065 InterlockedDecrement(&prev
->resource
->bind_count
);
1067 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1068 device_invalidate_state(cs
->device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1070 device_invalidate_state(cs
->device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1073 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
1074 UINT view_idx
, struct wined3d_shader_resource_view
*view
)
1076 struct wined3d_cs_set_shader_resource_view
*op
;
1078 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1079 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
;
1081 op
->view_idx
= view_idx
;
1084 cs
->ops
->submit(cs
);
1087 static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
1089 const struct wined3d_cs_set_unordered_access_view
*op
= data
;
1090 struct wined3d_unordered_access_view
*prev
;
1092 prev
= cs
->state
.unordered_access_view
[op
->pipeline
][op
->view_idx
];
1093 cs
->state
.unordered_access_view
[op
->pipeline
][op
->view_idx
] = op
->view
;
1096 InterlockedIncrement(&op
->view
->resource
->bind_count
);
1098 InterlockedDecrement(&prev
->resource
->bind_count
);
1100 device_invalidate_state(cs
->device
, STATE_UNORDERED_ACCESS_VIEW_BINDING(op
->pipeline
));
1103 void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs
*cs
, enum wined3d_pipeline pipeline
,
1104 unsigned int view_idx
, struct wined3d_unordered_access_view
*view
)
1106 struct wined3d_cs_set_unordered_access_view
*op
;
1108 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1109 op
->opcode
= WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW
;
1110 op
->pipeline
= pipeline
;
1111 op
->view_idx
= view_idx
;
1114 cs
->ops
->submit(cs
);
1117 static void wined3d_cs_exec_set_sampler(struct wined3d_cs
*cs
, const void *data
)
1119 const struct wined3d_cs_set_sampler
*op
= data
;
1121 cs
->state
.sampler
[op
->type
][op
->sampler_idx
] = op
->sampler
;
1122 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1123 device_invalidate_state(cs
->device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1125 device_invalidate_state(cs
->device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1128 void wined3d_cs_emit_set_sampler(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
1129 UINT sampler_idx
, struct wined3d_sampler
*sampler
)
1131 struct wined3d_cs_set_sampler
*op
;
1133 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1134 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER
;
1136 op
->sampler_idx
= sampler_idx
;
1137 op
->sampler
= sampler
;
1139 cs
->ops
->submit(cs
);
1142 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
1144 const struct wined3d_cs_set_shader
*op
= data
;
1146 cs
->state
.shader
[op
->type
] = op
->shader
;
1147 device_invalidate_state(cs
->device
, STATE_SHADER(op
->type
));
1148 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1149 device_invalidate_state(cs
->device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1151 device_invalidate_state(cs
->device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1154 void wined3d_cs_emit_set_shader(struct wined3d_cs
*cs
, enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
1156 struct wined3d_cs_set_shader
*op
;
1158 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1159 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
1161 op
->shader
= shader
;
1163 cs
->ops
->submit(cs
);
1166 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs
*cs
, const void *data
)
1168 const struct wined3d_cs_set_rasterizer_state
*op
= data
;
1170 cs
->state
.rasterizer_state
= op
->state
;
1171 device_invalidate_state(cs
->device
, STATE_FRONTFACE
);
1174 void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs
*cs
,
1175 struct wined3d_rasterizer_state
*rasterizer_state
)
1177 struct wined3d_cs_set_rasterizer_state
*op
;
1179 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1180 op
->opcode
= WINED3D_CS_OP_SET_RASTERIZER_STATE
;
1181 op
->state
= rasterizer_state
;
1183 cs
->ops
->submit(cs
);
1186 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
1188 const struct wined3d_cs_set_render_state
*op
= data
;
1190 cs
->state
.render_states
[op
->state
] = op
->value
;
1191 device_invalidate_state(cs
->device
, STATE_RENDER(op
->state
));
1194 void wined3d_cs_emit_set_render_state(struct wined3d_cs
*cs
, enum wined3d_render_state state
, DWORD value
)
1196 struct wined3d_cs_set_render_state
*op
;
1198 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1199 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
1203 cs
->ops
->submit(cs
);
1206 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
1208 const struct wined3d_cs_set_texture_state
*op
= data
;
1210 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
1211 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
1214 void wined3d_cs_emit_set_texture_state(struct wined3d_cs
*cs
, UINT stage
,
1215 enum wined3d_texture_stage_state state
, DWORD value
)
1217 struct wined3d_cs_set_texture_state
*op
;
1219 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1220 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
1225 cs
->ops
->submit(cs
);
1228 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
1230 const struct wined3d_cs_set_sampler_state
*op
= data
;
1232 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
1233 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->sampler_idx
));
1236 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs
*cs
, UINT sampler_idx
,
1237 enum wined3d_sampler_state state
, DWORD value
)
1239 struct wined3d_cs_set_sampler_state
*op
;
1241 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1242 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
1243 op
->sampler_idx
= sampler_idx
;
1247 cs
->ops
->submit(cs
);
1250 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
1252 const struct wined3d_cs_set_transform
*op
= data
;
1254 cs
->state
.transforms
[op
->state
] = op
->matrix
;
1255 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
1256 device_invalidate_state(cs
->device
, STATE_TRANSFORM(op
->state
));
1259 void wined3d_cs_emit_set_transform(struct wined3d_cs
*cs
, enum wined3d_transform_state state
,
1260 const struct wined3d_matrix
*matrix
)
1262 struct wined3d_cs_set_transform
*op
;
1264 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1265 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
1267 op
->matrix
= *matrix
;
1269 cs
->ops
->submit(cs
);
1272 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
1274 const struct wined3d_cs_set_clip_plane
*op
= data
;
1276 cs
->state
.clip_planes
[op
->plane_idx
] = op
->plane
;
1277 device_invalidate_state(cs
->device
, STATE_CLIPPLANE(op
->plane_idx
));
1280 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs
*cs
, UINT plane_idx
, const struct wined3d_vec4
*plane
)
1282 struct wined3d_cs_set_clip_plane
*op
;
1284 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1285 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
1286 op
->plane_idx
= plane_idx
;
1289 cs
->ops
->submit(cs
);
1292 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
1294 const struct wined3d_cs_set_color_key
*op
= data
;
1295 struct wined3d_texture
*texture
= op
->texture
;
1301 case WINED3D_CKEY_DST_BLT
:
1302 texture
->async
.dst_blt_color_key
= op
->color_key
;
1303 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
1306 case WINED3D_CKEY_DST_OVERLAY
:
1307 texture
->async
.dst_overlay_color_key
= op
->color_key
;
1308 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
1311 case WINED3D_CKEY_SRC_BLT
:
1312 if (texture
== cs
->state
.textures
[0])
1314 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
1315 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
1316 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1319 texture
->async
.src_blt_color_key
= op
->color_key
;
1320 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
1323 case WINED3D_CKEY_SRC_OVERLAY
:
1324 texture
->async
.src_overlay_color_key
= op
->color_key
;
1325 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
1333 case WINED3D_CKEY_DST_BLT
:
1334 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
1337 case WINED3D_CKEY_DST_OVERLAY
:
1338 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
1341 case WINED3D_CKEY_SRC_BLT
:
1342 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1343 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1345 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
1348 case WINED3D_CKEY_SRC_OVERLAY
:
1349 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
1355 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
1356 WORD flags
, const struct wined3d_color_key
*color_key
)
1358 struct wined3d_cs_set_color_key
*op
;
1360 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1361 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
1362 op
->texture
= texture
;
1366 op
->color_key
= *color_key
;
1372 cs
->ops
->submit(cs
);
1375 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
1377 const struct wined3d_cs_set_material
*op
= data
;
1379 cs
->state
.material
= op
->material
;
1380 device_invalidate_state(cs
->device
, STATE_MATERIAL
);
1383 void wined3d_cs_emit_set_material(struct wined3d_cs
*cs
, const struct wined3d_material
*material
)
1385 struct wined3d_cs_set_material
*op
;
1387 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1388 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
1389 op
->material
= *material
;
1391 cs
->ops
->submit(cs
);
1394 static void wined3d_cs_exec_set_light(struct wined3d_cs
*cs
, const void *data
)
1396 const struct wined3d_cs_set_light
*op
= data
;
1397 struct wined3d_light_info
*light_info
;
1398 unsigned int light_idx
, hash_idx
;
1400 light_idx
= op
->light
.OriginalIndex
;
1402 if (!(light_info
= wined3d_state_get_light(&cs
->state
, light_idx
)))
1404 TRACE("Adding new light.\n");
1405 if (!(light_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*light_info
))))
1407 ERR("Failed to allocate light info.\n");
1411 hash_idx
= LIGHTMAP_HASHFUNC(light_idx
);
1412 list_add_head(&cs
->state
.light_map
[hash_idx
], &light_info
->entry
);
1413 light_info
->glIndex
= -1;
1414 light_info
->OriginalIndex
= light_idx
;
1417 if (light_info
->glIndex
!= -1)
1419 if (light_info
->OriginalParms
.type
!= op
->light
.OriginalParms
.type
)
1420 device_invalidate_state(cs
->device
, STATE_LIGHT_TYPE
);
1421 device_invalidate_state(cs
->device
, STATE_ACTIVELIGHT(light_info
->glIndex
));
1424 light_info
->OriginalParms
= op
->light
.OriginalParms
;
1425 light_info
->position
= op
->light
.position
;
1426 light_info
->direction
= op
->light
.direction
;
1427 light_info
->exponent
= op
->light
.exponent
;
1428 light_info
->cutoff
= op
->light
.cutoff
;
1431 void wined3d_cs_emit_set_light(struct wined3d_cs
*cs
, const struct wined3d_light_info
*light
)
1433 struct wined3d_cs_set_light
*op
;
1435 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1436 op
->opcode
= WINED3D_CS_OP_SET_LIGHT
;
1439 cs
->ops
->submit(cs
);
1442 static void wined3d_cs_exec_set_light_enable(struct wined3d_cs
*cs
, const void *data
)
1444 const struct wined3d_cs_set_light_enable
*op
= data
;
1445 struct wined3d_device
*device
= cs
->device
;
1446 struct wined3d_light_info
*light_info
;
1449 if (!(light_info
= wined3d_state_get_light(&cs
->state
, op
->idx
)))
1451 ERR("Light doesn't exist.\n");
1455 prev_idx
= light_info
->glIndex
;
1456 wined3d_state_enable_light(&cs
->state
, &device
->adapter
->d3d_info
, light_info
, op
->enable
);
1457 if (light_info
->glIndex
!= prev_idx
)
1459 device_invalidate_state(device
, STATE_LIGHT_TYPE
);
1460 device_invalidate_state(device
, STATE_ACTIVELIGHT(op
->enable
? light_info
->glIndex
: prev_idx
));
1464 void wined3d_cs_emit_set_light_enable(struct wined3d_cs
*cs
, unsigned int idx
, BOOL enable
)
1466 struct wined3d_cs_set_light_enable
*op
;
1468 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1469 op
->opcode
= WINED3D_CS_OP_SET_LIGHT_ENABLE
;
1471 op
->enable
= enable
;
1473 cs
->ops
->submit(cs
);
1476 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
1478 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
1480 state_cleanup(&cs
->state
);
1481 memset(&cs
->state
, 0, sizeof(cs
->state
));
1482 state_init(&cs
->state
, &cs
->fb
, &adapter
->gl_info
, &adapter
->d3d_info
,
1483 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
);
1486 void wined3d_cs_emit_reset_state(struct wined3d_cs
*cs
)
1488 struct wined3d_cs_reset_state
*op
;
1490 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1491 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
1493 cs
->ops
->submit(cs
);
1496 static void wined3d_cs_exec_callback(struct wined3d_cs
*cs
, const void *data
)
1498 const struct wined3d_cs_callback
*op
= data
;
1500 op
->callback(op
->object
);
1503 static void wined3d_cs_emit_callback(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
1505 struct wined3d_cs_callback
*op
;
1507 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1508 op
->opcode
= WINED3D_CS_OP_CALLBACK
;
1509 op
->callback
= callback
;
1510 op
->object
= object
;
1512 cs
->ops
->submit(cs
);
1515 void wined3d_cs_destroy_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
1517 wined3d_cs_emit_callback(cs
, callback
, object
);
1520 void wined3d_cs_init_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
1522 wined3d_cs_emit_callback(cs
, callback
, object
);
1525 static void wined3d_cs_exec_query_issue(struct wined3d_cs
*cs
, const void *data
)
1527 const struct wined3d_cs_query_issue
*op
= data
;
1528 struct wined3d_query
*query
= op
->query
;
1530 query
->query_ops
->query_issue(query
, op
->flags
);
1533 void wined3d_cs_emit_query_issue(struct wined3d_cs
*cs
, struct wined3d_query
*query
, DWORD flags
)
1535 struct wined3d_cs_query_issue
*op
;
1537 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1538 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
1542 cs
->ops
->submit(cs
);
1545 static void wined3d_cs_exec_preload_resource(struct wined3d_cs
*cs
, const void *data
)
1547 const struct wined3d_cs_preload_resource
*op
= data
;
1548 struct wined3d_resource
*resource
= op
->resource
;
1550 resource
->resource_ops
->resource_preload(resource
);
1551 wined3d_resource_release(resource
);
1554 void wined3d_cs_emit_preload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
1556 struct wined3d_cs_preload_resource
*op
;
1558 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1559 op
->opcode
= WINED3D_CS_OP_PRELOAD_RESOURCE
;
1560 op
->resource
= resource
;
1562 wined3d_resource_acquire(resource
);
1564 cs
->ops
->submit(cs
);
1567 static void wined3d_cs_exec_unload_resource(struct wined3d_cs
*cs
, const void *data
)
1569 const struct wined3d_cs_unload_resource
*op
= data
;
1570 struct wined3d_resource
*resource
= op
->resource
;
1572 resource
->resource_ops
->resource_unload(resource
);
1573 wined3d_resource_release(resource
);
1576 void wined3d_cs_emit_unload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
1578 struct wined3d_cs_unload_resource
*op
;
1580 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1581 op
->opcode
= WINED3D_CS_OP_UNLOAD_RESOURCE
;
1582 op
->resource
= resource
;
1584 wined3d_resource_acquire(resource
);
1586 cs
->ops
->submit(cs
);
1589 static void wined3d_cs_exec_map(struct wined3d_cs
*cs
, const void *data
)
1591 const struct wined3d_cs_map
*op
= data
;
1592 struct wined3d_resource
*resource
= op
->resource
;
1594 *op
->hr
= resource
->resource_ops
->resource_sub_resource_map(resource
,
1595 op
->sub_resource_idx
, op
->map_desc
, op
->box
, op
->flags
);
1598 HRESULT
wined3d_cs_map(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
1599 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, unsigned int flags
)
1601 struct wined3d_cs_map
*op
;
1604 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1605 op
->opcode
= WINED3D_CS_OP_MAP
;
1606 op
->resource
= resource
;
1607 op
->sub_resource_idx
= sub_resource_idx
;
1608 op
->map_desc
= map_desc
;
1613 cs
->ops
->submit(cs
);
1618 static void wined3d_cs_exec_unmap(struct wined3d_cs
*cs
, const void *data
)
1620 const struct wined3d_cs_unmap
*op
= data
;
1621 struct wined3d_resource
*resource
= op
->resource
;
1623 *op
->hr
= resource
->resource_ops
->resource_sub_resource_unmap(resource
, op
->sub_resource_idx
);
1626 HRESULT
wined3d_cs_unmap(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
1628 struct wined3d_cs_unmap
*op
;
1631 op
= cs
->ops
->require_space(cs
, sizeof(*op
));
1632 op
->opcode
= WINED3D_CS_OP_UNMAP
;
1633 op
->resource
= resource
;
1634 op
->sub_resource_idx
= sub_resource_idx
;
1637 cs
->ops
->submit(cs
);
1642 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
1644 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
1645 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
1646 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch
,
1647 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
1648 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
1649 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport
,
1650 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect
,
1651 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view
,
1652 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
1653 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
1654 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source
,
1655 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq
,
1656 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output
,
1657 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
1658 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer
,
1659 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
1660 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view
,
1661 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view
,
1662 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler
,
1663 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
1664 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state
,
1665 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
1666 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
1667 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
1668 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
1669 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
1670 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
1671 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
1672 /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light
,
1673 /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable
,
1674 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
1675 /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback
,
1676 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue
,
1677 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource
,
1678 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource
,
1679 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map
,
1680 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap
,
1683 static void *wined3d_cs_st_require_space(struct wined3d_cs
*cs
, size_t size
)
1685 if (size
> (cs
->data_size
- cs
->end
))
1690 new_size
= max(size
, cs
->data_size
* 2);
1692 new_data
= HeapReAlloc(GetProcessHeap(), 0, cs
->data
, new_size
);
1694 new_data
= HeapAlloc(GetProcessHeap(), 0, new_size
);
1698 cs
->data_size
= new_size
;
1699 cs
->start
= cs
->end
= 0;
1700 cs
->data
= new_data
;
1705 return (BYTE
*)cs
->data
+ cs
->start
;
1708 static void wined3d_cs_st_submit(struct wined3d_cs
*cs
)
1710 enum wined3d_cs_op opcode
;
1716 cs
->start
= cs
->end
;
1718 opcode
= *(const enum wined3d_cs_op
*)&data
[start
];
1719 wined3d_cs_op_handlers
[opcode
](cs
, &data
[start
]);
1721 if (cs
->data
== data
)
1722 cs
->start
= cs
->end
= start
;
1724 HeapFree(GetProcessHeap(), 0, data
);
1727 static void wined3d_cs_st_push_constants(struct wined3d_cs
*cs
, enum wined3d_push_constants p
,
1728 unsigned int start_idx
, unsigned int count
, const void *constants
)
1730 struct wined3d_device
*device
= cs
->device
;
1731 unsigned int context_count
;
1741 push_constant_info
[] =
1743 /* WINED3D_PUSH_CONSTANTS_VS_F */
1744 {FIELD_OFFSET(struct wined3d_state
, vs_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_VS_F
},
1745 /* WINED3D_PUSH_CONSTANTS_PS_F */
1746 {FIELD_OFFSET(struct wined3d_state
, ps_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_PS_F
},
1747 /* WINED3D_PUSH_CONSTANTS_VS_I */
1748 {FIELD_OFFSET(struct wined3d_state
, vs_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_VS_I
},
1749 /* WINED3D_PUSH_CONSTANTS_PS_I */
1750 {FIELD_OFFSET(struct wined3d_state
, ps_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_PS_I
},
1751 /* WINED3D_PUSH_CONSTANTS_VS_B */
1752 {FIELD_OFFSET(struct wined3d_state
, vs_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_VS_B
},
1753 /* WINED3D_PUSH_CONSTANTS_PS_B */
1754 {FIELD_OFFSET(struct wined3d_state
, ps_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_PS_B
},
1757 if (p
== WINED3D_PUSH_CONSTANTS_VS_F
)
1758 device
->shader_backend
->shader_update_float_vertex_constants(device
, start_idx
, count
);
1759 else if (p
== WINED3D_PUSH_CONSTANTS_PS_F
)
1760 device
->shader_backend
->shader_update_float_pixel_constants(device
, start_idx
, count
);
1762 offset
= push_constant_info
[p
].offset
+ start_idx
* push_constant_info
[p
].size
;
1763 memcpy((BYTE
*)&cs
->state
+ offset
, constants
, count
* push_constant_info
[p
].size
);
1764 for (i
= 0, context_count
= device
->context_count
; i
< context_count
; ++i
)
1766 device
->contexts
[i
]->constant_update_mask
|= push_constant_info
[p
].mask
;
1770 static const struct wined3d_cs_ops wined3d_cs_st_ops
=
1772 wined3d_cs_st_require_space
,
1773 wined3d_cs_st_submit
,
1774 wined3d_cs_st_push_constants
,
1777 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
)
1779 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
1780 struct wined3d_cs
*cs
;
1782 if (!(cs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cs
))))
1785 if (!(cs
->fb
.render_targets
= wined3d_calloc(gl_info
->limits
.buffers
, sizeof(*cs
->fb
.render_targets
))))
1787 HeapFree(GetProcessHeap(), 0, cs
);
1791 state_init(&cs
->state
, &cs
->fb
, gl_info
, &device
->adapter
->d3d_info
,
1792 WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
);
1794 cs
->ops
= &wined3d_cs_st_ops
;
1795 cs
->device
= device
;
1797 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
1798 if (!(cs
->data
= HeapAlloc(GetProcessHeap(), 0, cs
->data_size
)))
1800 state_cleanup(&cs
->state
);
1801 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1802 HeapFree(GetProcessHeap(), 0, cs
);
1809 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
1811 state_cleanup(&cs
->state
);
1812 HeapFree(GetProcessHeap(), 0, cs
->fb
.render_targets
);
1813 HeapFree(GetProcessHeap(), 0, cs
->data
);
1814 HeapFree(GetProcessHeap(), 0, cs
);