dwrite: Keep factory reference for each layout.
[wine.git] / dlls / wined3d / cs.c
blob316ccb85c74efb425ecf2de5b61c1c0e70344ce6
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 const RECT *src_rect;
63 const RECT *dst_rect;
64 const RGNDATA *dirty_region;
65 DWORD flags;
68 struct wined3d_cs_clear
70 enum wined3d_cs_op opcode;
71 DWORD rect_count;
72 const RECT *rects;
73 DWORD flags;
74 const struct wined3d_color *color;
75 float depth;
76 DWORD stencil;
79 struct wined3d_cs_draw
81 enum wined3d_cs_op opcode;
82 UINT start_idx;
83 UINT index_count;
84 UINT start_instance;
85 UINT instance_count;
86 BOOL indexed;
89 struct wined3d_cs_set_predication
91 enum wined3d_cs_op opcode;
92 struct wined3d_query *predicate;
93 BOOL value;
96 struct wined3d_cs_set_viewport
98 enum wined3d_cs_op opcode;
99 const struct wined3d_viewport *viewport;
102 struct wined3d_cs_set_scissor_rect
104 enum wined3d_cs_op opcode;
105 const RECT *rect;
108 struct wined3d_cs_set_rendertarget_view
110 enum wined3d_cs_op opcode;
111 unsigned int view_idx;
112 struct wined3d_rendertarget_view *view;
115 struct wined3d_cs_set_depth_stencil_view
117 enum wined3d_cs_op opcode;
118 struct wined3d_rendertarget_view *view;
121 struct wined3d_cs_set_vertex_declaration
123 enum wined3d_cs_op opcode;
124 struct wined3d_vertex_declaration *declaration;
127 struct wined3d_cs_set_stream_source
129 enum wined3d_cs_op opcode;
130 UINT stream_idx;
131 struct wined3d_buffer *buffer;
132 UINT offset;
133 UINT stride;
136 struct wined3d_cs_set_stream_source_freq
138 enum wined3d_cs_op opcode;
139 UINT stream_idx;
140 UINT frequency;
141 UINT flags;
144 struct wined3d_cs_set_stream_output
146 enum wined3d_cs_op opcode;
147 UINT stream_idx;
148 struct wined3d_buffer *buffer;
149 UINT offset;
152 struct wined3d_cs_set_index_buffer
154 enum wined3d_cs_op opcode;
155 struct wined3d_buffer *buffer;
156 enum wined3d_format_id format_id;
159 struct wined3d_cs_set_constant_buffer
161 enum wined3d_cs_op opcode;
162 enum wined3d_shader_type type;
163 UINT cb_idx;
164 struct wined3d_buffer *buffer;
167 struct wined3d_cs_set_texture
169 enum wined3d_cs_op opcode;
170 UINT stage;
171 struct wined3d_texture *texture;
174 struct wined3d_cs_set_color_key
176 enum wined3d_cs_op opcode;
177 struct wined3d_texture *texture;
178 WORD flags;
179 WORD set;
180 struct wined3d_color_key color_key;
183 struct wined3d_cs_set_shader_resource_view
185 enum wined3d_cs_op opcode;
186 enum wined3d_shader_type type;
187 UINT view_idx;
188 struct wined3d_shader_resource_view *view;
191 struct wined3d_cs_set_sampler
193 enum wined3d_cs_op opcode;
194 enum wined3d_shader_type type;
195 UINT sampler_idx;
196 struct wined3d_sampler *sampler;
199 struct wined3d_cs_set_shader
201 enum wined3d_cs_op opcode;
202 enum wined3d_shader_type type;
203 struct wined3d_shader *shader;
206 struct wined3d_cs_set_render_state
208 enum wined3d_cs_op opcode;
209 enum wined3d_render_state state;
210 DWORD value;
213 struct wined3d_cs_set_texture_state
215 enum wined3d_cs_op opcode;
216 UINT stage;
217 enum wined3d_texture_stage_state state;
218 DWORD value;
221 struct wined3d_cs_set_sampler_state
223 enum wined3d_cs_op opcode;
224 UINT sampler_idx;
225 enum wined3d_sampler_state state;
226 DWORD value;
229 struct wined3d_cs_set_transform
231 enum wined3d_cs_op opcode;
232 enum wined3d_transform_state state;
233 const struct wined3d_matrix *matrix;
236 struct wined3d_cs_set_clip_plane
238 enum wined3d_cs_op opcode;
239 UINT plane_idx;
240 const struct wined3d_vec4 *plane;
243 struct wined3d_cs_set_material
245 enum wined3d_cs_op opcode;
246 const struct wined3d_material *material;
249 struct wined3d_cs_reset_state
251 enum wined3d_cs_op opcode;
254 static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
256 const struct wined3d_cs_present *op = data;
257 struct wined3d_swapchain *swapchain;
259 swapchain = op->swapchain;
260 wined3d_swapchain_set_window(swapchain, op->dst_window_override);
262 swapchain->swapchain_ops->swapchain_present(swapchain,
263 op->src_rect, op->dst_rect, op->dirty_region, op->flags);
266 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
267 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
268 const RGNDATA *dirty_region, DWORD flags)
270 struct wined3d_cs_present *op;
272 op = cs->ops->require_space(cs, sizeof(*op));
273 op->opcode = WINED3D_CS_OP_PRESENT;
274 op->dst_window_override = dst_window_override;
275 op->swapchain = swapchain;
276 op->src_rect = src_rect;
277 op->dst_rect = dst_rect;
278 op->dirty_region = dirty_region;
279 op->flags = flags;
281 cs->ops->submit(cs);
284 static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
286 const struct wined3d_cs_clear *op = data;
287 struct wined3d_device *device;
288 RECT draw_rect;
290 device = cs->device;
291 wined3d_get_draw_rect(&device->state, &draw_rect);
292 device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
293 &device->fb, op->rect_count, op->rects, &draw_rect, op->flags,
294 op->color, op->depth, op->stencil);
297 void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
298 DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
300 struct wined3d_cs_clear *op;
302 op = cs->ops->require_space(cs, sizeof(*op));
303 op->opcode = WINED3D_CS_OP_CLEAR;
304 op->rect_count = rect_count;
305 op->rects = rects;
306 op->flags = flags;
307 op->color = color;
308 op->depth = depth;
309 op->stencil = stencil;
311 cs->ops->submit(cs);
314 static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
316 const struct wined3d_cs_draw *op = data;
318 draw_primitive(cs->device, op->start_idx, op->index_count,
319 op->start_instance, op->instance_count, op->indexed);
322 void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count,
323 UINT start_instance, UINT instance_count, BOOL indexed)
325 struct wined3d_cs_draw *op;
327 op = cs->ops->require_space(cs, sizeof(*op));
328 op->opcode = WINED3D_CS_OP_DRAW;
329 op->start_idx = start_idx;
330 op->index_count = index_count;
331 op->start_instance = start_instance;
332 op->instance_count = instance_count;
333 op->indexed = indexed;
335 cs->ops->submit(cs);
338 static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data)
340 const struct wined3d_cs_set_predication *op = data;
342 cs->state.predicate = op->predicate;
343 cs->state.predicate_value = op->value;
346 void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value)
348 struct wined3d_cs_set_predication *op;
350 op = cs->ops->require_space(cs, sizeof(*op));
351 op->opcode = WINED3D_CS_OP_SET_PREDICATION;
352 op->predicate = predicate;
353 op->value = value;
355 cs->ops->submit(cs);
358 static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
360 const struct wined3d_cs_set_viewport *op = data;
362 cs->state.viewport = *op->viewport;
363 device_invalidate_state(cs->device, STATE_VIEWPORT);
366 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
368 struct wined3d_cs_set_viewport *op;
370 op = cs->ops->require_space(cs, sizeof(*op));
371 op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
372 op->viewport = viewport;
374 cs->ops->submit(cs);
377 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
379 const struct wined3d_cs_set_scissor_rect *op = data;
381 cs->state.scissor_rect = *op->rect;
382 device_invalidate_state(cs->device, STATE_SCISSORRECT);
385 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
387 struct wined3d_cs_set_scissor_rect *op;
389 op = cs->ops->require_space(cs, sizeof(*op));
390 op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
391 op->rect = rect;
393 cs->ops->submit(cs);
396 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
398 const struct wined3d_cs_set_rendertarget_view *op = data;
400 cs->state.fb->render_targets[op->view_idx] = op->view;
401 device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
404 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
405 struct wined3d_rendertarget_view *view)
407 struct wined3d_cs_set_rendertarget_view *op;
409 op = cs->ops->require_space(cs, sizeof(*op));
410 op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
411 op->view_idx = view_idx;
412 op->view = view;
414 cs->ops->submit(cs);
417 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data)
419 const struct wined3d_cs_set_depth_stencil_view *op = data;
420 struct wined3d_device *device = cs->device;
421 struct wined3d_rendertarget_view *prev;
423 if ((prev = cs->state.fb->depth_stencil))
425 struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev);
427 if (prev_surface && (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
428 || prev_surface->flags & SFLAG_DISCARD))
430 surface_modify_ds_location(prev_surface, WINED3D_LOCATION_DISCARDED, prev->width, prev->height);
431 if (prev_surface == device->onscreen_depth_stencil)
433 wined3d_texture_decref(device->onscreen_depth_stencil->container);
434 device->onscreen_depth_stencil = NULL;
439 cs->fb.depth_stencil = op->view;
441 if (!prev != !op->view)
443 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
444 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
445 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE));
446 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
447 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
449 else if (prev && (prev->format_flags & WINED3DFMT_FLAG_FLOAT)
450 != (op->view->format_flags & WINED3DFMT_FLAG_FLOAT))
452 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
455 device_invalidate_state(device, STATE_FRAMEBUFFER);
458 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view)
460 struct wined3d_cs_set_depth_stencil_view *op;
462 op = cs->ops->require_space(cs, sizeof(*op));
463 op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW;
464 op->view = view;
466 cs->ops->submit(cs);
469 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data)
471 const struct wined3d_cs_set_vertex_declaration *op = data;
473 cs->state.vertex_declaration = op->declaration;
474 device_invalidate_state(cs->device, STATE_VDECL);
477 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration)
479 struct wined3d_cs_set_vertex_declaration *op;
481 op = cs->ops->require_space(cs, sizeof(*op));
482 op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION;
483 op->declaration = declaration;
485 cs->ops->submit(cs);
488 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data)
490 const struct wined3d_cs_set_stream_source *op = data;
491 struct wined3d_stream_state *stream;
492 struct wined3d_buffer *prev;
494 stream = &cs->state.streams[op->stream_idx];
495 prev = stream->buffer;
496 stream->buffer = op->buffer;
497 stream->offset = op->offset;
498 stream->stride = op->stride;
500 if (op->buffer)
501 InterlockedIncrement(&op->buffer->resource.bind_count);
502 if (prev)
503 InterlockedDecrement(&prev->resource.bind_count);
505 device_invalidate_state(cs->device, STATE_STREAMSRC);
508 void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx,
509 struct wined3d_buffer *buffer, UINT offset, UINT stride)
511 struct wined3d_cs_set_stream_source *op;
513 op = cs->ops->require_space(cs, sizeof(*op));
514 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE;
515 op->stream_idx = stream_idx;
516 op->buffer = buffer;
517 op->offset = offset;
518 op->stride = stride;
520 cs->ops->submit(cs);
523 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data)
525 const struct wined3d_cs_set_stream_source_freq *op = data;
526 struct wined3d_stream_state *stream;
528 stream = &cs->state.streams[op->stream_idx];
529 stream->frequency = op->frequency;
530 stream->flags = op->flags;
532 device_invalidate_state(cs->device, STATE_STREAMSRC);
535 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags)
537 struct wined3d_cs_set_stream_source_freq *op;
539 op = cs->ops->require_space(cs, sizeof(*op));
540 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ;
541 op->stream_idx = stream_idx;
542 op->frequency = frequency;
543 op->flags = flags;
545 cs->ops->submit(cs);
548 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data)
550 const struct wined3d_cs_set_stream_output *op = data;
551 struct wined3d_stream_output *stream;
552 struct wined3d_buffer *prev;
554 stream = &cs->state.stream_output[op->stream_idx];
555 prev = stream->buffer;
556 stream->buffer = op->buffer;
557 stream->offset = op->offset;
559 if (op->buffer)
560 InterlockedIncrement(&op->buffer->resource.bind_count);
561 if (prev)
562 InterlockedDecrement(&prev->resource.bind_count);
565 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
566 struct wined3d_buffer *buffer, UINT offset)
568 struct wined3d_cs_set_stream_output *op;
570 op = cs->ops->require_space(cs, sizeof(*op));
571 op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT;
572 op->stream_idx = stream_idx;
573 op->buffer = buffer;
574 op->offset = offset;
576 cs->ops->submit(cs);
579 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data)
581 const struct wined3d_cs_set_index_buffer *op = data;
582 struct wined3d_buffer *prev;
584 prev = cs->state.index_buffer;
585 cs->state.index_buffer = op->buffer;
586 cs->state.index_format = op->format_id;
588 if (op->buffer)
589 InterlockedIncrement(&op->buffer->resource.bind_count);
590 if (prev)
591 InterlockedDecrement(&prev->resource.bind_count);
593 device_invalidate_state(cs->device, STATE_INDEXBUFFER);
596 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer,
597 enum wined3d_format_id format_id)
599 struct wined3d_cs_set_index_buffer *op;
601 op = cs->ops->require_space(cs, sizeof(*op));
602 op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER;
603 op->buffer = buffer;
604 op->format_id = format_id;
606 cs->ops->submit(cs);
609 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data)
611 const struct wined3d_cs_set_constant_buffer *op = data;
612 struct wined3d_buffer *prev;
614 prev = cs->state.cb[op->type][op->cb_idx];
615 cs->state.cb[op->type][op->cb_idx] = op->buffer;
617 if (op->buffer)
618 InterlockedIncrement(&op->buffer->resource.bind_count);
619 if (prev)
620 InterlockedDecrement(&prev->resource.bind_count);
622 device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type));
625 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
626 UINT cb_idx, struct wined3d_buffer *buffer)
628 struct wined3d_cs_set_constant_buffer *op;
630 op = cs->ops->require_space(cs, sizeof(*op));
631 op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER;
632 op->type = type;
633 op->cb_idx = cb_idx;
634 op->buffer = buffer;
636 cs->ops->submit(cs);
639 static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
641 const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
642 const struct wined3d_cs_set_texture *op = data;
643 struct wined3d_texture *prev;
644 BOOL old_use_color_key = FALSE, new_use_color_key = FALSE;
646 prev = cs->state.textures[op->stage];
647 cs->state.textures[op->stage] = op->texture;
649 if (op->texture)
651 const struct wined3d_format *new_format = op->texture->resource.format;
652 const struct wined3d_format *old_format = prev ? prev->resource.format : NULL;
653 unsigned int old_fmt_flags = prev ? prev->resource.format_flags : 0;
654 unsigned int new_fmt_flags = op->texture->resource.format_flags;
656 if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
657 op->texture->sampler = op->stage;
659 if (!prev || op->texture->target != prev->target
660 || !is_same_fixup(new_format->color_fixup, old_format->color_fixup)
661 || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW))
662 device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
664 if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
666 /* The source arguments for color and alpha ops have different
667 * meanings when a NULL texture is bound, so the COLOR_OP and
668 * ALPHA_OP have to be dirtified. */
669 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
670 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
673 if (!op->stage && op->texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
674 new_use_color_key = TRUE;
677 if (prev)
679 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
681 unsigned int i;
683 /* Search for other stages the texture is bound to. Shouldn't
684 * happen if applications bind textures to a single stage only. */
685 TRACE("Searching for other stages the texture is bound to.\n");
686 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
688 if (cs->state.textures[i] == prev)
690 TRACE("Texture is also bound to stage %u.\n", i);
691 prev->sampler = i;
692 break;
697 if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
699 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
700 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
703 if (!op->stage && prev->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
704 old_use_color_key = TRUE;
707 device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
709 if (new_use_color_key != old_use_color_key)
710 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
712 if (new_use_color_key)
713 device_invalidate_state(cs->device, STATE_COLOR_KEY);
716 void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
718 struct wined3d_cs_set_texture *op;
720 op = cs->ops->require_space(cs, sizeof(*op));
721 op->opcode = WINED3D_CS_OP_SET_TEXTURE;
722 op->stage = stage;
723 op->texture = texture;
725 cs->ops->submit(cs);
728 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data)
730 const struct wined3d_cs_set_shader_resource_view *op = data;
732 cs->state.shader_resource_view[op->type][op->view_idx] = op->view;
733 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
736 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type,
737 UINT view_idx, struct wined3d_shader_resource_view *view)
739 struct wined3d_cs_set_shader_resource_view *op;
741 op = cs->ops->require_space(cs, sizeof(*op));
742 op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW;
743 op->type = type;
744 op->view_idx = view_idx;
745 op->view = view;
747 cs->ops->submit(cs);
750 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
752 const struct wined3d_cs_set_sampler *op = data;
754 cs->state.sampler[op->type][op->sampler_idx] = op->sampler;
755 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
758 void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
759 UINT sampler_idx, struct wined3d_sampler *sampler)
761 struct wined3d_cs_set_sampler *op;
763 op = cs->ops->require_space(cs, sizeof(*op));
764 op->opcode = WINED3D_CS_OP_SET_SAMPLER;
765 op->type = type;
766 op->sampler_idx = sampler_idx;
767 op->sampler = sampler;
769 cs->ops->submit(cs);
772 static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data)
774 const struct wined3d_cs_set_shader *op = data;
776 cs->state.shader[op->type] = op->shader;
777 device_invalidate_state(cs->device, STATE_SHADER(op->type));
778 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
781 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader)
783 struct wined3d_cs_set_shader *op;
785 op = cs->ops->require_space(cs, sizeof(*op));
786 op->opcode = WINED3D_CS_OP_SET_SHADER;
787 op->type = type;
788 op->shader = shader;
790 cs->ops->submit(cs);
793 static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data)
795 const struct wined3d_cs_set_render_state *op = data;
797 cs->state.render_states[op->state] = op->value;
798 device_invalidate_state(cs->device, STATE_RENDER(op->state));
801 void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value)
803 struct wined3d_cs_set_render_state *op;
805 op = cs->ops->require_space(cs, sizeof(*op));
806 op->opcode = WINED3D_CS_OP_SET_RENDER_STATE;
807 op->state = state;
808 op->value = value;
810 cs->ops->submit(cs);
813 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
815 const struct wined3d_cs_set_texture_state *op = data;
817 cs->state.texture_states[op->stage][op->state] = op->value;
818 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state));
821 void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
822 enum wined3d_texture_stage_state state, DWORD value)
824 struct wined3d_cs_set_texture_state *op;
826 op = cs->ops->require_space(cs, sizeof(*op));
827 op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE;
828 op->stage = stage;
829 op->state = state;
830 op->value = value;
832 cs->ops->submit(cs);
835 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data)
837 const struct wined3d_cs_set_sampler_state *op = data;
839 cs->state.sampler_states[op->sampler_idx][op->state] = op->value;
840 device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx));
843 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
844 enum wined3d_sampler_state state, DWORD value)
846 struct wined3d_cs_set_sampler_state *op;
848 op = cs->ops->require_space(cs, sizeof(*op));
849 op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE;
850 op->sampler_idx = sampler_idx;
851 op->state = state;
852 op->value = value;
854 cs->ops->submit(cs);
857 static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data)
859 const struct wined3d_cs_set_transform *op = data;
861 cs->state.transforms[op->state] = *op->matrix;
862 if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->d3d_info.limits.ffp_vertex_blend_matrices))
863 device_invalidate_state(cs->device, STATE_TRANSFORM(op->state));
866 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
867 const struct wined3d_matrix *matrix)
869 struct wined3d_cs_set_transform *op;
871 op = cs->ops->require_space(cs, sizeof(*op));
872 op->opcode = WINED3D_CS_OP_SET_TRANSFORM;
873 op->state = state;
874 op->matrix = matrix;
876 cs->ops->submit(cs);
879 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data)
881 const struct wined3d_cs_set_clip_plane *op = data;
883 cs->state.clip_planes[op->plane_idx] = *op->plane;
884 device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx));
887 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane)
889 struct wined3d_cs_set_clip_plane *op;
891 op = cs->ops->require_space(cs, sizeof(*op));
892 op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE;
893 op->plane_idx = plane_idx;
894 op->plane = plane;
896 cs->ops->submit(cs);
899 static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *data)
901 const struct wined3d_cs_set_color_key *op = data;
902 struct wined3d_texture *texture = op->texture;
904 if (op->set)
906 switch (op->flags)
908 case WINED3D_CKEY_DST_BLT:
909 texture->async.dst_blt_color_key = op->color_key;
910 texture->async.color_key_flags |= WINED3D_CKEY_DST_BLT;
911 break;
913 case WINED3D_CKEY_DST_OVERLAY:
914 texture->async.dst_overlay_color_key = op->color_key;
915 texture->async.color_key_flags |= WINED3D_CKEY_DST_OVERLAY;
916 break;
918 case WINED3D_CKEY_SRC_BLT:
919 if (texture == cs->state.textures[0])
921 device_invalidate_state(cs->device, STATE_COLOR_KEY);
922 if (!(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT))
923 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
926 texture->async.src_blt_color_key = op->color_key;
927 texture->async.color_key_flags |= WINED3D_CKEY_SRC_BLT;
928 break;
930 case WINED3D_CKEY_SRC_OVERLAY:
931 texture->async.src_overlay_color_key = op->color_key;
932 texture->async.color_key_flags |= WINED3D_CKEY_SRC_OVERLAY;
933 break;
936 else
938 switch (op->flags)
940 case WINED3D_CKEY_DST_BLT:
941 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
942 break;
944 case WINED3D_CKEY_DST_OVERLAY:
945 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY;
946 break;
948 case WINED3D_CKEY_SRC_BLT:
949 if (texture == cs->state.textures[0] && texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
950 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
952 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_BLT;
953 break;
955 case WINED3D_CKEY_SRC_OVERLAY:
956 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY;
957 break;
962 void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture,
963 WORD flags, const struct wined3d_color_key *color_key)
965 struct wined3d_cs_set_color_key *op;
967 op = cs->ops->require_space(cs, sizeof(*op));
968 op->opcode = WINED3D_CS_OP_SET_COLOR_KEY;
969 op->texture = texture;
970 op->flags = flags;
971 if (color_key)
973 op->color_key = *color_key;
974 op->set = 1;
976 else
977 op->set = 0;
979 cs->ops->submit(cs);
982 static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data)
984 const struct wined3d_cs_set_material *op = data;
986 cs->state.material = *op->material;
987 device_invalidate_state(cs->device, STATE_MATERIAL);
990 void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material)
992 struct wined3d_cs_set_material *op;
994 op = cs->ops->require_space(cs, sizeof(*op));
995 op->opcode = WINED3D_CS_OP_SET_MATERIAL;
996 op->material = material;
998 cs->ops->submit(cs);
1001 static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data)
1003 struct wined3d_adapter *adapter = cs->device->adapter;
1004 HRESULT hr;
1006 state_cleanup(&cs->state);
1007 memset(&cs->state, 0, sizeof(cs->state));
1008 if (FAILED(hr = state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info,
1009 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
1010 ERR("Failed to initialize CS state, hr %#x.\n", hr);
1013 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs)
1015 struct wined3d_cs_reset_state *op;
1017 op = cs->ops->require_space(cs, sizeof(*op));
1018 op->opcode = WINED3D_CS_OP_RESET_STATE;
1020 cs->ops->submit(cs);
1023 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
1025 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
1026 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
1027 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
1028 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication,
1029 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
1030 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
1031 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
1032 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view,
1033 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
1034 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
1035 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
1036 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output,
1037 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
1038 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer,
1039 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
1040 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view,
1041 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler,
1042 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader,
1043 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state,
1044 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state,
1045 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state,
1046 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform,
1047 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane,
1048 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key,
1049 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material,
1050 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state,
1053 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
1055 if (size > cs->data_size)
1057 void *new_data;
1059 size = max( size, cs->data_size * 2 );
1060 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
1061 return NULL;
1063 cs->data_size = size;
1064 cs->data = new_data;
1067 return cs->data;
1070 static void wined3d_cs_st_submit(struct wined3d_cs *cs)
1072 enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
1074 wined3d_cs_op_handlers[opcode](cs, cs->data);
1077 static const struct wined3d_cs_ops wined3d_cs_st_ops =
1079 wined3d_cs_st_require_space,
1080 wined3d_cs_st_submit,
1083 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
1085 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1086 struct wined3d_cs *cs;
1088 if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
1089 return NULL;
1091 if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1092 sizeof(*cs->fb.render_targets) * gl_info->limits.buffers)))
1094 HeapFree(GetProcessHeap(), 0, cs);
1095 return NULL;
1098 if (FAILED(state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info,
1099 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
1101 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
1102 HeapFree(GetProcessHeap(), 0, cs);
1103 return NULL;
1106 cs->ops = &wined3d_cs_st_ops;
1107 cs->device = device;
1109 cs->data_size = WINED3D_INITIAL_CS_SIZE;
1110 if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
1112 HeapFree(GetProcessHeap(), 0, cs);
1113 return NULL;
1116 return cs;
1119 void wined3d_cs_destroy(struct wined3d_cs *cs)
1121 state_cleanup(&cs->state);
1122 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
1123 HeapFree(GetProcessHeap(), 0, cs->data);
1124 HeapFree(GetProcessHeap(), 0, cs);