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_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
;
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_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
;
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_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
;
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
);
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
;
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
;
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
));
617 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
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
);
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
;
652 op
->texture
= texture
;
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
;
672 op
->sampler_idx
= sampler_idx
;
673 op
->sampler
= sampler
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
823 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
825 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
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
;
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
)
878 size
= max( size
, cs
->data_size
* 2 );
879 if (!(new_data
= HeapReAlloc(GetProcessHeap(), 0, cs
->data
, size
)))
882 cs
->data_size
= size
;
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
))))
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
);
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
);
925 cs
->ops
= &wined3d_cs_st_ops
;
928 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
929 if (!(cs
->data
= HeapAlloc(GetProcessHeap(), 0, cs
->data_size
)))
931 HeapFree(GetProcessHeap(), 0, 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
);