comctl32: Use SetRect() instead of open coding it.
[wine.git] / dlls / wined3d / cs.c
blob2e5a3a6ad556ef1c548b35498b72c83e318d663d
1 /*
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
19 #include "config.h"
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
25 #define WINED3D_INITIAL_CS_SIZE 4096
27 enum wined3d_cs_op
29 WINED3D_CS_OP_PRESENT,
30 WINED3D_CS_OP_CLEAR,
31 WINED3D_CS_OP_DRAW,
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;
62 RECT src_rect;
63 RECT dst_rect;
64 DWORD flags;
67 struct wined3d_cs_clear
69 enum wined3d_cs_op opcode;
70 DWORD flags;
71 struct wined3d_color color;
72 float depth;
73 DWORD stencil;
74 unsigned int rect_count;
75 RECT rects[1];
78 struct wined3d_cs_draw
80 enum wined3d_cs_op opcode;
81 UINT start_idx;
82 UINT index_count;
83 UINT start_instance;
84 UINT instance_count;
85 BOOL indexed;
88 struct wined3d_cs_set_predication
90 enum wined3d_cs_op opcode;
91 struct wined3d_query *predicate;
92 BOOL value;
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;
104 RECT rect;
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;
129 UINT stream_idx;
130 struct wined3d_buffer *buffer;
131 UINT offset;
132 UINT stride;
135 struct wined3d_cs_set_stream_source_freq
137 enum wined3d_cs_op opcode;
138 UINT stream_idx;
139 UINT frequency;
140 UINT flags;
143 struct wined3d_cs_set_stream_output
145 enum wined3d_cs_op opcode;
146 UINT stream_idx;
147 struct wined3d_buffer *buffer;
148 UINT offset;
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;
162 UINT cb_idx;
163 struct wined3d_buffer *buffer;
166 struct wined3d_cs_set_texture
168 enum wined3d_cs_op opcode;
169 UINT stage;
170 struct wined3d_texture *texture;
173 struct wined3d_cs_set_color_key
175 enum wined3d_cs_op opcode;
176 struct wined3d_texture *texture;
177 WORD flags;
178 WORD set;
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;
186 UINT view_idx;
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;
194 UINT sampler_idx;
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;
209 DWORD value;
212 struct wined3d_cs_set_texture_state
214 enum wined3d_cs_op opcode;
215 UINT stage;
216 enum wined3d_texture_stage_state state;
217 DWORD value;
220 struct wined3d_cs_set_sampler_state
222 enum wined3d_cs_op opcode;
223 UINT sampler_idx;
224 enum wined3d_sampler_state state;
225 DWORD value;
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;
238 UINT plane_idx;
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;
275 op->flags = flags;
277 cs->ops->submit(cs);
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;
284 RECT draw_rect;
286 device = cs->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;
300 op->flags = flags;
301 op->color = *color;
302 op->depth = depth;
303 op->stencil = stencil;
304 op->rect_count = rect_count;
305 memcpy(op->rects, rects, sizeof(*rects) * rect_count);
307 cs->ops->submit(cs);
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;
331 cs->ops->submit(cs);
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;
349 op->value = value;
351 cs->ops->submit(cs);
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;
370 cs->ops->submit(cs);
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;
387 op->rect = *rect;
389 cs->ops->submit(cs);
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;
408 op->view = view;
410 cs->ops->submit(cs);
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;
460 op->view = view;
462 cs->ops->submit(cs);
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;
481 cs->ops->submit(cs);
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;
496 if (op->buffer)
497 InterlockedIncrement(&op->buffer->resource.bind_count);
498 if (prev)
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;
512 op->buffer = buffer;
513 op->offset = offset;
514 op->stride = stride;
516 cs->ops->submit(cs);
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;
539 op->flags = flags;
541 cs->ops->submit(cs);
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;
555 if (op->buffer)
556 InterlockedIncrement(&op->buffer->resource.bind_count);
557 if (prev)
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;
569 op->buffer = buffer;
570 op->offset = offset;
572 cs->ops->submit(cs);
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;
584 if (op->buffer)
585 InterlockedIncrement(&op->buffer->resource.bind_count);
586 if (prev)
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;
599 op->buffer = buffer;
600 op->format_id = format_id;
602 cs->ops->submit(cs);
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;
613 if (op->buffer)
614 InterlockedIncrement(&op->buffer->resource.bind_count);
615 if (prev)
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;
628 op->type = type;
629 op->cb_idx = cb_idx;
630 op->buffer = buffer;
632 cs->ops->submit(cs);
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;
646 if (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;
675 if (prev)
677 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
679 unsigned int i;
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);
689 prev->sampler = i;
690 break;
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;
720 op->stage = stage;
721 op->texture = texture;
723 cs->ops->submit(cs);
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;
741 op->type = type;
742 op->view_idx = view_idx;
743 op->view = view;
745 cs->ops->submit(cs);
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;
763 op->type = type;
764 op->sampler_idx = sampler_idx;
765 op->sampler = sampler;
767 cs->ops->submit(cs);
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;
785 op->type = type;
786 op->shader = shader;
788 cs->ops->submit(cs);
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;
805 op->state = state;
806 op->value = value;
808 cs->ops->submit(cs);
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;
826 op->stage = stage;
827 op->state = state;
828 op->value = value;
830 cs->ops->submit(cs);
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;
849 op->state = state;
850 op->value = value;
852 cs->ops->submit(cs);
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;
871 op->state = state;
872 op->matrix = *matrix;
874 cs->ops->submit(cs);
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;
892 op->plane = *plane;
894 cs->ops->submit(cs);
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;
902 if (op->set)
904 switch (op->flags)
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;
909 break;
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;
914 break;
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;
926 break;
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;
931 break;
934 else
936 switch (op->flags)
938 case WINED3D_CKEY_DST_BLT:
939 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
940 break;
942 case WINED3D_CKEY_DST_OVERLAY:
943 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY;
944 break;
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;
951 break;
953 case WINED3D_CKEY_SRC_OVERLAY:
954 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY;
955 break;
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;
968 op->flags = flags;
969 if (color_key)
971 op->color_key = *color_key;
972 op->set = 1;
974 else
975 op->set = 0;
977 cs->ops->submit(cs);
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;
996 cs->ops->submit(cs);
999 static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data)
1001 struct wined3d_adapter *adapter = cs->device->adapter;
1002 HRESULT hr;
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)
1055 void *new_data;
1057 size = max( size, cs->data_size * 2 );
1058 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
1059 return NULL;
1061 cs->data_size = size;
1062 cs->data = new_data;
1065 return cs->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))))
1087 return NULL;
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);
1093 return NULL;
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);
1101 return NULL;
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);
1111 return NULL;
1114 return 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);