wined3d: Send stream output binding updates through the command stream.
[wine.git] / dlls / wined3d / cs.c
blob3d9a07c0097984265179c21246380582343b0c0e
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_VIEWPORT,
33 WINED3D_CS_OP_SET_SCISSOR_RECT,
34 WINED3D_CS_OP_SET_RENDER_TARGET,
35 WINED3D_CS_OP_SET_DEPTH_STENCIL,
36 WINED3D_CS_OP_SET_VERTEX_DECLARATION,
37 WINED3D_CS_OP_SET_STREAM_SOURCE,
38 WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ,
39 WINED3D_CS_OP_SET_STREAM_OUTPUT,
40 WINED3D_CS_OP_SET_INDEX_BUFFER,
41 WINED3D_CS_OP_SET_CONSTANT_BUFFER,
42 WINED3D_CS_OP_SET_TEXTURE,
43 WINED3D_CS_OP_SET_SAMPLER,
44 WINED3D_CS_OP_SET_SHADER,
45 WINED3D_CS_OP_SET_RENDER_STATE,
46 WINED3D_CS_OP_SET_TEXTURE_STATE,
47 WINED3D_CS_OP_SET_SAMPLER_STATE,
48 WINED3D_CS_OP_SET_TRANSFORM,
49 WINED3D_CS_OP_SET_CLIP_PLANE,
50 WINED3D_CS_OP_SET_MATERIAL,
53 struct wined3d_cs_present
55 enum wined3d_cs_op opcode;
56 HWND dst_window_override;
57 struct wined3d_swapchain *swapchain;
58 const RECT *src_rect;
59 const RECT *dst_rect;
60 const RGNDATA *dirty_region;
61 DWORD flags;
64 struct wined3d_cs_clear
66 enum wined3d_cs_op opcode;
67 DWORD rect_count;
68 const RECT *rects;
69 DWORD flags;
70 const struct wined3d_color *color;
71 float depth;
72 DWORD stencil;
75 struct wined3d_cs_draw
77 enum wined3d_cs_op opcode;
78 UINT start_idx;
79 UINT index_count;
80 UINT start_instance;
81 UINT instance_count;
82 BOOL indexed;
85 struct wined3d_cs_set_viewport
87 enum wined3d_cs_op opcode;
88 const struct wined3d_viewport *viewport;
91 struct wined3d_cs_set_scissor_rect
93 enum wined3d_cs_op opcode;
94 const RECT *rect;
97 struct wined3d_cs_set_render_target
99 enum wined3d_cs_op opcode;
100 UINT render_target_idx;
101 struct wined3d_surface *render_target;
104 struct wined3d_cs_set_depth_stencil
106 enum wined3d_cs_op opcode;
107 struct wined3d_surface *depth_stencil;
110 struct wined3d_cs_set_vertex_declaration
112 enum wined3d_cs_op opcode;
113 struct wined3d_vertex_declaration *declaration;
116 struct wined3d_cs_set_stream_source
118 enum wined3d_cs_op opcode;
119 UINT stream_idx;
120 struct wined3d_buffer *buffer;
121 UINT offset;
122 UINT stride;
125 struct wined3d_cs_set_stream_source_freq
127 enum wined3d_cs_op opcode;
128 UINT stream_idx;
129 UINT frequency;
130 UINT flags;
133 struct wined3d_cs_set_stream_output
135 enum wined3d_cs_op opcode;
136 UINT stream_idx;
137 struct wined3d_buffer *buffer;
138 UINT offset;
141 struct wined3d_cs_set_index_buffer
143 enum wined3d_cs_op opcode;
144 struct wined3d_buffer *buffer;
145 enum wined3d_format_id format_id;
148 struct wined3d_cs_set_constant_buffer
150 enum wined3d_cs_op opcode;
151 enum wined3d_shader_type type;
152 UINT cb_idx;
153 struct wined3d_buffer *buffer;
156 struct wined3d_cs_set_texture
158 enum wined3d_cs_op opcode;
159 UINT stage;
160 struct wined3d_texture *texture;
163 struct wined3d_cs_set_sampler
165 enum wined3d_cs_op opcode;
166 enum wined3d_shader_type type;
167 UINT sampler_idx;
168 struct wined3d_sampler *sampler;
171 struct wined3d_cs_set_shader
173 enum wined3d_cs_op opcode;
174 enum wined3d_shader_type type;
175 struct wined3d_shader *shader;
178 struct wined3d_cs_set_render_state
180 enum wined3d_cs_op opcode;
181 enum wined3d_render_state state;
182 DWORD value;
185 struct wined3d_cs_set_texture_state
187 enum wined3d_cs_op opcode;
188 UINT stage;
189 enum wined3d_texture_stage_state state;
190 DWORD value;
193 struct wined3d_cs_set_sampler_state
195 enum wined3d_cs_op opcode;
196 UINT sampler_idx;
197 enum wined3d_sampler_state state;
198 DWORD value;
201 struct wined3d_cs_set_transform
203 enum wined3d_cs_op opcode;
204 enum wined3d_transform_state state;
205 const struct wined3d_matrix *matrix;
208 struct wined3d_cs_set_clip_plane
210 enum wined3d_cs_op opcode;
211 UINT plane_idx;
212 const struct wined3d_vec4 *plane;
215 struct wined3d_cs_set_material
217 enum wined3d_cs_op opcode;
218 const struct wined3d_material *material;
221 static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
223 const struct wined3d_cs_present *op = data;
224 struct wined3d_swapchain *swapchain;
226 swapchain = op->swapchain;
227 wined3d_swapchain_set_window(swapchain, op->dst_window_override);
229 swapchain->swapchain_ops->swapchain_present(swapchain,
230 op->src_rect, op->dst_rect, op->dirty_region, op->flags);
233 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
234 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
235 const RGNDATA *dirty_region, DWORD flags)
237 struct wined3d_cs_present *op;
239 op = cs->ops->require_space(cs, sizeof(*op));
240 op->opcode = WINED3D_CS_OP_PRESENT;
241 op->dst_window_override = dst_window_override;
242 op->swapchain = swapchain;
243 op->src_rect = src_rect;
244 op->dst_rect = dst_rect;
245 op->dirty_region = dirty_region;
246 op->flags = flags;
248 cs->ops->submit(cs);
251 static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
253 const struct wined3d_cs_clear *op = data;
254 struct wined3d_device *device;
255 RECT draw_rect;
257 device = cs->device;
258 wined3d_get_draw_rect(&device->state, &draw_rect);
259 device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
260 &device->fb, op->rect_count, op->rects, &draw_rect, op->flags,
261 op->color, op->depth, op->stencil);
264 void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
265 DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
267 struct wined3d_cs_clear *op;
269 op = cs->ops->require_space(cs, sizeof(*op));
270 op->opcode = WINED3D_CS_OP_CLEAR;
271 op->rect_count = rect_count;
272 op->rects = rects;
273 op->flags = flags;
274 op->color = color;
275 op->depth = depth;
276 op->stencil = stencil;
278 cs->ops->submit(cs);
281 static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
283 const struct wined3d_cs_draw *op = data;
285 draw_primitive(cs->device, op->start_idx, op->index_count,
286 op->start_instance, op->instance_count, op->indexed);
289 void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count,
290 UINT start_instance, UINT instance_count, BOOL indexed)
292 struct wined3d_cs_draw *op;
294 op = cs->ops->require_space(cs, sizeof(*op));
295 op->opcode = WINED3D_CS_OP_DRAW;
296 op->start_idx = start_idx;
297 op->index_count = index_count;
298 op->start_instance = start_instance;
299 op->instance_count = instance_count;
300 op->indexed = indexed;
302 cs->ops->submit(cs);
305 static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
307 const struct wined3d_cs_set_viewport *op = data;
309 cs->state.viewport = *op->viewport;
310 device_invalidate_state(cs->device, STATE_VIEWPORT);
313 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
315 struct wined3d_cs_set_viewport *op;
317 op = cs->ops->require_space(cs, sizeof(*op));
318 op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
319 op->viewport = viewport;
321 cs->ops->submit(cs);
324 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
326 const struct wined3d_cs_set_scissor_rect *op = data;
328 cs->state.scissor_rect = *op->rect;
329 device_invalidate_state(cs->device, STATE_SCISSORRECT);
332 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
334 struct wined3d_cs_set_scissor_rect *op;
336 op = cs->ops->require_space(cs, sizeof(*op));
337 op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
338 op->rect = rect;
340 cs->ops->submit(cs);
343 static void wined3d_cs_exec_set_render_target(struct wined3d_cs *cs, const void *data)
345 const struct wined3d_cs_set_render_target *op = data;
347 cs->state.fb->render_targets[op->render_target_idx] = op->render_target;
348 device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
351 void wined3d_cs_emit_set_render_target(struct wined3d_cs *cs, UINT render_target_idx,
352 struct wined3d_surface *render_target)
354 struct wined3d_cs_set_render_target *op;
356 op = cs->ops->require_space(cs, sizeof(*op));
357 op->opcode = WINED3D_CS_OP_SET_RENDER_TARGET;
358 op->render_target_idx = render_target_idx;
359 op->render_target = render_target;
361 cs->ops->submit(cs);
364 static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void *data)
366 const struct wined3d_cs_set_depth_stencil *op = data;
367 struct wined3d_device *device = cs->device;
368 struct wined3d_surface *prev;
370 if ((prev = cs->state.fb->depth_stencil))
372 if (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
373 || prev->flags & SFLAG_DISCARD)
375 surface_modify_ds_location(prev, SFLAG_DISCARDED,
376 prev->resource.width, prev->resource.height);
377 if (prev == device->onscreen_depth_stencil)
379 wined3d_surface_decref(device->onscreen_depth_stencil);
380 device->onscreen_depth_stencil = NULL;
385 cs->fb.depth_stencil = op->depth_stencil;
387 if (!prev != !op->depth_stencil)
389 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
390 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
391 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE));
392 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
393 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
395 else if (prev && prev->resource.format->depth_size != op->depth_stencil->resource.format->depth_size)
397 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
400 device_invalidate_state(device, STATE_FRAMEBUFFER);
403 void wined3d_cs_emit_set_depth_stencil(struct wined3d_cs *cs, struct wined3d_surface *depth_stencil)
405 struct wined3d_cs_set_depth_stencil *op;
407 op = cs->ops->require_space(cs, sizeof(*op));
408 op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL;
409 op->depth_stencil = depth_stencil;
411 cs->ops->submit(cs);
414 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data)
416 const struct wined3d_cs_set_vertex_declaration *op = data;
418 cs->state.vertex_declaration = op->declaration;
419 device_invalidate_state(cs->device, STATE_VDECL);
422 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration)
424 struct wined3d_cs_set_vertex_declaration *op;
426 op = cs->ops->require_space(cs, sizeof(*op));
427 op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION;
428 op->declaration = declaration;
430 cs->ops->submit(cs);
433 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data)
435 const struct wined3d_cs_set_stream_source *op = data;
436 struct wined3d_stream_state *stream;
437 struct wined3d_buffer *prev;
439 stream = &cs->state.streams[op->stream_idx];
440 prev = stream->buffer;
441 stream->buffer = op->buffer;
442 stream->offset = op->offset;
443 stream->stride = op->stride;
445 if (op->buffer)
446 InterlockedIncrement(&op->buffer->resource.bind_count);
447 if (prev)
448 InterlockedDecrement(&prev->resource.bind_count);
450 device_invalidate_state(cs->device, STATE_STREAMSRC);
453 void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx,
454 struct wined3d_buffer *buffer, UINT offset, UINT stride)
456 struct wined3d_cs_set_stream_source *op;
458 op = cs->ops->require_space(cs, sizeof(*op));
459 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE;
460 op->stream_idx = stream_idx;
461 op->buffer = buffer;
462 op->offset = offset;
463 op->stride = stride;
465 cs->ops->submit(cs);
468 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data)
470 const struct wined3d_cs_set_stream_source_freq *op = data;
471 struct wined3d_stream_state *stream;
473 stream = &cs->state.streams[op->stream_idx];
474 stream->frequency = op->frequency;
475 stream->flags = op->flags;
477 device_invalidate_state(cs->device, STATE_STREAMSRC);
480 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags)
482 struct wined3d_cs_set_stream_source_freq *op;
484 op = cs->ops->require_space(cs, sizeof(*op));
485 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ;
486 op->stream_idx = stream_idx;
487 op->frequency = frequency;
488 op->flags = flags;
490 cs->ops->submit(cs);
493 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data)
495 const struct wined3d_cs_set_stream_output *op = data;
496 struct wined3d_stream_output *stream;
497 struct wined3d_buffer *prev;
499 stream = &cs->state.stream_output[op->stream_idx];
500 prev = stream->buffer;
501 stream->buffer = op->buffer;
502 stream->offset = op->offset;
504 if (op->buffer)
505 InterlockedIncrement(&op->buffer->resource.bind_count);
506 if (prev)
507 InterlockedDecrement(&prev->resource.bind_count);
510 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
511 struct wined3d_buffer *buffer, UINT offset)
513 struct wined3d_cs_set_stream_output *op;
515 op = cs->ops->require_space(cs, sizeof(*op));
516 op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT;
517 op->stream_idx = stream_idx;
518 op->buffer = buffer;
519 op->offset = offset;
521 cs->ops->submit(cs);
524 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data)
526 const struct wined3d_cs_set_index_buffer *op = data;
527 struct wined3d_buffer *prev;
529 prev = cs->state.index_buffer;
530 cs->state.index_buffer = op->buffer;
531 cs->state.index_format = op->format_id;
533 if (op->buffer)
534 InterlockedIncrement(&op->buffer->resource.bind_count);
535 if (prev)
536 InterlockedDecrement(&prev->resource.bind_count);
538 device_invalidate_state(cs->device, STATE_INDEXBUFFER);
541 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer,
542 enum wined3d_format_id format_id)
544 struct wined3d_cs_set_index_buffer *op;
546 op = cs->ops->require_space(cs, sizeof(*op));
547 op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER;
548 op->buffer = buffer;
549 op->format_id = format_id;
551 cs->ops->submit(cs);
554 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data)
556 const struct wined3d_cs_set_constant_buffer *op = data;
557 struct wined3d_buffer *prev;
559 prev = cs->state.cb[op->type][op->cb_idx];
560 cs->state.cb[op->type][op->cb_idx] = op->buffer;
562 if (op->buffer)
563 InterlockedIncrement(&op->buffer->resource.bind_count);
564 if (prev)
565 InterlockedDecrement(&prev->resource.bind_count);
568 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
569 UINT cb_idx, struct wined3d_buffer *buffer)
571 struct wined3d_cs_set_constant_buffer *op;
573 op = cs->ops->require_space(cs, sizeof(*op));
574 op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER;
575 op->type = type;
576 op->cb_idx = cb_idx;
577 op->buffer = buffer;
579 cs->ops->submit(cs);
582 static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
584 const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
585 const struct wined3d_cs_set_texture *op = data;
586 struct wined3d_texture *prev;
588 prev = cs->state.textures[op->stage];
589 cs->state.textures[op->stage] = op->texture;
591 if (op->texture)
593 if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
594 op->texture->sampler = op->stage;
596 if (!prev || op->texture->target != prev->target)
597 device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
599 if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
601 /* The source arguments for color and alpha ops have different
602 * meanings when a NULL texture is bound, so the COLOR_OP and
603 * ALPHA_OP have to be dirtified. */
604 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
605 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
609 if (prev)
611 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
613 unsigned int i;
615 /* Search for other stages the texture is bound to. Shouldn't
616 * happen if applications bind textures to a single stage only. */
617 TRACE("Searching for other stages the texture is bound to.\n");
618 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
620 if (cs->state.textures[i] == prev)
622 TRACE("Texture is also bound to stage %u.\n", i);
623 prev->sampler = i;
624 break;
629 if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
631 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
632 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
636 device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
639 void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
641 struct wined3d_cs_set_texture *op;
643 op = cs->ops->require_space(cs, sizeof(*op));
644 op->opcode = WINED3D_CS_OP_SET_TEXTURE;
645 op->stage = stage;
646 op->texture = texture;
648 cs->ops->submit(cs);
651 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
653 const struct wined3d_cs_set_sampler *op = data;
655 cs->state.sampler[op->type][op->sampler_idx] = op->sampler;
658 void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
659 UINT sampler_idx, struct wined3d_sampler *sampler)
661 struct wined3d_cs_set_sampler *op;
663 op = cs->ops->require_space(cs, sizeof(*op));
664 op->opcode = WINED3D_CS_OP_SET_SAMPLER;
665 op->type = type;
666 op->sampler_idx = sampler_idx;
667 op->sampler = sampler;
669 cs->ops->submit(cs);
672 static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data)
674 const struct wined3d_cs_set_shader *op = data;
676 cs->state.shader[op->type] = op->shader;
677 device_invalidate_state(cs->device, STATE_SHADER(op->type));
680 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader)
682 struct wined3d_cs_set_shader *op;
684 op = cs->ops->require_space(cs, sizeof(*op));
685 op->opcode = WINED3D_CS_OP_SET_SHADER;
686 op->type = type;
687 op->shader = shader;
689 cs->ops->submit(cs);
692 static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data)
694 const struct wined3d_cs_set_render_state *op = data;
696 cs->state.render_states[op->state] = op->value;
697 device_invalidate_state(cs->device, STATE_RENDER(op->state));
700 void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value)
702 struct wined3d_cs_set_render_state *op;
704 op = cs->ops->require_space(cs, sizeof(*op));
705 op->opcode = WINED3D_CS_OP_SET_RENDER_STATE;
706 op->state = state;
707 op->value = value;
709 cs->ops->submit(cs);
712 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
714 const struct wined3d_cs_set_texture_state *op = data;
716 cs->state.texture_states[op->stage][op->state] = op->value;
717 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state));
720 void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
721 enum wined3d_texture_stage_state state, DWORD value)
723 struct wined3d_cs_set_texture_state *op;
725 op = cs->ops->require_space(cs, sizeof(*op));
726 op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE;
727 op->stage = stage;
728 op->state = state;
729 op->value = value;
731 cs->ops->submit(cs);
734 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data)
736 const struct wined3d_cs_set_sampler_state *op = data;
738 cs->state.sampler_states[op->sampler_idx][op->state] = op->value;
739 device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx));
742 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
743 enum wined3d_sampler_state state, DWORD value)
745 struct wined3d_cs_set_sampler_state *op;
747 op = cs->ops->require_space(cs, sizeof(*op));
748 op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE;
749 op->sampler_idx = sampler_idx;
750 op->state = state;
751 op->value = value;
753 cs->ops->submit(cs);
756 static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data)
758 const struct wined3d_cs_set_transform *op = data;
760 cs->state.transforms[op->state] = *op->matrix;
761 if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->gl_info.limits.blends))
762 device_invalidate_state(cs->device, STATE_TRANSFORM(op->state));
765 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
766 const struct wined3d_matrix *matrix)
768 struct wined3d_cs_set_transform *op;
770 op = cs->ops->require_space(cs, sizeof(*op));
771 op->opcode = WINED3D_CS_OP_SET_TRANSFORM;
772 op->state = state;
773 op->matrix = matrix;
775 cs->ops->submit(cs);
778 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data)
780 const struct wined3d_cs_set_clip_plane *op = data;
782 cs->state.clip_planes[op->plane_idx] = *op->plane;
783 device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx));
786 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane)
788 struct wined3d_cs_set_clip_plane *op;
790 op = cs->ops->require_space(cs, sizeof(*op));
791 op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE;
792 op->plane_idx = plane_idx;
793 op->plane = plane;
795 cs->ops->submit(cs);
798 static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data)
800 const struct wined3d_cs_set_material *op = data;
802 cs->state.material = *op->material;
803 device_invalidate_state(cs->device, STATE_MATERIAL);
806 void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material)
808 struct wined3d_cs_set_material *op;
810 op = cs->ops->require_space(cs, sizeof(*op));
811 op->opcode = WINED3D_CS_OP_SET_MATERIAL;
812 op->material = material;
814 cs->ops->submit(cs);
817 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
819 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
820 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
821 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
822 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
823 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
824 /* WINED3D_CS_OP_SET_RENDER_TARGET */ wined3d_cs_exec_set_render_target,
825 /* WINED3D_CS_OP_SET_DEPTH_STENCIL */ wined3d_cs_exec_set_depth_stencil,
826 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
827 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
828 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
829 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output,
830 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
831 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer,
832 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
833 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler,
834 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader,
835 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state,
836 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state,
837 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state,
838 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform,
839 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane,
840 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material,
843 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
845 if (size > cs->data_size)
847 void *new_data;
849 size = max( size, cs->data_size * 2 );
850 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
851 return NULL;
853 cs->data_size = size;
854 cs->data = new_data;
857 return cs->data;
860 static void wined3d_cs_st_submit(struct wined3d_cs *cs)
862 enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
864 wined3d_cs_op_handlers[opcode](cs, cs->data);
867 static const struct wined3d_cs_ops wined3d_cs_st_ops =
869 wined3d_cs_st_require_space,
870 wined3d_cs_st_submit,
873 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
875 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
876 struct wined3d_cs *cs;
878 if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
879 return NULL;
881 if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
882 sizeof(*cs->fb.render_targets) * gl_info->limits.buffers)))
884 HeapFree(GetProcessHeap(), 0, cs);
885 return NULL;
888 if (FAILED(state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info,
889 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
891 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
892 HeapFree(GetProcessHeap(), 0, cs);
893 return NULL;
896 cs->ops = &wined3d_cs_st_ops;
897 cs->device = device;
899 cs->data_size = WINED3D_INITIAL_CS_SIZE;
900 if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
902 HeapFree(GetProcessHeap(), 0, cs);
903 return NULL;
906 return cs;
909 void wined3d_cs_destroy(struct wined3d_cs *cs)
911 state_cleanup(&cs->state);
912 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
913 HeapFree(GetProcessHeap(), 0, cs);