wined3d: Use rendertarget views for color output instead of surfaces.
[wine.git] / dlls / wined3d / cs.c
blobdf1c4e35ea9bf85c46fb9a4740f153b75ba2fb73
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_RENDERTARGET_VIEW,
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,
51 WINED3D_CS_OP_RESET_STATE,
54 struct wined3d_cs_present
56 enum wined3d_cs_op opcode;
57 HWND dst_window_override;
58 struct wined3d_swapchain *swapchain;
59 const RECT *src_rect;
60 const RECT *dst_rect;
61 const RGNDATA *dirty_region;
62 DWORD flags;
65 struct wined3d_cs_clear
67 enum wined3d_cs_op opcode;
68 DWORD rect_count;
69 const RECT *rects;
70 DWORD flags;
71 const struct wined3d_color *color;
72 float depth;
73 DWORD stencil;
76 struct wined3d_cs_draw
78 enum wined3d_cs_op opcode;
79 UINT start_idx;
80 UINT index_count;
81 UINT start_instance;
82 UINT instance_count;
83 BOOL indexed;
86 struct wined3d_cs_set_viewport
88 enum wined3d_cs_op opcode;
89 const struct wined3d_viewport *viewport;
92 struct wined3d_cs_set_scissor_rect
94 enum wined3d_cs_op opcode;
95 const RECT *rect;
98 struct wined3d_cs_set_rendertarget_view
100 enum wined3d_cs_op opcode;
101 unsigned int view_idx;
102 struct wined3d_rendertarget_view *view;
105 struct wined3d_cs_set_depth_stencil
107 enum wined3d_cs_op opcode;
108 struct wined3d_surface *depth_stencil;
111 struct wined3d_cs_set_vertex_declaration
113 enum wined3d_cs_op opcode;
114 struct wined3d_vertex_declaration *declaration;
117 struct wined3d_cs_set_stream_source
119 enum wined3d_cs_op opcode;
120 UINT stream_idx;
121 struct wined3d_buffer *buffer;
122 UINT offset;
123 UINT stride;
126 struct wined3d_cs_set_stream_source_freq
128 enum wined3d_cs_op opcode;
129 UINT stream_idx;
130 UINT frequency;
131 UINT flags;
134 struct wined3d_cs_set_stream_output
136 enum wined3d_cs_op opcode;
137 UINT stream_idx;
138 struct wined3d_buffer *buffer;
139 UINT offset;
142 struct wined3d_cs_set_index_buffer
144 enum wined3d_cs_op opcode;
145 struct wined3d_buffer *buffer;
146 enum wined3d_format_id format_id;
149 struct wined3d_cs_set_constant_buffer
151 enum wined3d_cs_op opcode;
152 enum wined3d_shader_type type;
153 UINT cb_idx;
154 struct wined3d_buffer *buffer;
157 struct wined3d_cs_set_texture
159 enum wined3d_cs_op opcode;
160 UINT stage;
161 struct wined3d_texture *texture;
164 struct wined3d_cs_set_sampler
166 enum wined3d_cs_op opcode;
167 enum wined3d_shader_type type;
168 UINT sampler_idx;
169 struct wined3d_sampler *sampler;
172 struct wined3d_cs_set_shader
174 enum wined3d_cs_op opcode;
175 enum wined3d_shader_type type;
176 struct wined3d_shader *shader;
179 struct wined3d_cs_set_render_state
181 enum wined3d_cs_op opcode;
182 enum wined3d_render_state state;
183 DWORD value;
186 struct wined3d_cs_set_texture_state
188 enum wined3d_cs_op opcode;
189 UINT stage;
190 enum wined3d_texture_stage_state state;
191 DWORD value;
194 struct wined3d_cs_set_sampler_state
196 enum wined3d_cs_op opcode;
197 UINT sampler_idx;
198 enum wined3d_sampler_state state;
199 DWORD value;
202 struct wined3d_cs_set_transform
204 enum wined3d_cs_op opcode;
205 enum wined3d_transform_state state;
206 const struct wined3d_matrix *matrix;
209 struct wined3d_cs_set_clip_plane
211 enum wined3d_cs_op opcode;
212 UINT plane_idx;
213 const struct wined3d_vec4 *plane;
216 struct wined3d_cs_set_material
218 enum wined3d_cs_op opcode;
219 const struct wined3d_material *material;
222 struct wined3d_cs_reset_state
224 enum wined3d_cs_op opcode;
227 static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
229 const struct wined3d_cs_present *op = data;
230 struct wined3d_swapchain *swapchain;
232 swapchain = op->swapchain;
233 wined3d_swapchain_set_window(swapchain, op->dst_window_override);
235 swapchain->swapchain_ops->swapchain_present(swapchain,
236 op->src_rect, op->dst_rect, op->dirty_region, op->flags);
239 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
240 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
241 const RGNDATA *dirty_region, DWORD flags)
243 struct wined3d_cs_present *op;
245 op = cs->ops->require_space(cs, sizeof(*op));
246 op->opcode = WINED3D_CS_OP_PRESENT;
247 op->dst_window_override = dst_window_override;
248 op->swapchain = swapchain;
249 op->src_rect = src_rect;
250 op->dst_rect = dst_rect;
251 op->dirty_region = dirty_region;
252 op->flags = flags;
254 cs->ops->submit(cs);
257 static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
259 const struct wined3d_cs_clear *op = data;
260 struct wined3d_device *device;
261 RECT draw_rect;
263 device = cs->device;
264 wined3d_get_draw_rect(&device->state, &draw_rect);
265 device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
266 &device->fb, op->rect_count, op->rects, &draw_rect, op->flags,
267 op->color, op->depth, op->stencil);
270 void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
271 DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
273 struct wined3d_cs_clear *op;
275 op = cs->ops->require_space(cs, sizeof(*op));
276 op->opcode = WINED3D_CS_OP_CLEAR;
277 op->rect_count = rect_count;
278 op->rects = rects;
279 op->flags = flags;
280 op->color = color;
281 op->depth = depth;
282 op->stencil = stencil;
284 cs->ops->submit(cs);
287 static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
289 const struct wined3d_cs_draw *op = data;
291 draw_primitive(cs->device, op->start_idx, op->index_count,
292 op->start_instance, op->instance_count, op->indexed);
295 void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count,
296 UINT start_instance, UINT instance_count, BOOL indexed)
298 struct wined3d_cs_draw *op;
300 op = cs->ops->require_space(cs, sizeof(*op));
301 op->opcode = WINED3D_CS_OP_DRAW;
302 op->start_idx = start_idx;
303 op->index_count = index_count;
304 op->start_instance = start_instance;
305 op->instance_count = instance_count;
306 op->indexed = indexed;
308 cs->ops->submit(cs);
311 static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
313 const struct wined3d_cs_set_viewport *op = data;
315 cs->state.viewport = *op->viewport;
316 device_invalidate_state(cs->device, STATE_VIEWPORT);
319 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
321 struct wined3d_cs_set_viewport *op;
323 op = cs->ops->require_space(cs, sizeof(*op));
324 op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
325 op->viewport = viewport;
327 cs->ops->submit(cs);
330 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
332 const struct wined3d_cs_set_scissor_rect *op = data;
334 cs->state.scissor_rect = *op->rect;
335 device_invalidate_state(cs->device, STATE_SCISSORRECT);
338 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
340 struct wined3d_cs_set_scissor_rect *op;
342 op = cs->ops->require_space(cs, sizeof(*op));
343 op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
344 op->rect = rect;
346 cs->ops->submit(cs);
349 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
351 const struct wined3d_cs_set_rendertarget_view *op = data;
353 cs->state.fb->render_targets[op->view_idx] = op->view;
354 device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
357 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
358 struct wined3d_rendertarget_view *view)
360 struct wined3d_cs_set_rendertarget_view *op;
362 op = cs->ops->require_space(cs, sizeof(*op));
363 op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
364 op->view_idx = view_idx;
365 op->view = view;
367 cs->ops->submit(cs);
370 static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void *data)
372 const struct wined3d_cs_set_depth_stencil *op = data;
373 struct wined3d_device *device = cs->device;
374 struct wined3d_surface *prev;
376 if ((prev = cs->state.fb->depth_stencil))
378 if (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
379 || prev->flags & SFLAG_DISCARD)
381 surface_modify_ds_location(prev, WINED3D_LOCATION_DISCARDED,
382 prev->resource.width, prev->resource.height);
383 if (prev == device->onscreen_depth_stencil)
385 wined3d_surface_decref(device->onscreen_depth_stencil);
386 device->onscreen_depth_stencil = NULL;
391 cs->fb.depth_stencil = op->depth_stencil;
393 if (!prev != !op->depth_stencil)
395 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
396 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
397 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE));
398 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
399 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
401 else if (prev && prev->resource.format->depth_size != op->depth_stencil->resource.format->depth_size)
403 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
406 device_invalidate_state(device, STATE_FRAMEBUFFER);
409 void wined3d_cs_emit_set_depth_stencil(struct wined3d_cs *cs, struct wined3d_surface *depth_stencil)
411 struct wined3d_cs_set_depth_stencil *op;
413 op = cs->ops->require_space(cs, sizeof(*op));
414 op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL;
415 op->depth_stencil = depth_stencil;
417 cs->ops->submit(cs);
420 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data)
422 const struct wined3d_cs_set_vertex_declaration *op = data;
424 cs->state.vertex_declaration = op->declaration;
425 device_invalidate_state(cs->device, STATE_VDECL);
428 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration)
430 struct wined3d_cs_set_vertex_declaration *op;
432 op = cs->ops->require_space(cs, sizeof(*op));
433 op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION;
434 op->declaration = declaration;
436 cs->ops->submit(cs);
439 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data)
441 const struct wined3d_cs_set_stream_source *op = data;
442 struct wined3d_stream_state *stream;
443 struct wined3d_buffer *prev;
445 stream = &cs->state.streams[op->stream_idx];
446 prev = stream->buffer;
447 stream->buffer = op->buffer;
448 stream->offset = op->offset;
449 stream->stride = op->stride;
451 if (op->buffer)
452 InterlockedIncrement(&op->buffer->resource.bind_count);
453 if (prev)
454 InterlockedDecrement(&prev->resource.bind_count);
456 device_invalidate_state(cs->device, STATE_STREAMSRC);
459 void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx,
460 struct wined3d_buffer *buffer, UINT offset, UINT stride)
462 struct wined3d_cs_set_stream_source *op;
464 op = cs->ops->require_space(cs, sizeof(*op));
465 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE;
466 op->stream_idx = stream_idx;
467 op->buffer = buffer;
468 op->offset = offset;
469 op->stride = stride;
471 cs->ops->submit(cs);
474 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data)
476 const struct wined3d_cs_set_stream_source_freq *op = data;
477 struct wined3d_stream_state *stream;
479 stream = &cs->state.streams[op->stream_idx];
480 stream->frequency = op->frequency;
481 stream->flags = op->flags;
483 device_invalidate_state(cs->device, STATE_STREAMSRC);
486 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags)
488 struct wined3d_cs_set_stream_source_freq *op;
490 op = cs->ops->require_space(cs, sizeof(*op));
491 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ;
492 op->stream_idx = stream_idx;
493 op->frequency = frequency;
494 op->flags = flags;
496 cs->ops->submit(cs);
499 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data)
501 const struct wined3d_cs_set_stream_output *op = data;
502 struct wined3d_stream_output *stream;
503 struct wined3d_buffer *prev;
505 stream = &cs->state.stream_output[op->stream_idx];
506 prev = stream->buffer;
507 stream->buffer = op->buffer;
508 stream->offset = op->offset;
510 if (op->buffer)
511 InterlockedIncrement(&op->buffer->resource.bind_count);
512 if (prev)
513 InterlockedDecrement(&prev->resource.bind_count);
516 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
517 struct wined3d_buffer *buffer, UINT offset)
519 struct wined3d_cs_set_stream_output *op;
521 op = cs->ops->require_space(cs, sizeof(*op));
522 op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT;
523 op->stream_idx = stream_idx;
524 op->buffer = buffer;
525 op->offset = offset;
527 cs->ops->submit(cs);
530 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data)
532 const struct wined3d_cs_set_index_buffer *op = data;
533 struct wined3d_buffer *prev;
535 prev = cs->state.index_buffer;
536 cs->state.index_buffer = op->buffer;
537 cs->state.index_format = op->format_id;
539 if (op->buffer)
540 InterlockedIncrement(&op->buffer->resource.bind_count);
541 if (prev)
542 InterlockedDecrement(&prev->resource.bind_count);
544 device_invalidate_state(cs->device, STATE_INDEXBUFFER);
547 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer,
548 enum wined3d_format_id format_id)
550 struct wined3d_cs_set_index_buffer *op;
552 op = cs->ops->require_space(cs, sizeof(*op));
553 op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER;
554 op->buffer = buffer;
555 op->format_id = format_id;
557 cs->ops->submit(cs);
560 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data)
562 const struct wined3d_cs_set_constant_buffer *op = data;
563 struct wined3d_buffer *prev;
565 prev = cs->state.cb[op->type][op->cb_idx];
566 cs->state.cb[op->type][op->cb_idx] = op->buffer;
568 if (op->buffer)
569 InterlockedIncrement(&op->buffer->resource.bind_count);
570 if (prev)
571 InterlockedDecrement(&prev->resource.bind_count);
573 device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type));
576 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
577 UINT cb_idx, struct wined3d_buffer *buffer)
579 struct wined3d_cs_set_constant_buffer *op;
581 op = cs->ops->require_space(cs, sizeof(*op));
582 op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER;
583 op->type = type;
584 op->cb_idx = cb_idx;
585 op->buffer = buffer;
587 cs->ops->submit(cs);
590 static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
592 const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
593 const struct wined3d_cs_set_texture *op = data;
594 struct wined3d_texture *prev;
596 prev = cs->state.textures[op->stage];
597 cs->state.textures[op->stage] = op->texture;
599 if (op->texture)
601 if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
602 op->texture->sampler = op->stage;
604 if (!prev || op->texture->target != prev->target)
605 device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
607 if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
609 /* The source arguments for color and alpha ops have different
610 * meanings when a NULL texture is bound, so the COLOR_OP and
611 * ALPHA_OP have to be dirtified. */
612 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
613 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
617 if (prev)
619 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
621 unsigned int i;
623 /* Search for other stages the texture is bound to. Shouldn't
624 * happen if applications bind textures to a single stage only. */
625 TRACE("Searching for other stages the texture is bound to.\n");
626 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
628 if (cs->state.textures[i] == prev)
630 TRACE("Texture is also bound to stage %u.\n", i);
631 prev->sampler = i;
632 break;
637 if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
639 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
640 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
644 device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
647 void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
649 struct wined3d_cs_set_texture *op;
651 op = cs->ops->require_space(cs, sizeof(*op));
652 op->opcode = WINED3D_CS_OP_SET_TEXTURE;
653 op->stage = stage;
654 op->texture = texture;
656 cs->ops->submit(cs);
659 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
661 const struct wined3d_cs_set_sampler *op = data;
663 cs->state.sampler[op->type][op->sampler_idx] = op->sampler;
666 void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
667 UINT sampler_idx, struct wined3d_sampler *sampler)
669 struct wined3d_cs_set_sampler *op;
671 op = cs->ops->require_space(cs, sizeof(*op));
672 op->opcode = WINED3D_CS_OP_SET_SAMPLER;
673 op->type = type;
674 op->sampler_idx = sampler_idx;
675 op->sampler = sampler;
677 cs->ops->submit(cs);
680 static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data)
682 const struct wined3d_cs_set_shader *op = data;
684 cs->state.shader[op->type] = op->shader;
685 device_invalidate_state(cs->device, STATE_SHADER(op->type));
688 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader)
690 struct wined3d_cs_set_shader *op;
692 op = cs->ops->require_space(cs, sizeof(*op));
693 op->opcode = WINED3D_CS_OP_SET_SHADER;
694 op->type = type;
695 op->shader = shader;
697 cs->ops->submit(cs);
700 static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data)
702 const struct wined3d_cs_set_render_state *op = data;
704 cs->state.render_states[op->state] = op->value;
705 device_invalidate_state(cs->device, STATE_RENDER(op->state));
708 void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value)
710 struct wined3d_cs_set_render_state *op;
712 op = cs->ops->require_space(cs, sizeof(*op));
713 op->opcode = WINED3D_CS_OP_SET_RENDER_STATE;
714 op->state = state;
715 op->value = value;
717 cs->ops->submit(cs);
720 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
722 const struct wined3d_cs_set_texture_state *op = data;
724 cs->state.texture_states[op->stage][op->state] = op->value;
725 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state));
728 void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
729 enum wined3d_texture_stage_state state, DWORD value)
731 struct wined3d_cs_set_texture_state *op;
733 op = cs->ops->require_space(cs, sizeof(*op));
734 op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE;
735 op->stage = stage;
736 op->state = state;
737 op->value = value;
739 cs->ops->submit(cs);
742 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data)
744 const struct wined3d_cs_set_sampler_state *op = data;
746 cs->state.sampler_states[op->sampler_idx][op->state] = op->value;
747 device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx));
750 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
751 enum wined3d_sampler_state state, DWORD value)
753 struct wined3d_cs_set_sampler_state *op;
755 op = cs->ops->require_space(cs, sizeof(*op));
756 op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE;
757 op->sampler_idx = sampler_idx;
758 op->state = state;
759 op->value = value;
761 cs->ops->submit(cs);
764 static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data)
766 const struct wined3d_cs_set_transform *op = data;
768 cs->state.transforms[op->state] = *op->matrix;
769 if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->gl_info.limits.blends))
770 device_invalidate_state(cs->device, STATE_TRANSFORM(op->state));
773 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
774 const struct wined3d_matrix *matrix)
776 struct wined3d_cs_set_transform *op;
778 op = cs->ops->require_space(cs, sizeof(*op));
779 op->opcode = WINED3D_CS_OP_SET_TRANSFORM;
780 op->state = state;
781 op->matrix = matrix;
783 cs->ops->submit(cs);
786 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data)
788 const struct wined3d_cs_set_clip_plane *op = data;
790 cs->state.clip_planes[op->plane_idx] = *op->plane;
791 device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx));
794 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane)
796 struct wined3d_cs_set_clip_plane *op;
798 op = cs->ops->require_space(cs, sizeof(*op));
799 op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE;
800 op->plane_idx = plane_idx;
801 op->plane = plane;
803 cs->ops->submit(cs);
806 static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data)
808 const struct wined3d_cs_set_material *op = data;
810 cs->state.material = *op->material;
811 device_invalidate_state(cs->device, STATE_MATERIAL);
814 void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material)
816 struct wined3d_cs_set_material *op;
818 op = cs->ops->require_space(cs, sizeof(*op));
819 op->opcode = WINED3D_CS_OP_SET_MATERIAL;
820 op->material = material;
822 cs->ops->submit(cs);
825 static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data)
827 struct wined3d_adapter *adapter = cs->device->adapter;
828 HRESULT hr;
830 state_cleanup(&cs->state);
831 memset(&cs->state, 0, sizeof(cs->state));
832 if (FAILED(hr = state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info,
833 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
834 ERR("Failed to initialize CS state, hr %#x.\n", hr);
837 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs)
839 struct wined3d_cs_reset_state *op;
841 op = cs->ops->require_space(cs, sizeof(*op));
842 op->opcode = WINED3D_CS_OP_RESET_STATE;
844 cs->ops->submit(cs);
847 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
849 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
850 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
851 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
852 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
853 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
854 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
855 /* WINED3D_CS_OP_SET_DEPTH_STENCIL */ wined3d_cs_exec_set_depth_stencil,
856 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
857 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
858 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
859 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output,
860 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
861 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer,
862 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
863 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler,
864 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader,
865 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state,
866 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state,
867 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state,
868 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform,
869 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane,
870 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material,
871 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state,
874 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
876 if (size > cs->data_size)
878 void *new_data;
880 size = max( size, cs->data_size * 2 );
881 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
882 return NULL;
884 cs->data_size = size;
885 cs->data = new_data;
888 return cs->data;
891 static void wined3d_cs_st_submit(struct wined3d_cs *cs)
893 enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
895 wined3d_cs_op_handlers[opcode](cs, cs->data);
898 static const struct wined3d_cs_ops wined3d_cs_st_ops =
900 wined3d_cs_st_require_space,
901 wined3d_cs_st_submit,
904 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
906 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
907 struct wined3d_cs *cs;
909 if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
910 return NULL;
912 if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
913 sizeof(*cs->fb.render_targets) * gl_info->limits.buffers)))
915 HeapFree(GetProcessHeap(), 0, cs);
916 return NULL;
919 if (FAILED(state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info,
920 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
922 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
923 HeapFree(GetProcessHeap(), 0, cs);
924 return NULL;
927 cs->ops = &wined3d_cs_st_ops;
928 cs->device = device;
930 cs->data_size = WINED3D_INITIAL_CS_SIZE;
931 if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
933 HeapFree(GetProcessHeap(), 0, cs);
934 return NULL;
937 return cs;
940 void wined3d_cs_destroy(struct wined3d_cs *cs)
942 state_cleanup(&cs->state);
943 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
944 HeapFree(GetProcessHeap(), 0, cs->data);
945 HeapFree(GetProcessHeap(), 0, cs);