wined3d: Synchronise WINED3D_CS_OP_UNLOAD_RESOURCE resource access.
[wine.git] / dlls / wined3d / cs.c
blobc9d728cf597a440df456628218c581a9d91eafbd
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_RASTERIZER_STATE,
48 WINED3D_CS_OP_SET_RENDER_STATE,
49 WINED3D_CS_OP_SET_TEXTURE_STATE,
50 WINED3D_CS_OP_SET_SAMPLER_STATE,
51 WINED3D_CS_OP_SET_TRANSFORM,
52 WINED3D_CS_OP_SET_CLIP_PLANE,
53 WINED3D_CS_OP_SET_COLOR_KEY,
54 WINED3D_CS_OP_SET_MATERIAL,
55 WINED3D_CS_OP_RESET_STATE,
56 WINED3D_CS_OP_DESTROY_OBJECT,
57 WINED3D_CS_OP_QUERY_ISSUE,
58 WINED3D_CS_OP_UNLOAD_RESOURCE,
61 struct wined3d_cs_present
63 enum wined3d_cs_op opcode;
64 HWND dst_window_override;
65 struct wined3d_swapchain *swapchain;
66 RECT src_rect;
67 RECT dst_rect;
68 DWORD flags;
71 struct wined3d_cs_clear
73 enum wined3d_cs_op opcode;
74 DWORD flags;
75 struct wined3d_color color;
76 float depth;
77 DWORD stencil;
78 unsigned int rect_count;
79 RECT rects[1];
82 struct wined3d_cs_draw
84 enum wined3d_cs_op opcode;
85 int base_vertex_idx;
86 unsigned int start_idx;
87 unsigned int index_count;
88 unsigned int start_instance;
89 unsigned int instance_count;
90 BOOL indexed;
93 struct wined3d_cs_set_predication
95 enum wined3d_cs_op opcode;
96 struct wined3d_query *predicate;
97 BOOL value;
100 struct wined3d_cs_set_viewport
102 enum wined3d_cs_op opcode;
103 struct wined3d_viewport viewport;
106 struct wined3d_cs_set_scissor_rect
108 enum wined3d_cs_op opcode;
109 RECT rect;
112 struct wined3d_cs_set_rendertarget_view
114 enum wined3d_cs_op opcode;
115 unsigned int view_idx;
116 struct wined3d_rendertarget_view *view;
119 struct wined3d_cs_set_depth_stencil_view
121 enum wined3d_cs_op opcode;
122 struct wined3d_rendertarget_view *view;
125 struct wined3d_cs_set_vertex_declaration
127 enum wined3d_cs_op opcode;
128 struct wined3d_vertex_declaration *declaration;
131 struct wined3d_cs_set_stream_source
133 enum wined3d_cs_op opcode;
134 UINT stream_idx;
135 struct wined3d_buffer *buffer;
136 UINT offset;
137 UINT stride;
140 struct wined3d_cs_set_stream_source_freq
142 enum wined3d_cs_op opcode;
143 UINT stream_idx;
144 UINT frequency;
145 UINT flags;
148 struct wined3d_cs_set_stream_output
150 enum wined3d_cs_op opcode;
151 UINT stream_idx;
152 struct wined3d_buffer *buffer;
153 UINT offset;
156 struct wined3d_cs_set_index_buffer
158 enum wined3d_cs_op opcode;
159 struct wined3d_buffer *buffer;
160 enum wined3d_format_id format_id;
161 unsigned int offset;
164 struct wined3d_cs_set_constant_buffer
166 enum wined3d_cs_op opcode;
167 enum wined3d_shader_type type;
168 UINT cb_idx;
169 struct wined3d_buffer *buffer;
172 struct wined3d_cs_set_texture
174 enum wined3d_cs_op opcode;
175 UINT stage;
176 struct wined3d_texture *texture;
179 struct wined3d_cs_set_color_key
181 enum wined3d_cs_op opcode;
182 struct wined3d_texture *texture;
183 WORD flags;
184 WORD set;
185 struct wined3d_color_key color_key;
188 struct wined3d_cs_set_shader_resource_view
190 enum wined3d_cs_op opcode;
191 enum wined3d_shader_type type;
192 UINT view_idx;
193 struct wined3d_shader_resource_view *view;
196 struct wined3d_cs_set_sampler
198 enum wined3d_cs_op opcode;
199 enum wined3d_shader_type type;
200 UINT sampler_idx;
201 struct wined3d_sampler *sampler;
204 struct wined3d_cs_set_shader
206 enum wined3d_cs_op opcode;
207 enum wined3d_shader_type type;
208 struct wined3d_shader *shader;
211 struct wined3d_cs_set_rasterizer_state
213 enum wined3d_cs_op opcode;
214 struct wined3d_rasterizer_state *state;
217 struct wined3d_cs_set_render_state
219 enum wined3d_cs_op opcode;
220 enum wined3d_render_state state;
221 DWORD value;
224 struct wined3d_cs_set_texture_state
226 enum wined3d_cs_op opcode;
227 UINT stage;
228 enum wined3d_texture_stage_state state;
229 DWORD value;
232 struct wined3d_cs_set_sampler_state
234 enum wined3d_cs_op opcode;
235 UINT sampler_idx;
236 enum wined3d_sampler_state state;
237 DWORD value;
240 struct wined3d_cs_set_transform
242 enum wined3d_cs_op opcode;
243 enum wined3d_transform_state state;
244 struct wined3d_matrix matrix;
247 struct wined3d_cs_set_clip_plane
249 enum wined3d_cs_op opcode;
250 UINT plane_idx;
251 struct wined3d_vec4 plane;
254 struct wined3d_cs_set_material
256 enum wined3d_cs_op opcode;
257 struct wined3d_material material;
260 struct wined3d_cs_reset_state
262 enum wined3d_cs_op opcode;
265 struct wined3d_cs_destroy_object
267 enum wined3d_cs_op opcode;
268 void (*callback)(void *object);
269 void *object;
272 struct wined3d_cs_query_issue
274 enum wined3d_cs_op opcode;
275 struct wined3d_query *query;
276 DWORD flags;
279 struct wined3d_cs_unload_resource
281 enum wined3d_cs_op opcode;
282 struct wined3d_resource *resource;
285 static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
287 const struct wined3d_cs_present *op = data;
288 struct wined3d_swapchain *swapchain;
289 unsigned int i;
291 swapchain = op->swapchain;
292 wined3d_swapchain_set_window(swapchain, op->dst_window_override);
294 swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags);
296 wined3d_resource_release(&swapchain->front_buffer->resource);
297 for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
299 wined3d_resource_release(&swapchain->back_buffers[i]->resource);
303 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
304 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags)
306 struct wined3d_cs_present *op;
307 unsigned int i;
309 op = cs->ops->require_space(cs, sizeof(*op));
310 op->opcode = WINED3D_CS_OP_PRESENT;
311 op->dst_window_override = dst_window_override;
312 op->swapchain = swapchain;
313 op->src_rect = *src_rect;
314 op->dst_rect = *dst_rect;
315 op->flags = flags;
317 wined3d_resource_acquire(&swapchain->front_buffer->resource);
318 for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
320 wined3d_resource_acquire(&swapchain->back_buffers[i]->resource);
323 cs->ops->submit(cs);
326 static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
328 const struct wined3d_cs_clear *op = data;
329 const struct wined3d_state *state;
330 struct wined3d_device *device;
331 unsigned int i;
332 RECT draw_rect;
334 device = cs->device;
335 state = &device->state;
336 wined3d_get_draw_rect(state, &draw_rect);
337 device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
338 &device->fb, op->rect_count, op->rects, &draw_rect, op->flags,
339 &op->color, op->depth, op->stencil);
341 if (op->flags & WINED3DCLEAR_TARGET)
343 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
345 if (state->fb->render_targets[i])
346 wined3d_resource_release(state->fb->render_targets[i]->resource);
349 if (op->flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
350 wined3d_resource_release(state->fb->depth_stencil->resource);
353 void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
354 DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
356 const struct wined3d_state *state = &cs->device->state;
357 struct wined3d_cs_clear *op;
358 unsigned int i;
360 op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_clear, rects[rect_count]));
361 op->opcode = WINED3D_CS_OP_CLEAR;
362 op->flags = flags;
363 op->color = *color;
364 op->depth = depth;
365 op->stencil = stencil;
366 op->rect_count = rect_count;
367 memcpy(op->rects, rects, sizeof(*rects) * rect_count);
369 if (flags & WINED3DCLEAR_TARGET)
371 for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
373 if (state->fb->render_targets[i])
374 wined3d_resource_acquire(state->fb->render_targets[i]->resource);
377 if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
378 wined3d_resource_acquire(state->fb->depth_stencil->resource);
380 cs->ops->submit(cs);
383 static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
385 struct wined3d_state *state = &cs->device->state;
386 struct wined3d_shader_sampler_map_entry *entry;
387 struct wined3d_shader_resource_view *view;
388 const struct wined3d_cs_draw *op = data;
389 struct wined3d_shader *shader;
390 unsigned int i, j;
392 if (!cs->device->adapter->gl_info.supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]
393 && state->load_base_vertex_index != op->base_vertex_idx)
395 state->load_base_vertex_index = op->base_vertex_idx;
396 device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX);
399 draw_primitive(cs->device, state, op->base_vertex_idx, op->start_idx,
400 op->index_count, op->start_instance, op->instance_count, op->indexed);
402 if (op->indexed)
403 wined3d_resource_release(&state->index_buffer->resource);
404 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
406 if (state->streams[i].buffer)
407 wined3d_resource_release(&state->streams[i].buffer->resource);
409 for (i = 0; i < ARRAY_SIZE(state->textures); ++i)
411 if (state->textures[i])
412 wined3d_resource_release(&state->textures[i]->resource);
414 for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
416 if (state->fb->render_targets[i])
417 wined3d_resource_release(state->fb->render_targets[i]->resource);
419 if (state->fb->depth_stencil)
420 wined3d_resource_release(state->fb->depth_stencil->resource);
421 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
423 if (!(shader = state->shader[i]))
424 continue;
426 for (j = 0; j < WINED3D_MAX_CBS; ++j)
428 if (state->cb[i][j])
429 wined3d_resource_release(&state->cb[i][j]->resource);
432 for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
434 entry = &shader->reg_maps.sampler_map.entries[j];
436 if (!(view = state->shader_resource_view[i][entry->resource_idx]))
437 continue;
439 wined3d_resource_release(view->resource);
444 void wined3d_cs_emit_draw(struct wined3d_cs *cs, int base_vertex_idx, unsigned int start_idx,
445 unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed)
447 const struct wined3d_state *state = &cs->device->state;
448 struct wined3d_shader_sampler_map_entry *entry;
449 struct wined3d_shader_resource_view *view;
450 struct wined3d_shader *shader;
451 struct wined3d_cs_draw *op;
452 unsigned int i, j;
454 op = cs->ops->require_space(cs, sizeof(*op));
455 op->opcode = WINED3D_CS_OP_DRAW;
456 op->base_vertex_idx = base_vertex_idx;
457 op->start_idx = start_idx;
458 op->index_count = index_count;
459 op->start_instance = start_instance;
460 op->instance_count = instance_count;
461 op->indexed = indexed;
463 if (indexed)
464 wined3d_resource_acquire(&state->index_buffer->resource);
465 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
467 if (state->streams[i].buffer)
468 wined3d_resource_acquire(&state->streams[i].buffer->resource);
470 for (i = 0; i < ARRAY_SIZE(state->textures); ++i)
472 if (state->textures[i])
473 wined3d_resource_acquire(&state->textures[i]->resource);
475 for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
477 if (state->fb->render_targets[i])
478 wined3d_resource_acquire(state->fb->render_targets[i]->resource);
480 if (state->fb->depth_stencil)
481 wined3d_resource_acquire(state->fb->depth_stencil->resource);
482 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
484 if (!(shader = state->shader[i]))
485 continue;
487 for (j = 0; j < WINED3D_MAX_CBS; ++j)
489 if (state->cb[i][j])
490 wined3d_resource_acquire(&state->cb[i][j]->resource);
493 for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
495 entry = &shader->reg_maps.sampler_map.entries[j];
497 if (!(view = state->shader_resource_view[i][entry->resource_idx]))
498 continue;
500 wined3d_resource_acquire(view->resource);
504 cs->ops->submit(cs);
507 static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data)
509 const struct wined3d_cs_set_predication *op = data;
511 cs->state.predicate = op->predicate;
512 cs->state.predicate_value = op->value;
515 void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value)
517 struct wined3d_cs_set_predication *op;
519 op = cs->ops->require_space(cs, sizeof(*op));
520 op->opcode = WINED3D_CS_OP_SET_PREDICATION;
521 op->predicate = predicate;
522 op->value = value;
524 cs->ops->submit(cs);
527 static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
529 const struct wined3d_cs_set_viewport *op = data;
531 cs->state.viewport = op->viewport;
532 device_invalidate_state(cs->device, STATE_VIEWPORT);
535 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
537 struct wined3d_cs_set_viewport *op;
539 op = cs->ops->require_space(cs, sizeof(*op));
540 op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
541 op->viewport = *viewport;
543 cs->ops->submit(cs);
546 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
548 const struct wined3d_cs_set_scissor_rect *op = data;
550 cs->state.scissor_rect = op->rect;
551 device_invalidate_state(cs->device, STATE_SCISSORRECT);
554 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
556 struct wined3d_cs_set_scissor_rect *op;
558 op = cs->ops->require_space(cs, sizeof(*op));
559 op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
560 op->rect = *rect;
562 cs->ops->submit(cs);
565 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
567 const struct wined3d_cs_set_rendertarget_view *op = data;
569 cs->state.fb->render_targets[op->view_idx] = op->view;
570 device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
573 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
574 struct wined3d_rendertarget_view *view)
576 struct wined3d_cs_set_rendertarget_view *op;
578 op = cs->ops->require_space(cs, sizeof(*op));
579 op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
580 op->view_idx = view_idx;
581 op->view = view;
583 cs->ops->submit(cs);
586 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data)
588 const struct wined3d_cs_set_depth_stencil_view *op = data;
589 struct wined3d_device *device = cs->device;
590 struct wined3d_rendertarget_view *prev;
592 if ((prev = cs->state.fb->depth_stencil))
594 struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev);
596 if (prev_surface && (device->swapchains[0]->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
597 || prev_surface->container->flags & WINED3D_TEXTURE_DISCARD))
599 surface_modify_ds_location(prev_surface, WINED3D_LOCATION_DISCARDED, prev->width, prev->height);
600 if (prev_surface == device->onscreen_depth_stencil)
602 wined3d_texture_decref(device->onscreen_depth_stencil->container);
603 device->onscreen_depth_stencil = NULL;
608 cs->fb.depth_stencil = op->view;
610 if (!prev != !op->view)
612 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
613 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
614 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE));
615 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
616 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
618 else if (prev && (prev->format_flags & WINED3DFMT_FLAG_FLOAT)
619 != (op->view->format_flags & WINED3DFMT_FLAG_FLOAT))
621 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
624 device_invalidate_state(device, STATE_FRAMEBUFFER);
627 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view)
629 struct wined3d_cs_set_depth_stencil_view *op;
631 op = cs->ops->require_space(cs, sizeof(*op));
632 op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW;
633 op->view = view;
635 cs->ops->submit(cs);
638 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data)
640 const struct wined3d_cs_set_vertex_declaration *op = data;
642 cs->state.vertex_declaration = op->declaration;
643 device_invalidate_state(cs->device, STATE_VDECL);
646 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration)
648 struct wined3d_cs_set_vertex_declaration *op;
650 op = cs->ops->require_space(cs, sizeof(*op));
651 op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION;
652 op->declaration = declaration;
654 cs->ops->submit(cs);
657 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data)
659 const struct wined3d_cs_set_stream_source *op = data;
660 struct wined3d_stream_state *stream;
661 struct wined3d_buffer *prev;
663 stream = &cs->state.streams[op->stream_idx];
664 prev = stream->buffer;
665 stream->buffer = op->buffer;
666 stream->offset = op->offset;
667 stream->stride = op->stride;
669 if (op->buffer)
670 InterlockedIncrement(&op->buffer->resource.bind_count);
671 if (prev)
672 InterlockedDecrement(&prev->resource.bind_count);
674 device_invalidate_state(cs->device, STATE_STREAMSRC);
677 void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx,
678 struct wined3d_buffer *buffer, UINT offset, UINT stride)
680 struct wined3d_cs_set_stream_source *op;
682 op = cs->ops->require_space(cs, sizeof(*op));
683 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE;
684 op->stream_idx = stream_idx;
685 op->buffer = buffer;
686 op->offset = offset;
687 op->stride = stride;
689 cs->ops->submit(cs);
692 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data)
694 const struct wined3d_cs_set_stream_source_freq *op = data;
695 struct wined3d_stream_state *stream;
697 stream = &cs->state.streams[op->stream_idx];
698 stream->frequency = op->frequency;
699 stream->flags = op->flags;
701 device_invalidate_state(cs->device, STATE_STREAMSRC);
704 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags)
706 struct wined3d_cs_set_stream_source_freq *op;
708 op = cs->ops->require_space(cs, sizeof(*op));
709 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ;
710 op->stream_idx = stream_idx;
711 op->frequency = frequency;
712 op->flags = flags;
714 cs->ops->submit(cs);
717 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data)
719 const struct wined3d_cs_set_stream_output *op = data;
720 struct wined3d_stream_output *stream;
721 struct wined3d_buffer *prev;
723 stream = &cs->state.stream_output[op->stream_idx];
724 prev = stream->buffer;
725 stream->buffer = op->buffer;
726 stream->offset = op->offset;
728 if (op->buffer)
729 InterlockedIncrement(&op->buffer->resource.bind_count);
730 if (prev)
731 InterlockedDecrement(&prev->resource.bind_count);
734 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
735 struct wined3d_buffer *buffer, UINT offset)
737 struct wined3d_cs_set_stream_output *op;
739 op = cs->ops->require_space(cs, sizeof(*op));
740 op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT;
741 op->stream_idx = stream_idx;
742 op->buffer = buffer;
743 op->offset = offset;
745 cs->ops->submit(cs);
748 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data)
750 const struct wined3d_cs_set_index_buffer *op = data;
751 struct wined3d_buffer *prev;
753 prev = cs->state.index_buffer;
754 cs->state.index_buffer = op->buffer;
755 cs->state.index_format = op->format_id;
756 cs->state.index_offset = op->offset;
758 if (op->buffer)
759 InterlockedIncrement(&op->buffer->resource.bind_count);
760 if (prev)
761 InterlockedDecrement(&prev->resource.bind_count);
763 device_invalidate_state(cs->device, STATE_INDEXBUFFER);
766 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer,
767 enum wined3d_format_id format_id, unsigned int offset)
769 struct wined3d_cs_set_index_buffer *op;
771 op = cs->ops->require_space(cs, sizeof(*op));
772 op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER;
773 op->buffer = buffer;
774 op->format_id = format_id;
775 op->offset = offset;
777 cs->ops->submit(cs);
780 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data)
782 const struct wined3d_cs_set_constant_buffer *op = data;
783 struct wined3d_buffer *prev;
785 prev = cs->state.cb[op->type][op->cb_idx];
786 cs->state.cb[op->type][op->cb_idx] = op->buffer;
788 if (op->buffer)
789 InterlockedIncrement(&op->buffer->resource.bind_count);
790 if (prev)
791 InterlockedDecrement(&prev->resource.bind_count);
793 device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type));
796 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
797 UINT cb_idx, struct wined3d_buffer *buffer)
799 struct wined3d_cs_set_constant_buffer *op;
801 op = cs->ops->require_space(cs, sizeof(*op));
802 op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER;
803 op->type = type;
804 op->cb_idx = cb_idx;
805 op->buffer = buffer;
807 cs->ops->submit(cs);
810 static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
812 const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
813 const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
814 const struct wined3d_cs_set_texture *op = data;
815 struct wined3d_texture *prev;
816 BOOL old_use_color_key = FALSE, new_use_color_key = FALSE;
818 prev = cs->state.textures[op->stage];
819 cs->state.textures[op->stage] = op->texture;
821 if (op->texture)
823 const struct wined3d_format *new_format = op->texture->resource.format;
824 const struct wined3d_format *old_format = prev ? prev->resource.format : NULL;
825 unsigned int old_fmt_flags = prev ? prev->resource.format_flags : 0;
826 unsigned int new_fmt_flags = op->texture->resource.format_flags;
828 if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
829 op->texture->sampler = op->stage;
831 if (!prev || op->texture->target != prev->target
832 || (!is_same_fixup(new_format->color_fixup, old_format->color_fixup)
833 && !(can_use_texture_swizzle(gl_info, new_format) && can_use_texture_swizzle(gl_info, old_format)))
834 || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW))
835 device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
837 if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
839 /* The source arguments for color and alpha ops have different
840 * meanings when a NULL texture is bound, so the COLOR_OP and
841 * ALPHA_OP have to be dirtified. */
842 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
843 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
846 if (!op->stage && op->texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
847 new_use_color_key = TRUE;
850 if (prev)
852 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
854 unsigned int i;
856 /* Search for other stages the texture is bound to. Shouldn't
857 * happen if applications bind textures to a single stage only. */
858 TRACE("Searching for other stages the texture is bound to.\n");
859 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
861 if (cs->state.textures[i] == prev)
863 TRACE("Texture is also bound to stage %u.\n", i);
864 prev->sampler = i;
865 break;
870 if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
872 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
873 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
876 if (!op->stage && prev->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
877 old_use_color_key = TRUE;
880 device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
882 if (new_use_color_key != old_use_color_key)
883 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
885 if (new_use_color_key)
886 device_invalidate_state(cs->device, STATE_COLOR_KEY);
889 void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
891 struct wined3d_cs_set_texture *op;
893 op = cs->ops->require_space(cs, sizeof(*op));
894 op->opcode = WINED3D_CS_OP_SET_TEXTURE;
895 op->stage = stage;
896 op->texture = texture;
898 cs->ops->submit(cs);
901 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data)
903 const struct wined3d_cs_set_shader_resource_view *op = data;
905 cs->state.shader_resource_view[op->type][op->view_idx] = op->view;
906 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
909 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type,
910 UINT view_idx, struct wined3d_shader_resource_view *view)
912 struct wined3d_cs_set_shader_resource_view *op;
914 op = cs->ops->require_space(cs, sizeof(*op));
915 op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW;
916 op->type = type;
917 op->view_idx = view_idx;
918 op->view = view;
920 cs->ops->submit(cs);
923 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
925 const struct wined3d_cs_set_sampler *op = data;
927 cs->state.sampler[op->type][op->sampler_idx] = op->sampler;
928 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
931 void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
932 UINT sampler_idx, struct wined3d_sampler *sampler)
934 struct wined3d_cs_set_sampler *op;
936 op = cs->ops->require_space(cs, sizeof(*op));
937 op->opcode = WINED3D_CS_OP_SET_SAMPLER;
938 op->type = type;
939 op->sampler_idx = sampler_idx;
940 op->sampler = sampler;
942 cs->ops->submit(cs);
945 static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data)
947 const struct wined3d_cs_set_shader *op = data;
949 cs->state.shader[op->type] = op->shader;
950 device_invalidate_state(cs->device, STATE_SHADER(op->type));
951 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
954 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader)
956 struct wined3d_cs_set_shader *op;
958 op = cs->ops->require_space(cs, sizeof(*op));
959 op->opcode = WINED3D_CS_OP_SET_SHADER;
960 op->type = type;
961 op->shader = shader;
963 cs->ops->submit(cs);
966 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs *cs, const void *data)
968 const struct wined3d_cs_set_rasterizer_state *op = data;
970 cs->state.rasterizer_state = op->state;
971 device_invalidate_state(cs->device, STATE_FRONTFACE);
974 void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs,
975 struct wined3d_rasterizer_state *rasterizer_state)
977 struct wined3d_cs_set_rasterizer_state *op;
979 op = cs->ops->require_space(cs, sizeof(*op));
980 op->opcode = WINED3D_CS_OP_SET_RASTERIZER_STATE;
981 op->state = rasterizer_state;
983 cs->ops->submit(cs);
986 static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data)
988 const struct wined3d_cs_set_render_state *op = data;
990 cs->state.render_states[op->state] = op->value;
991 device_invalidate_state(cs->device, STATE_RENDER(op->state));
994 void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value)
996 struct wined3d_cs_set_render_state *op;
998 op = cs->ops->require_space(cs, sizeof(*op));
999 op->opcode = WINED3D_CS_OP_SET_RENDER_STATE;
1000 op->state = state;
1001 op->value = value;
1003 cs->ops->submit(cs);
1006 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
1008 const struct wined3d_cs_set_texture_state *op = data;
1010 cs->state.texture_states[op->stage][op->state] = op->value;
1011 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state));
1014 void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
1015 enum wined3d_texture_stage_state state, DWORD value)
1017 struct wined3d_cs_set_texture_state *op;
1019 op = cs->ops->require_space(cs, sizeof(*op));
1020 op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE;
1021 op->stage = stage;
1022 op->state = state;
1023 op->value = value;
1025 cs->ops->submit(cs);
1028 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data)
1030 const struct wined3d_cs_set_sampler_state *op = data;
1032 cs->state.sampler_states[op->sampler_idx][op->state] = op->value;
1033 device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx));
1036 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
1037 enum wined3d_sampler_state state, DWORD value)
1039 struct wined3d_cs_set_sampler_state *op;
1041 op = cs->ops->require_space(cs, sizeof(*op));
1042 op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE;
1043 op->sampler_idx = sampler_idx;
1044 op->state = state;
1045 op->value = value;
1047 cs->ops->submit(cs);
1050 static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data)
1052 const struct wined3d_cs_set_transform *op = data;
1054 cs->state.transforms[op->state] = op->matrix;
1055 if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->d3d_info.limits.ffp_vertex_blend_matrices))
1056 device_invalidate_state(cs->device, STATE_TRANSFORM(op->state));
1059 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
1060 const struct wined3d_matrix *matrix)
1062 struct wined3d_cs_set_transform *op;
1064 op = cs->ops->require_space(cs, sizeof(*op));
1065 op->opcode = WINED3D_CS_OP_SET_TRANSFORM;
1066 op->state = state;
1067 op->matrix = *matrix;
1069 cs->ops->submit(cs);
1072 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data)
1074 const struct wined3d_cs_set_clip_plane *op = data;
1076 cs->state.clip_planes[op->plane_idx] = op->plane;
1077 device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx));
1080 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane)
1082 struct wined3d_cs_set_clip_plane *op;
1084 op = cs->ops->require_space(cs, sizeof(*op));
1085 op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE;
1086 op->plane_idx = plane_idx;
1087 op->plane = *plane;
1089 cs->ops->submit(cs);
1092 static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *data)
1094 const struct wined3d_cs_set_color_key *op = data;
1095 struct wined3d_texture *texture = op->texture;
1097 if (op->set)
1099 switch (op->flags)
1101 case WINED3D_CKEY_DST_BLT:
1102 texture->async.dst_blt_color_key = op->color_key;
1103 texture->async.color_key_flags |= WINED3D_CKEY_DST_BLT;
1104 break;
1106 case WINED3D_CKEY_DST_OVERLAY:
1107 texture->async.dst_overlay_color_key = op->color_key;
1108 texture->async.color_key_flags |= WINED3D_CKEY_DST_OVERLAY;
1109 break;
1111 case WINED3D_CKEY_SRC_BLT:
1112 if (texture == cs->state.textures[0])
1114 device_invalidate_state(cs->device, STATE_COLOR_KEY);
1115 if (!(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT))
1116 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
1119 texture->async.src_blt_color_key = op->color_key;
1120 texture->async.color_key_flags |= WINED3D_CKEY_SRC_BLT;
1121 break;
1123 case WINED3D_CKEY_SRC_OVERLAY:
1124 texture->async.src_overlay_color_key = op->color_key;
1125 texture->async.color_key_flags |= WINED3D_CKEY_SRC_OVERLAY;
1126 break;
1129 else
1131 switch (op->flags)
1133 case WINED3D_CKEY_DST_BLT:
1134 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
1135 break;
1137 case WINED3D_CKEY_DST_OVERLAY:
1138 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY;
1139 break;
1141 case WINED3D_CKEY_SRC_BLT:
1142 if (texture == cs->state.textures[0] && texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
1143 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
1145 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_BLT;
1146 break;
1148 case WINED3D_CKEY_SRC_OVERLAY:
1149 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY;
1150 break;
1155 void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture,
1156 WORD flags, const struct wined3d_color_key *color_key)
1158 struct wined3d_cs_set_color_key *op;
1160 op = cs->ops->require_space(cs, sizeof(*op));
1161 op->opcode = WINED3D_CS_OP_SET_COLOR_KEY;
1162 op->texture = texture;
1163 op->flags = flags;
1164 if (color_key)
1166 op->color_key = *color_key;
1167 op->set = 1;
1169 else
1170 op->set = 0;
1172 cs->ops->submit(cs);
1175 static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data)
1177 const struct wined3d_cs_set_material *op = data;
1179 cs->state.material = op->material;
1180 device_invalidate_state(cs->device, STATE_MATERIAL);
1183 void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material)
1185 struct wined3d_cs_set_material *op;
1187 op = cs->ops->require_space(cs, sizeof(*op));
1188 op->opcode = WINED3D_CS_OP_SET_MATERIAL;
1189 op->material = *material;
1191 cs->ops->submit(cs);
1194 static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data)
1196 struct wined3d_adapter *adapter = cs->device->adapter;
1198 state_cleanup(&cs->state);
1199 memset(&cs->state, 0, sizeof(cs->state));
1200 state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info,
1201 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT);
1204 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs)
1206 struct wined3d_cs_reset_state *op;
1208 op = cs->ops->require_space(cs, sizeof(*op));
1209 op->opcode = WINED3D_CS_OP_RESET_STATE;
1211 cs->ops->submit(cs);
1214 static void wined3d_cs_exec_destroy_object(struct wined3d_cs *cs, const void *data)
1216 const struct wined3d_cs_destroy_object *op = data;
1218 op->callback(op->object);
1221 void wined3d_cs_emit_destroy_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object)
1223 struct wined3d_cs_destroy_object *op;
1225 op = cs->ops->require_space(cs, sizeof(*op));
1226 op->opcode = WINED3D_CS_OP_DESTROY_OBJECT;
1227 op->callback = callback;
1228 op->object = object;
1230 cs->ops->submit(cs);
1233 static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data)
1235 const struct wined3d_cs_query_issue *op = data;
1236 struct wined3d_query *query = op->query;
1238 query->query_ops->query_issue(query, op->flags);
1241 void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags)
1243 struct wined3d_cs_query_issue *op;
1245 op = cs->ops->require_space(cs, sizeof(*op));
1246 op->opcode = WINED3D_CS_OP_QUERY_ISSUE;
1247 op->query = query;
1248 op->flags = flags;
1250 cs->ops->submit(cs);
1253 static void wined3d_cs_exec_unload_resource(struct wined3d_cs *cs, const void *data)
1255 const struct wined3d_cs_unload_resource *op = data;
1256 struct wined3d_resource *resource = op->resource;
1258 resource->resource_ops->resource_unload(resource);
1259 wined3d_resource_release(resource);
1262 void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource)
1264 struct wined3d_cs_unload_resource *op;
1266 op = cs->ops->require_space(cs, sizeof(*op));
1267 op->opcode = WINED3D_CS_OP_UNLOAD_RESOURCE;
1268 op->resource = resource;
1270 wined3d_resource_acquire(resource);
1272 cs->ops->submit(cs);
1275 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
1277 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
1278 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
1279 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
1280 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication,
1281 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
1282 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
1283 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
1284 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view,
1285 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
1286 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
1287 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
1288 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output,
1289 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
1290 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer,
1291 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
1292 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view,
1293 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler,
1294 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader,
1295 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state,
1296 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state,
1297 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state,
1298 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state,
1299 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform,
1300 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane,
1301 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key,
1302 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material,
1303 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state,
1304 /* WINED3D_CS_OP_DESTROY_OBJECT */ wined3d_cs_exec_destroy_object,
1305 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue,
1306 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource,
1309 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
1311 if (size > cs->data_size)
1313 void *new_data;
1315 size = max( size, cs->data_size * 2 );
1316 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
1317 return NULL;
1319 cs->data_size = size;
1320 cs->data = new_data;
1323 return cs->data;
1326 static void wined3d_cs_st_submit(struct wined3d_cs *cs)
1328 enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
1330 wined3d_cs_op_handlers[opcode](cs, cs->data);
1333 static void wined3d_cs_st_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p,
1334 unsigned int start_idx, unsigned int count, const void *constants)
1336 struct wined3d_device *device = cs->device;
1337 unsigned int context_count;
1338 unsigned int i;
1339 size_t offset;
1341 static const struct
1343 size_t offset;
1344 size_t size;
1345 DWORD mask;
1347 push_constant_info[] =
1349 /* WINED3D_PUSH_CONSTANTS_VS_F */
1350 {FIELD_OFFSET(struct wined3d_state, vs_consts_f), sizeof(struct wined3d_vec4), WINED3D_SHADER_CONST_VS_F},
1351 /* WINED3D_PUSH_CONSTANTS_PS_F */
1352 {FIELD_OFFSET(struct wined3d_state, ps_consts_f), sizeof(struct wined3d_vec4), WINED3D_SHADER_CONST_PS_F},
1353 /* WINED3D_PUSH_CONSTANTS_VS_I */
1354 {FIELD_OFFSET(struct wined3d_state, vs_consts_i), sizeof(struct wined3d_ivec4), WINED3D_SHADER_CONST_VS_I},
1355 /* WINED3D_PUSH_CONSTANTS_PS_I */
1356 {FIELD_OFFSET(struct wined3d_state, ps_consts_i), sizeof(struct wined3d_ivec4), WINED3D_SHADER_CONST_PS_I},
1357 /* WINED3D_PUSH_CONSTANTS_VS_B */
1358 {FIELD_OFFSET(struct wined3d_state, vs_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_VS_B},
1359 /* WINED3D_PUSH_CONSTANTS_PS_B */
1360 {FIELD_OFFSET(struct wined3d_state, ps_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_PS_B},
1363 if (p == WINED3D_PUSH_CONSTANTS_VS_F)
1364 device->shader_backend->shader_update_float_vertex_constants(device, start_idx, count);
1365 else if (p == WINED3D_PUSH_CONSTANTS_PS_F)
1366 device->shader_backend->shader_update_float_pixel_constants(device, start_idx, count);
1368 offset = push_constant_info[p].offset + start_idx * push_constant_info[p].size;
1369 memcpy((BYTE *)&cs->state + offset, constants, count * push_constant_info[p].size);
1370 for (i = 0, context_count = device->context_count; i < context_count; ++i)
1372 device->contexts[i]->constant_update_mask |= push_constant_info[p].mask;
1376 static const struct wined3d_cs_ops wined3d_cs_st_ops =
1378 wined3d_cs_st_require_space,
1379 wined3d_cs_st_submit,
1380 wined3d_cs_st_push_constants,
1383 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
1385 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1386 struct wined3d_cs *cs;
1388 if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
1389 return NULL;
1391 if (!(cs->fb.render_targets = wined3d_calloc(gl_info->limits.buffers, sizeof(*cs->fb.render_targets))))
1393 HeapFree(GetProcessHeap(), 0, cs);
1394 return NULL;
1397 state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info,
1398 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT);
1400 cs->ops = &wined3d_cs_st_ops;
1401 cs->device = device;
1403 cs->data_size = WINED3D_INITIAL_CS_SIZE;
1404 if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
1406 state_cleanup(&cs->state);
1407 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
1408 HeapFree(GetProcessHeap(), 0, cs);
1409 return NULL;
1412 return cs;
1415 void wined3d_cs_destroy(struct wined3d_cs *cs)
1417 state_cleanup(&cs->state);
1418 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
1419 HeapFree(GetProcessHeap(), 0, cs->data);
1420 HeapFree(GetProcessHeap(), 0, cs);