d3d8/tests: Use a separate device for texop_test().
[wine/multimedia.git] / dlls / wined3d / cs.c
blob9288b949d81ec10466ca24c2c58518d61db9048f
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,
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_render_target
100 enum wined3d_cs_op opcode;
101 UINT render_target_idx;
102 struct wined3d_surface *render_target;
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_render_target(struct wined3d_cs *cs, const void *data)
351 const struct wined3d_cs_set_render_target *op = data;
353 cs->state.fb->render_targets[op->render_target_idx] = op->render_target;
354 device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
357 void wined3d_cs_emit_set_render_target(struct wined3d_cs *cs, UINT render_target_idx,
358 struct wined3d_surface *render_target)
360 struct wined3d_cs_set_render_target *op;
362 op = cs->ops->require_space(cs, sizeof(*op));
363 op->opcode = WINED3D_CS_OP_SET_RENDER_TARGET;
364 op->render_target_idx = render_target_idx;
365 op->render_target = render_target;
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);
574 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
575 UINT cb_idx, struct wined3d_buffer *buffer)
577 struct wined3d_cs_set_constant_buffer *op;
579 op = cs->ops->require_space(cs, sizeof(*op));
580 op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER;
581 op->type = type;
582 op->cb_idx = cb_idx;
583 op->buffer = buffer;
585 cs->ops->submit(cs);
588 static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
590 const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
591 const struct wined3d_cs_set_texture *op = data;
592 struct wined3d_texture *prev;
594 prev = cs->state.textures[op->stage];
595 cs->state.textures[op->stage] = op->texture;
597 if (op->texture)
599 if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
600 op->texture->sampler = op->stage;
602 if (!prev || op->texture->target != prev->target)
603 device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
605 if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
607 /* The source arguments for color and alpha ops have different
608 * meanings when a NULL texture is bound, so the COLOR_OP and
609 * ALPHA_OP have to be dirtified. */
610 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
611 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
615 if (prev)
617 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
619 unsigned int i;
621 /* Search for other stages the texture is bound to. Shouldn't
622 * happen if applications bind textures to a single stage only. */
623 TRACE("Searching for other stages the texture is bound to.\n");
624 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
626 if (cs->state.textures[i] == prev)
628 TRACE("Texture is also bound to stage %u.\n", i);
629 prev->sampler = i;
630 break;
635 if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
637 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
638 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
642 device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
645 void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
647 struct wined3d_cs_set_texture *op;
649 op = cs->ops->require_space(cs, sizeof(*op));
650 op->opcode = WINED3D_CS_OP_SET_TEXTURE;
651 op->stage = stage;
652 op->texture = texture;
654 cs->ops->submit(cs);
657 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
659 const struct wined3d_cs_set_sampler *op = data;
661 cs->state.sampler[op->type][op->sampler_idx] = op->sampler;
664 void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
665 UINT sampler_idx, struct wined3d_sampler *sampler)
667 struct wined3d_cs_set_sampler *op;
669 op = cs->ops->require_space(cs, sizeof(*op));
670 op->opcode = WINED3D_CS_OP_SET_SAMPLER;
671 op->type = type;
672 op->sampler_idx = sampler_idx;
673 op->sampler = sampler;
675 cs->ops->submit(cs);
678 static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data)
680 const struct wined3d_cs_set_shader *op = data;
682 cs->state.shader[op->type] = op->shader;
683 device_invalidate_state(cs->device, STATE_SHADER(op->type));
686 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader)
688 struct wined3d_cs_set_shader *op;
690 op = cs->ops->require_space(cs, sizeof(*op));
691 op->opcode = WINED3D_CS_OP_SET_SHADER;
692 op->type = type;
693 op->shader = shader;
695 cs->ops->submit(cs);
698 static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data)
700 const struct wined3d_cs_set_render_state *op = data;
702 cs->state.render_states[op->state] = op->value;
703 device_invalidate_state(cs->device, STATE_RENDER(op->state));
706 void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value)
708 struct wined3d_cs_set_render_state *op;
710 op = cs->ops->require_space(cs, sizeof(*op));
711 op->opcode = WINED3D_CS_OP_SET_RENDER_STATE;
712 op->state = state;
713 op->value = value;
715 cs->ops->submit(cs);
718 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
720 const struct wined3d_cs_set_texture_state *op = data;
722 cs->state.texture_states[op->stage][op->state] = op->value;
723 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state));
726 void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
727 enum wined3d_texture_stage_state state, DWORD value)
729 struct wined3d_cs_set_texture_state *op;
731 op = cs->ops->require_space(cs, sizeof(*op));
732 op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE;
733 op->stage = stage;
734 op->state = state;
735 op->value = value;
737 cs->ops->submit(cs);
740 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data)
742 const struct wined3d_cs_set_sampler_state *op = data;
744 cs->state.sampler_states[op->sampler_idx][op->state] = op->value;
745 device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx));
748 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
749 enum wined3d_sampler_state state, DWORD value)
751 struct wined3d_cs_set_sampler_state *op;
753 op = cs->ops->require_space(cs, sizeof(*op));
754 op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE;
755 op->sampler_idx = sampler_idx;
756 op->state = state;
757 op->value = value;
759 cs->ops->submit(cs);
762 static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data)
764 const struct wined3d_cs_set_transform *op = data;
766 cs->state.transforms[op->state] = *op->matrix;
767 if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->gl_info.limits.blends))
768 device_invalidate_state(cs->device, STATE_TRANSFORM(op->state));
771 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
772 const struct wined3d_matrix *matrix)
774 struct wined3d_cs_set_transform *op;
776 op = cs->ops->require_space(cs, sizeof(*op));
777 op->opcode = WINED3D_CS_OP_SET_TRANSFORM;
778 op->state = state;
779 op->matrix = matrix;
781 cs->ops->submit(cs);
784 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data)
786 const struct wined3d_cs_set_clip_plane *op = data;
788 cs->state.clip_planes[op->plane_idx] = *op->plane;
789 device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx));
792 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane)
794 struct wined3d_cs_set_clip_plane *op;
796 op = cs->ops->require_space(cs, sizeof(*op));
797 op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE;
798 op->plane_idx = plane_idx;
799 op->plane = plane;
801 cs->ops->submit(cs);
804 static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data)
806 const struct wined3d_cs_set_material *op = data;
808 cs->state.material = *op->material;
809 device_invalidate_state(cs->device, STATE_MATERIAL);
812 void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material)
814 struct wined3d_cs_set_material *op;
816 op = cs->ops->require_space(cs, sizeof(*op));
817 op->opcode = WINED3D_CS_OP_SET_MATERIAL;
818 op->material = material;
820 cs->ops->submit(cs);
823 static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data)
825 struct wined3d_adapter *adapter = cs->device->adapter;
826 HRESULT hr;
828 state_cleanup(&cs->state);
829 memset(&cs->state, 0, sizeof(cs->state));
830 if (FAILED(hr = state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info,
831 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
832 ERR("Failed to initialize CS state, hr %#x.\n", hr);
835 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs)
837 struct wined3d_cs_reset_state *op;
839 op = cs->ops->require_space(cs, sizeof(*op));
840 op->opcode = WINED3D_CS_OP_RESET_STATE;
842 cs->ops->submit(cs);
845 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
847 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
848 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
849 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
850 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
851 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
852 /* WINED3D_CS_OP_SET_RENDER_TARGET */ wined3d_cs_exec_set_render_target,
853 /* WINED3D_CS_OP_SET_DEPTH_STENCIL */ wined3d_cs_exec_set_depth_stencil,
854 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
855 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
856 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
857 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output,
858 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
859 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer,
860 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
861 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler,
862 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader,
863 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state,
864 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state,
865 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state,
866 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform,
867 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane,
868 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material,
869 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state,
872 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
874 if (size > cs->data_size)
876 void *new_data;
878 size = max( size, cs->data_size * 2 );
879 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
880 return NULL;
882 cs->data_size = size;
883 cs->data = new_data;
886 return cs->data;
889 static void wined3d_cs_st_submit(struct wined3d_cs *cs)
891 enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
893 wined3d_cs_op_handlers[opcode](cs, cs->data);
896 static const struct wined3d_cs_ops wined3d_cs_st_ops =
898 wined3d_cs_st_require_space,
899 wined3d_cs_st_submit,
902 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
904 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
905 struct wined3d_cs *cs;
907 if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
908 return NULL;
910 if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
911 sizeof(*cs->fb.render_targets) * gl_info->limits.buffers)))
913 HeapFree(GetProcessHeap(), 0, cs);
914 return NULL;
917 if (FAILED(state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info,
918 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT)))
920 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
921 HeapFree(GetProcessHeap(), 0, cs);
922 return NULL;
925 cs->ops = &wined3d_cs_st_ops;
926 cs->device = device;
928 cs->data_size = WINED3D_INITIAL_CS_SIZE;
929 if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
931 HeapFree(GetProcessHeap(), 0, cs);
932 return NULL;
935 return cs;
938 void wined3d_cs_destroy(struct wined3d_cs *cs)
940 state_cleanup(&cs->state);
941 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
942 HeapFree(GetProcessHeap(), 0, cs->data);
943 HeapFree(GetProcessHeap(), 0, cs);