winex11: Keep the result string in the IME UI window procedure.
[wine.git] / dlls / wined3d / drawprim.c
blob95e79f777ac2819f2ec3eb9ad33c07e97e73f7eb
1 /*
2 * WINED3D draw functions
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2006, 2008 Henri Verbeet
9 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * Copyright 2009 Henri Verbeet for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "config.h"
28 #include "wine/port.h"
30 #include "wined3d_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
33 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d);
36 /* Context activation is done by the caller. */
37 static void draw_primitive_arrays(struct wined3d_context *context, const struct wined3d_state *state,
38 const void *idx_data, unsigned int idx_size, int base_vertex_idx, unsigned int start_idx,
39 unsigned int count, unsigned int start_instance, unsigned int instance_count)
41 const struct wined3d_ffp_attrib_ops *ops = &context->d3d_info->ffp_attrib_ops;
42 GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
43 const struct wined3d_stream_info *si = &context->stream_info;
44 unsigned int instanced_elements[ARRAY_SIZE(si->elements)];
45 const struct wined3d_gl_info *gl_info = context->gl_info;
46 unsigned int instanced_element_count = 0;
47 unsigned int i, j;
49 if (!instance_count)
51 if (!idx_size)
53 gl_info->gl_ops.gl.p_glDrawArrays(state->gl_primitive_type, start_idx, count);
54 checkGLcall("glDrawArrays");
55 return;
58 if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
60 GL_EXTCALL(glDrawElementsBaseVertex(state->gl_primitive_type, count, idx_type,
61 (const char *)idx_data + (idx_size * start_idx), base_vertex_idx));
62 checkGLcall("glDrawElementsBaseVertex");
63 return;
66 gl_info->gl_ops.gl.p_glDrawElements(state->gl_primitive_type, count,
67 idx_type, (const char *)idx_data + (idx_size * start_idx));
68 checkGLcall("glDrawElements");
69 return;
72 if (start_instance && !(gl_info->supported[ARB_BASE_INSTANCE] && gl_info->supported[ARB_INSTANCED_ARRAYS]))
73 FIXME("Start instance (%u) not supported.\n", start_instance);
75 if (gl_info->supported[ARB_INSTANCED_ARRAYS])
77 if (!idx_size)
79 if (gl_info->supported[ARB_BASE_INSTANCE])
81 GL_EXTCALL(glDrawArraysInstancedBaseInstance(state->gl_primitive_type, start_idx, count, instance_count, start_instance));
82 checkGLcall("glDrawArraysInstancedBaseInstance");
83 return;
86 GL_EXTCALL(glDrawArraysInstanced(state->gl_primitive_type, start_idx, count, instance_count));
87 checkGLcall("glDrawArraysInstanced");
88 return;
91 if (gl_info->supported[ARB_BASE_INSTANCE])
93 GL_EXTCALL(glDrawElementsInstancedBaseVertexBaseInstance(state->gl_primitive_type, count, idx_type,
94 (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_idx, start_instance));
95 checkGLcall("glDrawElementsInstancedBaseVertexBaseInstance");
96 return;
98 if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
100 GL_EXTCALL(glDrawElementsInstancedBaseVertex(state->gl_primitive_type, count, idx_type,
101 (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_idx));
102 checkGLcall("glDrawElementsInstancedBaseVertex");
103 return;
106 GL_EXTCALL(glDrawElementsInstanced(state->gl_primitive_type, count, idx_type,
107 (const char *)idx_data + (idx_size * start_idx), instance_count));
108 checkGLcall("glDrawElementsInstanced");
109 return;
112 /* Instancing emulation by mixing immediate mode and arrays. */
114 /* This is a nasty thing. MSDN says no hardware supports this and
115 * applications have to use software vertex processing. We don't support
116 * this for now.
118 * Shouldn't be too hard to support with OpenGL, in theory just call
119 * glDrawArrays() instead of drawElements(). But the stream fequency value
120 * has a different meaning in that situation. */
121 if (!idx_size)
123 FIXME("Non-indexed instanced drawing is not supported\n");
124 return;
127 for (i = 0; i < ARRAY_SIZE(si->elements); ++i)
129 if (!(si->use_map & (1u << i)))
130 continue;
132 if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
133 instanced_elements[instanced_element_count++] = i;
136 for (i = 0; i < instance_count; ++i)
138 /* Specify the instanced attributes using immediate mode calls. */
139 for (j = 0; j < instanced_element_count; ++j)
141 const struct wined3d_stream_info_element *element;
142 unsigned int element_idx;
143 const BYTE *ptr;
145 element_idx = instanced_elements[j];
146 element = &si->elements[element_idx];
147 ptr = element->data.addr + element->stride * i;
148 if (element->data.buffer_object)
149 ptr += (ULONG_PTR)wined3d_buffer_load_sysmem(state->streams[element->stream_idx].buffer, context);
150 ops->generic[element->format->emit_idx](element_idx, ptr);
153 if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
155 GL_EXTCALL(glDrawElementsBaseVertex(state->gl_primitive_type, count, idx_type,
156 (const char *)idx_data + (idx_size * start_idx), base_vertex_idx));
157 checkGLcall("glDrawElementsBaseVertex");
159 else
161 gl_info->gl_ops.gl.p_glDrawElements(state->gl_primitive_type, count, idx_type,
162 (const char *)idx_data + (idx_size * start_idx));
163 checkGLcall("glDrawElements");
168 static unsigned int get_stride_idx(const void *idx_data, unsigned int idx_size,
169 unsigned int base_vertex_idx, unsigned int start_idx, unsigned int vertex_idx)
171 if (!idx_data)
172 return start_idx + vertex_idx;
173 if (idx_size == 2)
174 return ((const WORD *)idx_data)[start_idx + vertex_idx] + base_vertex_idx;
175 return ((const DWORD *)idx_data)[start_idx + vertex_idx] + base_vertex_idx;
178 /* Context activation is done by the caller. */
179 static void draw_primitive_immediate_mode(struct wined3d_context *context, const struct wined3d_state *state,
180 const struct wined3d_stream_info *si, const void *idx_data, unsigned int idx_size,
181 int base_vertex_idx, unsigned int start_idx, unsigned int vertex_count, unsigned int instance_count)
183 const BYTE *position = NULL, *normal = NULL, *diffuse = NULL, *specular = NULL;
184 const struct wined3d_d3d_info *d3d_info = context->d3d_info;
185 unsigned int coord_idx, stride_idx, texture_idx, vertex_idx;
186 const struct wined3d_gl_info *gl_info = context->gl_info;
187 const struct wined3d_stream_info_element *element;
188 const BYTE *tex_coords[WINED3DDP_MAXTEXCOORD];
189 unsigned int texture_unit, texture_stages;
190 const struct wined3d_ffp_attrib_ops *ops;
191 unsigned int untracked_material_count;
192 unsigned int tex_mask = 0;
193 BOOL specular_fog = FALSE;
194 BOOL ps = use_ps(state);
195 const void *ptr;
197 static unsigned int once;
199 if (!once++)
200 FIXME_(d3d_perf)("Drawing using immediate mode.\n");
201 else
202 WARN_(d3d_perf)("Drawing using immediate mode.\n");
204 if (!idx_size && idx_data)
205 ERR("Non-NULL idx_data with 0 idx_size, this should never happen.\n");
207 if (instance_count)
208 FIXME("Instancing not implemented.\n");
210 /* Immediate mode drawing can't make use of indices in a VBO - get the
211 * data from the index buffer. */
212 if (idx_size)
213 idx_data = wined3d_buffer_load_sysmem(state->index_buffer, context) + state->index_offset;
215 ops = &d3d_info->ffp_attrib_ops;
217 gl_info->gl_ops.gl.p_glBegin(state->gl_primitive_type);
219 if (use_vs(state) || d3d_info->ffp_generic_attributes)
221 for (vertex_idx = 0; vertex_idx < vertex_count; ++vertex_idx)
223 unsigned int use_map = si->use_map;
224 unsigned int element_idx;
226 stride_idx = get_stride_idx(idx_data, idx_size, base_vertex_idx, start_idx, vertex_idx);
227 for (element_idx = MAX_ATTRIBS - 1; use_map; use_map &= ~(1u << element_idx), --element_idx)
229 if (!(use_map & 1u << element_idx))
230 continue;
232 ptr = si->elements[element_idx].data.addr + si->elements[element_idx].stride * stride_idx;
233 ops->generic[si->elements[element_idx].format->emit_idx](element_idx, ptr);
237 gl_info->gl_ops.gl.p_glEnd();
238 return;
241 if (si->use_map & (1u << WINED3D_FFP_POSITION))
242 position = si->elements[WINED3D_FFP_POSITION].data.addr;
244 if (si->use_map & (1u << WINED3D_FFP_NORMAL))
245 normal = si->elements[WINED3D_FFP_NORMAL].data.addr;
246 else
247 gl_info->gl_ops.gl.p_glNormal3f(0.0f, 0.0f, 0.0f);
249 untracked_material_count = context->num_untracked_materials;
250 if (si->use_map & (1u << WINED3D_FFP_DIFFUSE))
252 element = &si->elements[WINED3D_FFP_DIFFUSE];
253 diffuse = element->data.addr;
255 if (untracked_material_count && element->format->id != WINED3DFMT_B8G8R8A8_UNORM)
256 FIXME("Implement diffuse color tracking from %s.\n", debug_d3dformat(element->format->id));
258 else
260 gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
263 if (si->use_map & (1u << WINED3D_FFP_SPECULAR))
265 element = &si->elements[WINED3D_FFP_SPECULAR];
266 specular = element->data.addr;
268 /* Special case where the fog density is stored in the specular alpha channel. */
269 if (state->render_states[WINED3D_RS_FOGENABLE]
270 && (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE
271 || si->elements[WINED3D_FFP_POSITION].format->id == WINED3DFMT_R32G32B32A32_FLOAT)
272 && state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
274 if (gl_info->supported[EXT_FOG_COORD])
276 if (element->format->id == WINED3DFMT_B8G8R8A8_UNORM)
277 specular_fog = TRUE;
278 else
279 FIXME("Implement fog coordinates from %s.\n", debug_d3dformat(element->format->id));
281 else
283 static unsigned int once;
285 if (!once++)
286 FIXME("Implement fog for transformed vertices in software.\n");
290 else if (gl_info->supported[EXT_SECONDARY_COLOR])
292 GL_EXTCALL(glSecondaryColor3fEXT)(0.0f, 0.0f, 0.0f);
295 texture_stages = d3d_info->limits.ffp_blend_stages;
296 for (texture_idx = 0; texture_idx < texture_stages; ++texture_idx)
298 if (!gl_info->supported[ARB_MULTITEXTURE] && texture_idx > 0)
300 FIXME("Program using multiple concurrent textures which this OpenGL implementation doesn't support.\n");
301 continue;
304 if (!ps && !state->textures[texture_idx])
305 continue;
307 texture_unit = context->tex_unit_map[texture_idx];
308 if (texture_unit == WINED3D_UNMAPPED_STAGE)
309 continue;
311 coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX];
312 if (coord_idx > 7)
314 TRACE("Skipping generated coordinates (%#x) for texture %u.\n", coord_idx, texture_idx);
315 continue;
318 if (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))
320 tex_coords[coord_idx] = si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].data.addr;
321 tex_mask |= (1u << texture_idx);
323 else
325 TRACE("Setting default coordinates for texture %u.\n", texture_idx);
326 if (gl_info->supported[ARB_MULTITEXTURE])
327 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_unit, 0.0f, 0.0f, 0.0f, 1.0f));
328 else
329 gl_info->gl_ops.gl.p_glTexCoord4f(0.0f, 0.0f, 0.0f, 1.0f);
333 /* Blending data and point sizes are not supported by this function. They
334 * are not supported by the fixed function pipeline at all. A FIXME for
335 * them is printed after decoding the vertex declaration. */
336 for (vertex_idx = 0; vertex_idx < vertex_count; ++vertex_idx)
338 unsigned int tmp_tex_mask;
340 stride_idx = get_stride_idx(idx_data, idx_size, base_vertex_idx, start_idx, vertex_idx);
342 if (normal)
344 ptr = normal + stride_idx * si->elements[WINED3D_FFP_NORMAL].stride;
345 ops->normal[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptr);
348 if (diffuse)
350 ptr = diffuse + stride_idx * si->elements[WINED3D_FFP_DIFFUSE].stride;
351 ops->diffuse[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptr);
353 if (untracked_material_count)
355 struct wined3d_color color;
356 unsigned int i;
358 wined3d_color_from_d3dcolor(&color, *(const DWORD *)ptr);
359 for (i = 0; i < untracked_material_count; ++i)
361 gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], &color.r);
366 if (specular)
368 ptr = specular + stride_idx * si->elements[WINED3D_FFP_SPECULAR].stride;
369 ops->specular[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptr);
371 if (specular_fog)
372 GL_EXTCALL(glFogCoordfEXT((float)(*(const DWORD *)ptr >> 24)));
375 tmp_tex_mask = tex_mask;
376 for (texture_idx = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture_idx)
378 if (!(tmp_tex_mask & 1))
379 continue;
381 coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX];
382 ptr = tex_coords[coord_idx] + (stride_idx * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride);
383 ops->texcoord[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
384 GL_TEXTURE0_ARB + context->tex_unit_map[texture_idx], ptr);
387 if (position)
389 ptr = position + stride_idx * si->elements[WINED3D_FFP_POSITION].stride;
390 ops->position[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptr);
394 gl_info->gl_ops.gl.p_glEnd();
395 checkGLcall("glEnd and previous calls");
398 static void draw_indirect(struct wined3d_context *context, const struct wined3d_state *state,
399 const struct wined3d_indirect_draw_parameters *parameters, unsigned int idx_size)
401 const struct wined3d_gl_info *gl_info = context->gl_info;
402 struct wined3d_buffer *buffer = parameters->buffer;
404 if (!gl_info->supported[ARB_DRAW_INDIRECT])
406 FIXME("OpenGL implementation does not support indirect draws.\n");
407 return;
410 wined3d_buffer_load(buffer, context, state);
411 GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->buffer_object));
413 if (idx_size)
415 GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
416 if (state->index_offset)
417 FIXME("Ignoring index offset %u.\n", state->index_offset);
418 GL_EXTCALL(glDrawElementsIndirect(state->gl_primitive_type, idx_type,
419 (void *)(GLintptr)parameters->offset));
421 else
423 GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type,
424 (void *)(GLintptr)parameters->offset));
427 GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0));
429 checkGLcall("draw indirect");
432 static void remove_vbos(struct wined3d_context *context,
433 const struct wined3d_state *state, struct wined3d_stream_info *s)
435 unsigned int i;
437 for (i = 0; i < ARRAY_SIZE(s->elements); ++i)
439 struct wined3d_stream_info_element *e;
441 if (!(s->use_map & (1u << i)))
442 continue;
444 e = &s->elements[i];
445 if (e->data.buffer_object)
447 struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
448 e->data.buffer_object = 0;
449 e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(vb, context);
454 static BOOL use_transform_feedback(const struct wined3d_state *state)
456 const struct wined3d_shader *shader;
457 if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]))
458 return FALSE;
459 return shader->u.gs.so_desc.element_count;
462 static void context_pause_transform_feedback(struct wined3d_context *context, BOOL force)
464 const struct wined3d_gl_info *gl_info = context->gl_info;
466 if (!context->transform_feedback_active || context->transform_feedback_paused)
467 return;
469 if (gl_info->supported[ARB_TRANSFORM_FEEDBACK2])
471 GL_EXTCALL(glPauseTransformFeedback());
472 checkGLcall("glPauseTransformFeedback");
473 context->transform_feedback_paused = 1;
474 return;
477 WARN("Cannot pause transform feedback operations.\n");
479 if (force)
480 context_end_transform_feedback(context);
483 static GLenum gl_tfb_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
485 GLenum gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
486 switch (gl_primitive_type)
488 case GL_POINTS:
489 return GL_POINTS;
491 case GL_LINE_STRIP:
492 case GL_LINE_STRIP_ADJACENCY:
493 case GL_LINES_ADJACENCY:
494 case GL_LINES:
495 return GL_LINES;
497 case GL_TRIANGLE_FAN:
498 case GL_TRIANGLE_STRIP:
499 case GL_TRIANGLE_STRIP_ADJACENCY:
500 case GL_TRIANGLES_ADJACENCY:
501 case GL_TRIANGLES:
502 return GL_TRIANGLES;
504 default:
505 return gl_primitive_type;
509 /* Routine common to the draw primitive and draw indexed primitive routines */
510 void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state,
511 const struct wined3d_draw_parameters *parameters)
513 BOOL emulation = FALSE, rasterizer_discard = FALSE;
514 const struct wined3d_fb_state *fb = state->fb;
515 const struct wined3d_stream_info *stream_info;
516 struct wined3d_rendertarget_view *dsv, *rtv;
517 struct wined3d_stream_info si_emulated;
518 struct wined3d_fence *ib_fence = NULL;
519 const struct wined3d_gl_info *gl_info;
520 struct wined3d_context *context;
521 unsigned int i, idx_size = 0;
522 const void *idx_data = NULL;
524 if (!parameters->indirect && !parameters->u.direct.index_count)
525 return;
527 if (!(rtv = fb->render_targets[0]))
528 rtv = fb->depth_stencil;
529 if (rtv)
530 context = context_acquire(device, wined3d_texture_from_resource(rtv->resource), rtv->sub_resource_idx);
531 else
532 context = context_acquire(device, NULL, 0);
533 if (!context->valid)
535 context_release(context);
536 WARN("Invalid context, skipping draw.\n");
537 return;
539 gl_info = context->gl_info;
541 if (!use_transform_feedback(state))
542 context_pause_transform_feedback(context, TRUE);
544 for (i = 0; i < gl_info->limits.buffers; ++i)
546 if (!(rtv = fb->render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
547 continue;
549 if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
551 wined3d_rendertarget_view_load_location(rtv, context, rtv->resource->draw_binding);
552 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
554 else
556 wined3d_rendertarget_view_prepare_location(rtv, context, rtv->resource->draw_binding);
560 if ((dsv = fb->depth_stencil))
562 /* Note that this depends on the context_acquire() call above to set
563 * context->render_offscreen properly. We don't currently take the
564 * Z-compare function into account, but we could skip loading the
565 * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note
566 * that we never copy the stencil data.*/
567 DWORD location = context->render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
569 if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE])
570 wined3d_rendertarget_view_load_location(dsv, context, location);
571 else
572 wined3d_rendertarget_view_prepare_location(dsv, context, location);
575 if (!context_apply_draw_state(context, device, state))
577 context_release(context);
578 WARN("Unable to apply draw state, skipping draw.\n");
579 return;
582 if (dsv && state->render_states[WINED3D_RS_ZWRITEENABLE])
584 DWORD location = context->render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
586 wined3d_rendertarget_view_validate_location(dsv, location);
587 wined3d_rendertarget_view_invalidate_location(dsv, ~location);
590 stream_info = &context->stream_info;
592 if (parameters->indexed)
594 struct wined3d_buffer *index_buffer = state->index_buffer;
595 if (!index_buffer->buffer_object || !stream_info->all_vbo)
597 idx_data = index_buffer->resource.heap_memory;
599 else
601 ib_fence = index_buffer->fence;
602 idx_data = NULL;
604 idx_data = (const BYTE *)idx_data + state->index_offset;
606 if (state->index_format == WINED3DFMT_R16_UINT)
607 idx_size = 2;
608 else
609 idx_size = 4;
612 if (!use_vs(state))
614 if (!stream_info->position_transformed && context->num_untracked_materials
615 && state->render_states[WINED3D_RS_LIGHTING])
617 static BOOL warned;
619 if (!warned++)
620 FIXME("Using software emulation because not all material properties could be tracked.\n");
621 else
622 WARN_(d3d_perf)("Using software emulation because not all material properties could be tracked.\n");
623 emulation = TRUE;
625 else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE])
627 static BOOL warned;
629 /* Either write a pipeline replacement shader or convert the
630 * specular alpha from unsigned byte to a float in the vertex
631 * buffer. */
632 if (!warned++)
633 FIXME("Using software emulation because manual fog coordinates are provided.\n");
634 else
635 WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n");
636 emulation = TRUE;
639 if (emulation)
641 si_emulated = context->stream_info;
642 remove_vbos(context, state, &si_emulated);
643 stream_info = &si_emulated;
647 if (use_transform_feedback(state))
649 const struct wined3d_shader *shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
651 if (is_rasterization_disabled(shader))
653 glEnable(GL_RASTERIZER_DISCARD);
654 checkGLcall("enable rasterizer discard");
655 rasterizer_discard = TRUE;
658 if (context->transform_feedback_paused)
660 GL_EXTCALL(glResumeTransformFeedback());
661 checkGLcall("glResumeTransformFeedback");
662 context->transform_feedback_paused = 0;
664 else if (!context->transform_feedback_active)
666 GLenum mode = gl_tfb_primitive_type_from_d3d(shader->u.gs.output_type);
667 GL_EXTCALL(glBeginTransformFeedback(mode));
668 checkGLcall("glBeginTransformFeedback");
669 context->transform_feedback_active = 1;
673 if (state->gl_primitive_type == GL_PATCHES)
675 GL_EXTCALL(glPatchParameteri(GL_PATCH_VERTICES, state->gl_patch_vertices));
676 checkGLcall("glPatchParameteri");
679 if (parameters->indirect)
681 if (!context->use_immediate_mode_draw && !emulation)
682 draw_indirect(context, state, &parameters->u.indirect, idx_size);
683 else
684 FIXME("Indirect draws with immediate mode/emulation are not supported.\n");
686 else
688 unsigned int instance_count = parameters->u.direct.instance_count;
689 if (context->instance_count)
690 instance_count = context->instance_count;
692 if (context->use_immediate_mode_draw || emulation)
693 draw_primitive_immediate_mode(context, state, stream_info, idx_data,
694 idx_size, parameters->u.direct.base_vertex_idx,
695 parameters->u.direct.start_idx, parameters->u.direct.index_count, instance_count);
696 else
697 draw_primitive_arrays(context, state, idx_data, idx_size, parameters->u.direct.base_vertex_idx,
698 parameters->u.direct.start_idx, parameters->u.direct.index_count,
699 parameters->u.direct.start_instance, instance_count);
702 if (context->uses_uavs)
704 GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS));
705 checkGLcall("glMemoryBarrier");
708 context_pause_transform_feedback(context, FALSE);
710 if (rasterizer_discard)
712 glDisable(GL_RASTERIZER_DISCARD);
713 checkGLcall("disable rasterizer discard");
716 if (ib_fence)
717 wined3d_fence_issue(ib_fence, device);
718 for (i = 0; i < context->buffer_fence_count; ++i)
719 wined3d_fence_issue(context->buffer_fences[i], device);
721 if (wined3d_settings.strict_draw_ordering)
722 gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
724 context_release(context);
726 TRACE("Done all gl drawing.\n");
729 void dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state,
730 const struct wined3d_dispatch_parameters *parameters)
732 const struct wined3d_gl_info *gl_info;
733 struct wined3d_context *context;
735 context = context_acquire(device, NULL, 0);
736 if (!context->valid)
738 context_release(context);
739 WARN("Invalid context, skipping dispatch.\n");
740 return;
742 gl_info = context->gl_info;
744 if (!gl_info->supported[ARB_COMPUTE_SHADER])
746 context_release(context);
747 FIXME("OpenGL implementation does not support compute shaders.\n");
748 return;
751 context_apply_compute_state(context, device, state);
753 if (!state->shader[WINED3D_SHADER_TYPE_COMPUTE])
755 context_release(context);
756 WARN("No compute shader bound, skipping dispatch.\n");
757 return;
760 if (parameters->indirect)
762 const struct wined3d_indirect_dispatch_parameters *indirect = &parameters->u.indirect;
763 struct wined3d_buffer *buffer = indirect->buffer;
765 wined3d_buffer_load(buffer, context, state);
766 GL_EXTCALL(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->buffer_object));
767 GL_EXTCALL(glDispatchComputeIndirect((GLintptr)indirect->offset));
768 GL_EXTCALL(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0));
770 else
772 const struct wined3d_direct_dispatch_parameters *direct = &parameters->u.direct;
773 GL_EXTCALL(glDispatchCompute(direct->group_count_x, direct->group_count_y, direct->group_count_z));
775 checkGLcall("dispatch compute");
777 GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS));
778 checkGLcall("glMemoryBarrier");
780 if (wined3d_settings.strict_draw_ordering)
781 gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
783 context_release(context);