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
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
25 #define WINED3D_INITIAL_CS_SIZE 4096
29 WINED3D_CS_OP_PRESENT
,
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
;
61 const RGNDATA
*dirty_region
;
65 struct wined3d_cs_clear
67 enum wined3d_cs_op opcode
;
71 const struct wined3d_color
*color
;
76 struct wined3d_cs_draw
78 enum wined3d_cs_op opcode
;
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
;
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
;
121 struct wined3d_buffer
*buffer
;
126 struct wined3d_cs_set_stream_source_freq
128 enum wined3d_cs_op opcode
;
134 struct wined3d_cs_set_stream_output
136 enum wined3d_cs_op opcode
;
138 struct wined3d_buffer
*buffer
;
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
;
154 struct wined3d_buffer
*buffer
;
157 struct wined3d_cs_set_texture
159 enum wined3d_cs_op opcode
;
161 struct wined3d_texture
*texture
;
164 struct wined3d_cs_set_sampler
166 enum wined3d_cs_op opcode
;
167 enum wined3d_shader_type type
;
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
;
186 struct wined3d_cs_set_texture_state
188 enum wined3d_cs_op opcode
;
190 enum wined3d_texture_stage_state state
;
194 struct wined3d_cs_set_sampler_state
196 enum wined3d_cs_op opcode
;
198 enum wined3d_sampler_state state
;
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
;
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
;
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
;
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
;
282 op
->stencil
= stencil
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
452 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
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
;
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
;
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
;
511 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
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
;
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
;
540 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
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
;
555 op
->format_id
= format_id
;
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
;
569 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
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
;
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
;
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
));
619 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
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
);
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
;
654 op
->texture
= texture
;
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
;
674 op
->sampler_idx
= sampler_idx
;
675 op
->sampler
= sampler
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
825 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
827 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
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
;
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
)
880 size
= max( size
, cs
->data_size
* 2 );
881 if (!(new_data
= HeapReAlloc(GetProcessHeap(), 0, cs
->data
, size
)))
884 cs
->data_size
= size
;
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
))))
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
);
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
);
927 cs
->ops
= &wined3d_cs_st_ops
;
930 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
931 if (!(cs
->data
= HeapAlloc(GetProcessHeap(), 0, cs
->data_size
)))
933 HeapFree(GetProcessHeap(), 0, 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
);