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