From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/Makefile.in | 1 - dlls/wined3d/context.c | 699 ++++++++++++++++++++++++++++++++++++++- dlls/wined3d/drawprim.c | 725 ----------------------------------------- dlls/wined3d/wined3d_private.h | 2 - 4 files changed, 698 insertions(+), 729 deletions(-) delete mode 100644 dlls/wined3d/drawprim.c
diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in index edee58845aa6..58fc2d5f42d0 100644 --- a/dlls/wined3d/Makefile.in +++ b/dlls/wined3d/Makefile.in @@ -10,7 +10,6 @@ C_SRCS = \ cs.c \ device.c \ directx.c \ - drawprim.c \ gl_compat.c \ glsl_shader.c \ nvidia_texture_shader.c \ diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index e36898f84fd9..235b75b9a86b 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -1,6 +1,11 @@ /* * Context and render target management in wined3d * + * Copyright 2002-2004 Jason Edmeades + * Copyright 2002-2004 Raphael Junqueira + * Copyright 2004 Christian Costa + * Copyright 2005 Oliver Stieber + * Copyright 2006, 2008 Henri Verbeet * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers * Copyright 2009-2011 Henri Verbeet for CodeWeavers * @@ -3898,7 +3903,7 @@ static void context_load_stream_output_buffers(struct wined3d_context *context, }
/* Context activation is done by the caller. */ -BOOL context_apply_draw_state(struct wined3d_context *context, +static BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, const struct wined3d_state *state) { const struct StateEntry *state_table = context->state_table; @@ -4062,6 +4067,14 @@ static void context_apply_compute_state(struct wined3d_context *context, context->last_was_blit = FALSE; }
+static BOOL use_transform_feedback(const struct wined3d_state *state) +{ + const struct wined3d_shader *shader; + if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY])) + return FALSE; + return shader->u.gs.so_desc.element_count; +} + void context_end_transform_feedback(struct wined3d_context *context) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -4074,6 +4087,27 @@ void context_end_transform_feedback(struct wined3d_context *context) } }
+static void context_pause_transform_feedback(struct wined3d_context *context, BOOL force) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (!context->transform_feedback_active || context->transform_feedback_paused) + return; + + if (gl_info->supported[ARB_TRANSFORM_FEEDBACK2]) + { + GL_EXTCALL(glPauseTransformFeedback()); + checkGLcall("glPauseTransformFeedback"); + context->transform_feedback_paused = 1; + return; + } + + WARN("Cannot pause transform feedback operations.\n"); + + if (force) + context_end_transform_feedback(context); +} + static void context_setup_target(struct wined3d_context *context, struct wined3d_texture *texture, unsigned int sub_resource_idx) { @@ -4286,3 +4320,666 @@ void dispatch_compute(struct wined3d_device *device, const struct wined3d_state
context_release(context); } + +/* Context activation is done by the caller. */ +static void draw_primitive_arrays(struct wined3d_context *context, const struct wined3d_state *state, + const void *idx_data, unsigned int idx_size, int base_vertex_idx, unsigned int start_idx, + unsigned int count, unsigned int start_instance, unsigned int instance_count) +{ + const struct wined3d_ffp_attrib_ops *ops = &context->d3d_info->ffp_attrib_ops; + GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; + const struct wined3d_stream_info *si = &context->stream_info; + unsigned int instanced_elements[ARRAY_SIZE(si->elements)]; + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int instanced_element_count = 0; + GLenum mode = state->gl_primitive_type; + const void *indices; + unsigned int i, j; + + indices = (const char *)idx_data + idx_size * start_idx; + + if (!instance_count) + { + if (!idx_size) + { + gl_info->gl_ops.gl.p_glDrawArrays(mode, start_idx, count); + checkGLcall("glDrawArrays"); + return; + } + + if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) + { + GL_EXTCALL(glDrawElementsBaseVertex(mode, count, idx_type, indices, base_vertex_idx)); + checkGLcall("glDrawElementsBaseVertex"); + return; + } + + gl_info->gl_ops.gl.p_glDrawElements(mode, count, idx_type, indices); + checkGLcall("glDrawElements"); + return; + } + + if (start_instance && !(gl_info->supported[ARB_BASE_INSTANCE] && gl_info->supported[ARB_INSTANCED_ARRAYS])) + FIXME("Start instance (%u) not supported.\n", start_instance); + + if (gl_info->supported[ARB_INSTANCED_ARRAYS]) + { + if (!idx_size) + { + if (gl_info->supported[ARB_BASE_INSTANCE]) + { + GL_EXTCALL(glDrawArraysInstancedBaseInstance(mode, start_idx, count, instance_count, start_instance)); + checkGLcall("glDrawArraysInstancedBaseInstance"); + return; + } + + GL_EXTCALL(glDrawArraysInstanced(mode, start_idx, count, instance_count)); + checkGLcall("glDrawArraysInstanced"); + return; + } + + if (gl_info->supported[ARB_BASE_INSTANCE]) + { + GL_EXTCALL(glDrawElementsInstancedBaseVertexBaseInstance(mode, count, idx_type, + indices, instance_count, base_vertex_idx, start_instance)); + checkGLcall("glDrawElementsInstancedBaseVertexBaseInstance"); + return; + } + if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) + { + GL_EXTCALL(glDrawElementsInstancedBaseVertex(mode, count, idx_type, + indices, instance_count, base_vertex_idx)); + checkGLcall("glDrawElementsInstancedBaseVertex"); + return; + } + + GL_EXTCALL(glDrawElementsInstanced(mode, count, idx_type, indices, instance_count)); + checkGLcall("glDrawElementsInstanced"); + return; + } + + /* Instancing emulation by mixing immediate mode and arrays. */ + + /* This is a nasty thing. MSDN says no hardware supports this and + * applications have to use software vertex processing. We don't support + * this for now. + * + * Shouldn't be too hard to support with OpenGL, in theory just call + * glDrawArrays() instead of drawElements(). But the stream fequency value + * has a different meaning in that situation. */ + if (!idx_size) + { + FIXME("Non-indexed instanced drawing is not supported.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(si->elements); ++i) + { + if (!(si->use_map & (1u << i))) + continue; + + if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA) + instanced_elements[instanced_element_count++] = i; + } + + for (i = 0; i < instance_count; ++i) + { + /* Specify the instanced attributes using immediate mode calls. */ + for (j = 0; j < instanced_element_count; ++j) + { + const struct wined3d_stream_info_element *element; + unsigned int element_idx; + const BYTE *ptr; + + element_idx = instanced_elements[j]; + element = &si->elements[element_idx]; + ptr = element->data.addr + element->stride * i; + if (element->data.buffer_object) + ptr += (ULONG_PTR)wined3d_buffer_load_sysmem(state->streams[element->stream_idx].buffer, context); + ops->generic[element->format->emit_idx](element_idx, ptr); + } + + if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) + { + GL_EXTCALL(glDrawElementsBaseVertex(mode, count, idx_type, indices, base_vertex_idx)); + checkGLcall("glDrawElementsBaseVertex"); + } + else + { + gl_info->gl_ops.gl.p_glDrawElements(mode, count, idx_type, indices); + checkGLcall("glDrawElements"); + } + } +} + +static unsigned int get_stride_idx(const void *idx_data, unsigned int idx_size, + unsigned int base_vertex_idx, unsigned int start_idx, unsigned int vertex_idx) +{ + if (!idx_data) + return start_idx + vertex_idx; + if (idx_size == 2) + return ((const WORD *)idx_data)[start_idx + vertex_idx] + base_vertex_idx; + return ((const DWORD *)idx_data)[start_idx + vertex_idx] + base_vertex_idx; +} + +/* Context activation is done by the caller. */ +static void draw_primitive_immediate_mode(struct wined3d_context *context, const struct wined3d_state *state, + const struct wined3d_stream_info *si, const void *idx_data, unsigned int idx_size, + int base_vertex_idx, unsigned int start_idx, unsigned int vertex_count, unsigned int instance_count) +{ + const BYTE *position = NULL, *normal = NULL, *diffuse = NULL, *specular = NULL; + const struct wined3d_d3d_info *d3d_info = context->d3d_info; + unsigned int coord_idx, stride_idx, texture_idx, vertex_idx; + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_stream_info_element *element; + const BYTE *tex_coords[WINED3DDP_MAXTEXCOORD]; + unsigned int texture_unit, texture_stages; + const struct wined3d_ffp_attrib_ops *ops; + unsigned int untracked_material_count; + unsigned int tex_mask = 0; + BOOL specular_fog = FALSE; + BOOL ps = use_ps(state); + const void *ptr; + + static unsigned int once; + + if (!once++) + FIXME_(d3d_perf)("Drawing using immediate mode.\n"); + else + WARN_(d3d_perf)("Drawing using immediate mode.\n"); + + if (!idx_size && idx_data) + ERR("Non-NULL idx_data with 0 idx_size, this should never happen.\n"); + + if (instance_count) + FIXME("Instancing not implemented.\n"); + + /* Immediate mode drawing can't make use of indices in a VBO - get the + * data from the index buffer. */ + if (idx_size) + idx_data = wined3d_buffer_load_sysmem(state->index_buffer, context) + state->index_offset; + + ops = &d3d_info->ffp_attrib_ops; + + gl_info->gl_ops.gl.p_glBegin(state->gl_primitive_type); + + if (use_vs(state) || d3d_info->ffp_generic_attributes) + { + for (vertex_idx = 0; vertex_idx < vertex_count; ++vertex_idx) + { + unsigned int use_map = si->use_map; + unsigned int element_idx; + + stride_idx = get_stride_idx(idx_data, idx_size, base_vertex_idx, start_idx, vertex_idx); + for (element_idx = MAX_ATTRIBS - 1; use_map; use_map &= ~(1u << element_idx), --element_idx) + { + if (!(use_map & 1u << element_idx)) + continue; + + ptr = si->elements[element_idx].data.addr + si->elements[element_idx].stride * stride_idx; + ops->generic[si->elements[element_idx].format->emit_idx](element_idx, ptr); + } + } + + gl_info->gl_ops.gl.p_glEnd(); + return; + } + + if (si->use_map & (1u << WINED3D_FFP_POSITION)) + position = si->elements[WINED3D_FFP_POSITION].data.addr; + + if (si->use_map & (1u << WINED3D_FFP_NORMAL)) + normal = si->elements[WINED3D_FFP_NORMAL].data.addr; + else + gl_info->gl_ops.gl.p_glNormal3f(0.0f, 0.0f, 0.0f); + + untracked_material_count = context->num_untracked_materials; + if (si->use_map & (1u << WINED3D_FFP_DIFFUSE)) + { + element = &si->elements[WINED3D_FFP_DIFFUSE]; + diffuse = element->data.addr; + + if (untracked_material_count && element->format->id != WINED3DFMT_B8G8R8A8_UNORM) + FIXME("Implement diffuse color tracking from %s.\n", debug_d3dformat(element->format->id)); + } + else + { + gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } + + if (si->use_map & (1u << WINED3D_FFP_SPECULAR)) + { + element = &si->elements[WINED3D_FFP_SPECULAR]; + specular = element->data.addr; + + /* Special case where the fog density is stored in the specular alpha channel. */ + if (state->render_states[WINED3D_RS_FOGENABLE] + && (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE + || si->elements[WINED3D_FFP_POSITION].format->id == WINED3DFMT_R32G32B32A32_FLOAT) + && state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE) + { + if (gl_info->supported[EXT_FOG_COORD]) + { + if (element->format->id == WINED3DFMT_B8G8R8A8_UNORM) + specular_fog = TRUE; + else + FIXME("Implement fog coordinates from %s.\n", debug_d3dformat(element->format->id)); + } + else + { + static unsigned int once; + + if (!once++) + FIXME("Implement fog for transformed vertices in software.\n"); + } + } + } + else if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GL_EXTCALL(glSecondaryColor3fEXT)(0.0f, 0.0f, 0.0f); + } + + texture_stages = d3d_info->limits.ffp_blend_stages; + for (texture_idx = 0; texture_idx < texture_stages; ++texture_idx) + { + if (!gl_info->supported[ARB_MULTITEXTURE] && texture_idx > 0) + { + FIXME("Program using multiple concurrent textures which this OpenGL implementation doesn't support.\n"); + continue; + } + + if (!ps && !state->textures[texture_idx]) + continue; + + texture_unit = context->tex_unit_map[texture_idx]; + if (texture_unit == WINED3D_UNMAPPED_STAGE) + continue; + + coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX]; + if (coord_idx > 7) + { + TRACE("Skipping generated coordinates (%#x) for texture %u.\n", coord_idx, texture_idx); + continue; + } + + if (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))) + { + tex_coords[coord_idx] = si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].data.addr; + tex_mask |= (1u << texture_idx); + } + else + { + TRACE("Setting default coordinates for texture %u.\n", texture_idx); + if (gl_info->supported[ARB_MULTITEXTURE]) + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_unit, 0.0f, 0.0f, 0.0f, 1.0f)); + else + gl_info->gl_ops.gl.p_glTexCoord4f(0.0f, 0.0f, 0.0f, 1.0f); + } + } + + /* Blending data and point sizes are not supported by this function. They + * are not supported by the fixed function pipeline at all. A FIXME for + * them is printed after decoding the vertex declaration. */ + for (vertex_idx = 0; vertex_idx < vertex_count; ++vertex_idx) + { + unsigned int tmp_tex_mask; + + stride_idx = get_stride_idx(idx_data, idx_size, base_vertex_idx, start_idx, vertex_idx); + + if (normal) + { + ptr = normal + stride_idx * si->elements[WINED3D_FFP_NORMAL].stride; + ops->normal[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptr); + } + + if (diffuse) + { + ptr = diffuse + stride_idx * si->elements[WINED3D_FFP_DIFFUSE].stride; + ops->diffuse[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptr); + + if (untracked_material_count) + { + struct wined3d_color color; + unsigned int i; + + wined3d_color_from_d3dcolor(&color, *(const DWORD *)ptr); + for (i = 0; i < untracked_material_count; ++i) + { + gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], &color.r); + } + } + } + + if (specular) + { + ptr = specular + stride_idx * si->elements[WINED3D_FFP_SPECULAR].stride; + ops->specular[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptr); + + if (specular_fog) + GL_EXTCALL(glFogCoordfEXT((float)(*(const DWORD *)ptr >> 24))); + } + + tmp_tex_mask = tex_mask; + for (texture_idx = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture_idx) + { + if (!(tmp_tex_mask & 1)) + continue; + + coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX]; + ptr = tex_coords[coord_idx] + (stride_idx * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride); + ops->texcoord[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx]( + GL_TEXTURE0_ARB + context->tex_unit_map[texture_idx], ptr); + } + + if (position) + { + ptr = position + stride_idx * si->elements[WINED3D_FFP_POSITION].stride; + ops->position[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptr); + } + } + + gl_info->gl_ops.gl.p_glEnd(); + checkGLcall("draw immediate mode"); +} + +static void draw_indirect(struct wined3d_context *context, const struct wined3d_state *state, + const struct wined3d_indirect_draw_parameters *parameters, unsigned int idx_size) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_buffer *buffer = parameters->buffer; + const void *offset; + + if (!gl_info->supported[ARB_DRAW_INDIRECT]) + { + FIXME("OpenGL implementation does not support indirect draws.\n"); + return; + } + + GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->buffer_object)); + + offset = (void *)(GLintptr)parameters->offset; + if (idx_size) + { + GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; + if (state->index_offset) + FIXME("Ignoring index offset %u.\n", state->index_offset); + GL_EXTCALL(glDrawElementsIndirect(state->gl_primitive_type, idx_type, offset)); + } + else + { + GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type, offset)); + } + + GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0)); + + checkGLcall("draw indirect"); +} + +static void remove_vbos(struct wined3d_context *context, + const struct wined3d_state *state, struct wined3d_stream_info *s) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(s->elements); ++i) + { + struct wined3d_stream_info_element *e; + + if (!(s->use_map & (1u << i))) + continue; + + e = &s->elements[i]; + if (e->data.buffer_object) + { + struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer; + e->data.buffer_object = 0; + e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(vb, context); + } + } +} + +static GLenum gl_tfb_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) +{ + GLenum gl_primitive_type = gl_primitive_type_from_d3d(primitive_type); + switch (gl_primitive_type) + { + case GL_POINTS: + return GL_POINTS; + + case GL_LINE_STRIP: + case GL_LINE_STRIP_ADJACENCY: + case GL_LINES_ADJACENCY: + case GL_LINES: + return GL_LINES; + + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_STRIP_ADJACENCY: + case GL_TRIANGLES_ADJACENCY: + case GL_TRIANGLES: + return GL_TRIANGLES; + + default: + return gl_primitive_type; + } +} + +/* Routine common to the draw primitive and draw indexed primitive routines */ +void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, + const struct wined3d_draw_parameters *parameters) +{ + BOOL emulation = FALSE, rasterizer_discard = FALSE; + const struct wined3d_fb_state *fb = state->fb; + const struct wined3d_stream_info *stream_info; + struct wined3d_rendertarget_view *dsv, *rtv; + struct wined3d_stream_info si_emulated; + struct wined3d_fence *ib_fence = NULL; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + unsigned int i, idx_size = 0; + const void *idx_data = NULL; + + if (!parameters->indirect && !parameters->u.direct.index_count) + return; + + if (!(rtv = fb->render_targets[0])) + rtv = fb->depth_stencil; + if (rtv) + context = context_acquire(device, wined3d_texture_from_resource(rtv->resource), rtv->sub_resource_idx); + else + context = context_acquire(device, NULL, 0); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping draw.\n"); + return; + } + gl_info = context->gl_info; + + if (!use_transform_feedback(state)) + context_pause_transform_feedback(context, TRUE); + + for (i = 0; i < gl_info->limits.buffers; ++i) + { + if (!(rtv = fb->render_targets[i]) || rtv->format->id == WINED3DFMT_NULL) + continue; + + if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) + { + wined3d_rendertarget_view_load_location(rtv, context, rtv->resource->draw_binding); + wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); + } + else + { + wined3d_rendertarget_view_prepare_location(rtv, context, rtv->resource->draw_binding); + } + } + + if ((dsv = fb->depth_stencil)) + { + /* Note that this depends on the context_acquire() call above to set + * context->render_offscreen properly. We don't currently take the + * Z-compare function into account, but we could skip loading the + * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note + * that we never copy the stencil data.*/ + DWORD location = context->render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; + + if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) + wined3d_rendertarget_view_load_location(dsv, context, location); + else + wined3d_rendertarget_view_prepare_location(dsv, context, location); + } + + if (parameters->indirect) + wined3d_buffer_load(parameters->u.indirect.buffer, context, state); + + if (!context_apply_draw_state(context, device, state)) + { + context_release(context); + WARN("Unable to apply draw state, skipping draw.\n"); + return; + } + + if (dsv && state->render_states[WINED3D_RS_ZWRITEENABLE]) + { + DWORD location = context->render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; + + wined3d_rendertarget_view_validate_location(dsv, location); + wined3d_rendertarget_view_invalidate_location(dsv, ~location); + } + + stream_info = &context->stream_info; + + if (parameters->indexed) + { + struct wined3d_buffer *index_buffer = state->index_buffer; + if (!index_buffer->buffer_object || !stream_info->all_vbo) + { + idx_data = index_buffer->resource.heap_memory; + } + else + { + ib_fence = index_buffer->fence; + idx_data = NULL; + } + idx_data = (const BYTE *)idx_data + state->index_offset; + + if (state->index_format == WINED3DFMT_R16_UINT) + idx_size = 2; + else + idx_size = 4; + } + + if (!use_vs(state)) + { + if (!stream_info->position_transformed && context->num_untracked_materials + && state->render_states[WINED3D_RS_LIGHTING]) + { + static BOOL warned; + + if (!warned++) + FIXME("Using software emulation because not all material properties could be tracked.\n"); + else + WARN_(d3d_perf)("Using software emulation because not all material properties could be tracked.\n"); + emulation = TRUE; + } + else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE]) + { + static BOOL warned; + + /* Either write a pipeline replacement shader or convert the + * specular alpha from unsigned byte to a float in the vertex + * buffer. */ + if (!warned++) + FIXME("Using software emulation because manual fog coordinates are provided.\n"); + else + WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n"); + emulation = TRUE; + } + + if (emulation) + { + si_emulated = context->stream_info; + remove_vbos(context, state, &si_emulated); + stream_info = &si_emulated; + } + } + + if (use_transform_feedback(state)) + { + const struct wined3d_shader *shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]; + + if (is_rasterization_disabled(shader)) + { + glEnable(GL_RASTERIZER_DISCARD); + checkGLcall("enable rasterizer discard"); + rasterizer_discard = TRUE; + } + + if (context->transform_feedback_paused) + { + GL_EXTCALL(glResumeTransformFeedback()); + checkGLcall("glResumeTransformFeedback"); + context->transform_feedback_paused = 0; + } + else if (!context->transform_feedback_active) + { + GLenum mode = gl_tfb_primitive_type_from_d3d(shader->u.gs.output_type); + GL_EXTCALL(glBeginTransformFeedback(mode)); + checkGLcall("glBeginTransformFeedback"); + context->transform_feedback_active = 1; + } + } + + if (state->gl_primitive_type == GL_PATCHES) + { + GL_EXTCALL(glPatchParameteri(GL_PATCH_VERTICES, state->gl_patch_vertices)); + checkGLcall("glPatchParameteri"); + } + + if (parameters->indirect) + { + if (!context->use_immediate_mode_draw && !emulation) + draw_indirect(context, state, ¶meters->u.indirect, idx_size); + else + FIXME("Indirect draws with immediate mode/emulation are not supported.\n"); + } + else + { + unsigned int instance_count = parameters->u.direct.instance_count; + if (context->instance_count) + instance_count = context->instance_count; + + if (context->use_immediate_mode_draw || emulation) + draw_primitive_immediate_mode(context, state, stream_info, idx_data, + idx_size, parameters->u.direct.base_vertex_idx, + parameters->u.direct.start_idx, parameters->u.direct.index_count, instance_count); + else + draw_primitive_arrays(context, state, idx_data, idx_size, parameters->u.direct.base_vertex_idx, + parameters->u.direct.start_idx, parameters->u.direct.index_count, + parameters->u.direct.start_instance, instance_count); + } + + if (context->uses_uavs) + { + GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS)); + checkGLcall("glMemoryBarrier"); + } + + context_pause_transform_feedback(context, FALSE); + + if (rasterizer_discard) + { + glDisable(GL_RASTERIZER_DISCARD); + checkGLcall("disable rasterizer discard"); + } + + if (ib_fence) + wined3d_fence_issue(ib_fence, device); + for (i = 0; i < context->buffer_fence_count; ++i) + wined3d_fence_issue(context->buffer_fences[i], device); + + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +} diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c deleted file mode 100644 index 19a578a17f94..000000000000 --- a/dlls/wined3d/drawprim.c +++ /dev/null @@ -1,725 +0,0 @@ -/* - * WINED3D draw functions - * - * Copyright 2002-2004 Jason Edmeades - * Copyright 2002-2004 Raphael Junqueira - * Copyright 2004 Christian Costa - * Copyright 2005 Oliver Stieber - * Copyright 2006, 2008 Henri Verbeet - * Copyright 2007-2008 Stefan Dösinger for CodeWeavers - * Copyright 2009 Henri Verbeet for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" -#include "wine/port.h" - -#include "wined3d_private.h" - -WINE_DEFAULT_DEBUG_CHANNEL(d3d); -WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); - -/* Context activation is done by the caller. */ -static void draw_primitive_arrays(struct wined3d_context *context, const struct wined3d_state *state, - const void *idx_data, unsigned int idx_size, int base_vertex_idx, unsigned int start_idx, - unsigned int count, unsigned int start_instance, unsigned int instance_count) -{ - const struct wined3d_ffp_attrib_ops *ops = &context->d3d_info->ffp_attrib_ops; - GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - const struct wined3d_stream_info *si = &context->stream_info; - unsigned int instanced_elements[ARRAY_SIZE(si->elements)]; - const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int instanced_element_count = 0; - GLenum mode = state->gl_primitive_type; - const void *indices; - unsigned int i, j; - - indices = (const char *)idx_data + idx_size * start_idx; - - if (!instance_count) - { - if (!idx_size) - { - gl_info->gl_ops.gl.p_glDrawArrays(mode, start_idx, count); - checkGLcall("glDrawArrays"); - return; - } - - if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) - { - GL_EXTCALL(glDrawElementsBaseVertex(mode, count, idx_type, indices, base_vertex_idx)); - checkGLcall("glDrawElementsBaseVertex"); - return; - } - - gl_info->gl_ops.gl.p_glDrawElements(mode, count, idx_type, indices); - checkGLcall("glDrawElements"); - return; - } - - if (start_instance && !(gl_info->supported[ARB_BASE_INSTANCE] && gl_info->supported[ARB_INSTANCED_ARRAYS])) - FIXME("Start instance (%u) not supported.\n", start_instance); - - if (gl_info->supported[ARB_INSTANCED_ARRAYS]) - { - if (!idx_size) - { - if (gl_info->supported[ARB_BASE_INSTANCE]) - { - GL_EXTCALL(glDrawArraysInstancedBaseInstance(mode, start_idx, count, instance_count, start_instance)); - checkGLcall("glDrawArraysInstancedBaseInstance"); - return; - } - - GL_EXTCALL(glDrawArraysInstanced(mode, start_idx, count, instance_count)); - checkGLcall("glDrawArraysInstanced"); - return; - } - - if (gl_info->supported[ARB_BASE_INSTANCE]) - { - GL_EXTCALL(glDrawElementsInstancedBaseVertexBaseInstance(mode, count, idx_type, - indices, instance_count, base_vertex_idx, start_instance)); - checkGLcall("glDrawElementsInstancedBaseVertexBaseInstance"); - return; - } - if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) - { - GL_EXTCALL(glDrawElementsInstancedBaseVertex(mode, count, idx_type, - indices, instance_count, base_vertex_idx)); - checkGLcall("glDrawElementsInstancedBaseVertex"); - return; - } - - GL_EXTCALL(glDrawElementsInstanced(mode, count, idx_type, indices, instance_count)); - checkGLcall("glDrawElementsInstanced"); - return; - } - - /* Instancing emulation by mixing immediate mode and arrays. */ - - /* This is a nasty thing. MSDN says no hardware supports this and - * applications have to use software vertex processing. We don't support - * this for now. - * - * Shouldn't be too hard to support with OpenGL, in theory just call - * glDrawArrays() instead of drawElements(). But the stream fequency value - * has a different meaning in that situation. */ - if (!idx_size) - { - FIXME("Non-indexed instanced drawing is not supported.\n"); - return; - } - - for (i = 0; i < ARRAY_SIZE(si->elements); ++i) - { - if (!(si->use_map & (1u << i))) - continue; - - if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA) - instanced_elements[instanced_element_count++] = i; - } - - for (i = 0; i < instance_count; ++i) - { - /* Specify the instanced attributes using immediate mode calls. */ - for (j = 0; j < instanced_element_count; ++j) - { - const struct wined3d_stream_info_element *element; - unsigned int element_idx; - const BYTE *ptr; - - element_idx = instanced_elements[j]; - element = &si->elements[element_idx]; - ptr = element->data.addr + element->stride * i; - if (element->data.buffer_object) - ptr += (ULONG_PTR)wined3d_buffer_load_sysmem(state->streams[element->stream_idx].buffer, context); - ops->generic[element->format->emit_idx](element_idx, ptr); - } - - if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) - { - GL_EXTCALL(glDrawElementsBaseVertex(mode, count, idx_type, indices, base_vertex_idx)); - checkGLcall("glDrawElementsBaseVertex"); - } - else - { - gl_info->gl_ops.gl.p_glDrawElements(mode, count, idx_type, indices); - checkGLcall("glDrawElements"); - } - } -} - -static unsigned int get_stride_idx(const void *idx_data, unsigned int idx_size, - unsigned int base_vertex_idx, unsigned int start_idx, unsigned int vertex_idx) -{ - if (!idx_data) - return start_idx + vertex_idx; - if (idx_size == 2) - return ((const WORD *)idx_data)[start_idx + vertex_idx] + base_vertex_idx; - return ((const DWORD *)idx_data)[start_idx + vertex_idx] + base_vertex_idx; -} - -/* Context activation is done by the caller. */ -static void draw_primitive_immediate_mode(struct wined3d_context *context, const struct wined3d_state *state, - const struct wined3d_stream_info *si, const void *idx_data, unsigned int idx_size, - int base_vertex_idx, unsigned int start_idx, unsigned int vertex_count, unsigned int instance_count) -{ - const BYTE *position = NULL, *normal = NULL, *diffuse = NULL, *specular = NULL; - const struct wined3d_d3d_info *d3d_info = context->d3d_info; - unsigned int coord_idx, stride_idx, texture_idx, vertex_idx; - const struct wined3d_gl_info *gl_info = context->gl_info; - const struct wined3d_stream_info_element *element; - const BYTE *tex_coords[WINED3DDP_MAXTEXCOORD]; - unsigned int texture_unit, texture_stages; - const struct wined3d_ffp_attrib_ops *ops; - unsigned int untracked_material_count; - unsigned int tex_mask = 0; - BOOL specular_fog = FALSE; - BOOL ps = use_ps(state); - const void *ptr; - - static unsigned int once; - - if (!once++) - FIXME_(d3d_perf)("Drawing using immediate mode.\n"); - else - WARN_(d3d_perf)("Drawing using immediate mode.\n"); - - if (!idx_size && idx_data) - ERR("Non-NULL idx_data with 0 idx_size, this should never happen.\n"); - - if (instance_count) - FIXME("Instancing not implemented.\n"); - - /* Immediate mode drawing can't make use of indices in a VBO - get the - * data from the index buffer. */ - if (idx_size) - idx_data = wined3d_buffer_load_sysmem(state->index_buffer, context) + state->index_offset; - - ops = &d3d_info->ffp_attrib_ops; - - gl_info->gl_ops.gl.p_glBegin(state->gl_primitive_type); - - if (use_vs(state) || d3d_info->ffp_generic_attributes) - { - for (vertex_idx = 0; vertex_idx < vertex_count; ++vertex_idx) - { - unsigned int use_map = si->use_map; - unsigned int element_idx; - - stride_idx = get_stride_idx(idx_data, idx_size, base_vertex_idx, start_idx, vertex_idx); - for (element_idx = MAX_ATTRIBS - 1; use_map; use_map &= ~(1u << element_idx), --element_idx) - { - if (!(use_map & 1u << element_idx)) - continue; - - ptr = si->elements[element_idx].data.addr + si->elements[element_idx].stride * stride_idx; - ops->generic[si->elements[element_idx].format->emit_idx](element_idx, ptr); - } - } - - gl_info->gl_ops.gl.p_glEnd(); - return; - } - - if (si->use_map & (1u << WINED3D_FFP_POSITION)) - position = si->elements[WINED3D_FFP_POSITION].data.addr; - - if (si->use_map & (1u << WINED3D_FFP_NORMAL)) - normal = si->elements[WINED3D_FFP_NORMAL].data.addr; - else - gl_info->gl_ops.gl.p_glNormal3f(0.0f, 0.0f, 0.0f); - - untracked_material_count = context->num_untracked_materials; - if (si->use_map & (1u << WINED3D_FFP_DIFFUSE)) - { - element = &si->elements[WINED3D_FFP_DIFFUSE]; - diffuse = element->data.addr; - - if (untracked_material_count && element->format->id != WINED3DFMT_B8G8R8A8_UNORM) - FIXME("Implement diffuse color tracking from %s.\n", debug_d3dformat(element->format->id)); - } - else - { - gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } - - if (si->use_map & (1u << WINED3D_FFP_SPECULAR)) - { - element = &si->elements[WINED3D_FFP_SPECULAR]; - specular = element->data.addr; - - /* Special case where the fog density is stored in the specular alpha channel. */ - if (state->render_states[WINED3D_RS_FOGENABLE] - && (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE - || si->elements[WINED3D_FFP_POSITION].format->id == WINED3DFMT_R32G32B32A32_FLOAT) - && state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE) - { - if (gl_info->supported[EXT_FOG_COORD]) - { - if (element->format->id == WINED3DFMT_B8G8R8A8_UNORM) - specular_fog = TRUE; - else - FIXME("Implement fog coordinates from %s.\n", debug_d3dformat(element->format->id)); - } - else - { - static unsigned int once; - - if (!once++) - FIXME("Implement fog for transformed vertices in software.\n"); - } - } - } - else if (gl_info->supported[EXT_SECONDARY_COLOR]) - { - GL_EXTCALL(glSecondaryColor3fEXT)(0.0f, 0.0f, 0.0f); - } - - texture_stages = d3d_info->limits.ffp_blend_stages; - for (texture_idx = 0; texture_idx < texture_stages; ++texture_idx) - { - if (!gl_info->supported[ARB_MULTITEXTURE] && texture_idx > 0) - { - FIXME("Program using multiple concurrent textures which this OpenGL implementation doesn't support.\n"); - continue; - } - - if (!ps && !state->textures[texture_idx]) - continue; - - texture_unit = context->tex_unit_map[texture_idx]; - if (texture_unit == WINED3D_UNMAPPED_STAGE) - continue; - - coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX]; - if (coord_idx > 7) - { - TRACE("Skipping generated coordinates (%#x) for texture %u.\n", coord_idx, texture_idx); - continue; - } - - if (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))) - { - tex_coords[coord_idx] = si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].data.addr; - tex_mask |= (1u << texture_idx); - } - else - { - TRACE("Setting default coordinates for texture %u.\n", texture_idx); - if (gl_info->supported[ARB_MULTITEXTURE]) - GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_unit, 0.0f, 0.0f, 0.0f, 1.0f)); - else - gl_info->gl_ops.gl.p_glTexCoord4f(0.0f, 0.0f, 0.0f, 1.0f); - } - } - - /* Blending data and point sizes are not supported by this function. They - * are not supported by the fixed function pipeline at all. A FIXME for - * them is printed after decoding the vertex declaration. */ - for (vertex_idx = 0; vertex_idx < vertex_count; ++vertex_idx) - { - unsigned int tmp_tex_mask; - - stride_idx = get_stride_idx(idx_data, idx_size, base_vertex_idx, start_idx, vertex_idx); - - if (normal) - { - ptr = normal + stride_idx * si->elements[WINED3D_FFP_NORMAL].stride; - ops->normal[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptr); - } - - if (diffuse) - { - ptr = diffuse + stride_idx * si->elements[WINED3D_FFP_DIFFUSE].stride; - ops->diffuse[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptr); - - if (untracked_material_count) - { - struct wined3d_color color; - unsigned int i; - - wined3d_color_from_d3dcolor(&color, *(const DWORD *)ptr); - for (i = 0; i < untracked_material_count; ++i) - { - gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], &color.r); - } - } - } - - if (specular) - { - ptr = specular + stride_idx * si->elements[WINED3D_FFP_SPECULAR].stride; - ops->specular[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptr); - - if (specular_fog) - GL_EXTCALL(glFogCoordfEXT((float)(*(const DWORD *)ptr >> 24))); - } - - tmp_tex_mask = tex_mask; - for (texture_idx = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture_idx) - { - if (!(tmp_tex_mask & 1)) - continue; - - coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX]; - ptr = tex_coords[coord_idx] + (stride_idx * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride); - ops->texcoord[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx]( - GL_TEXTURE0_ARB + context->tex_unit_map[texture_idx], ptr); - } - - if (position) - { - ptr = position + stride_idx * si->elements[WINED3D_FFP_POSITION].stride; - ops->position[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptr); - } - } - - gl_info->gl_ops.gl.p_glEnd(); - checkGLcall("draw immediate mode"); -} - -static void draw_indirect(struct wined3d_context *context, const struct wined3d_state *state, - const struct wined3d_indirect_draw_parameters *parameters, unsigned int idx_size) -{ - const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_buffer *buffer = parameters->buffer; - const void *offset; - - if (!gl_info->supported[ARB_DRAW_INDIRECT]) - { - FIXME("OpenGL implementation does not support indirect draws.\n"); - return; - } - - GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->buffer_object)); - - offset = (void *)(GLintptr)parameters->offset; - if (idx_size) - { - GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - if (state->index_offset) - FIXME("Ignoring index offset %u.\n", state->index_offset); - GL_EXTCALL(glDrawElementsIndirect(state->gl_primitive_type, idx_type, offset)); - } - else - { - GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type, offset)); - } - - GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0)); - - checkGLcall("draw indirect"); -} - -static void remove_vbos(struct wined3d_context *context, - const struct wined3d_state *state, struct wined3d_stream_info *s) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(s->elements); ++i) - { - struct wined3d_stream_info_element *e; - - if (!(s->use_map & (1u << i))) - continue; - - e = &s->elements[i]; - if (e->data.buffer_object) - { - struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer; - e->data.buffer_object = 0; - e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(vb, context); - } - } -} - -static BOOL use_transform_feedback(const struct wined3d_state *state) -{ - const struct wined3d_shader *shader; - if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY])) - return FALSE; - return shader->u.gs.so_desc.element_count; -} - -static void context_pause_transform_feedback(struct wined3d_context *context, BOOL force) -{ - const struct wined3d_gl_info *gl_info = context->gl_info; - - if (!context->transform_feedback_active || context->transform_feedback_paused) - return; - - if (gl_info->supported[ARB_TRANSFORM_FEEDBACK2]) - { - GL_EXTCALL(glPauseTransformFeedback()); - checkGLcall("glPauseTransformFeedback"); - context->transform_feedback_paused = 1; - return; - } - - WARN("Cannot pause transform feedback operations.\n"); - - if (force) - context_end_transform_feedback(context); -} - -static GLenum gl_tfb_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) -{ - GLenum gl_primitive_type = gl_primitive_type_from_d3d(primitive_type); - switch (gl_primitive_type) - { - case GL_POINTS: - return GL_POINTS; - - case GL_LINE_STRIP: - case GL_LINE_STRIP_ADJACENCY: - case GL_LINES_ADJACENCY: - case GL_LINES: - return GL_LINES; - - case GL_TRIANGLE_FAN: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_STRIP_ADJACENCY: - case GL_TRIANGLES_ADJACENCY: - case GL_TRIANGLES: - return GL_TRIANGLES; - - default: - return gl_primitive_type; - } -} - -/* Routine common to the draw primitive and draw indexed primitive routines */ -void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, - const struct wined3d_draw_parameters *parameters) -{ - BOOL emulation = FALSE, rasterizer_discard = FALSE; - const struct wined3d_fb_state *fb = state->fb; - const struct wined3d_stream_info *stream_info; - struct wined3d_rendertarget_view *dsv, *rtv; - struct wined3d_stream_info si_emulated; - struct wined3d_fence *ib_fence = NULL; - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; - unsigned int i, idx_size = 0; - const void *idx_data = NULL; - - if (!parameters->indirect && !parameters->u.direct.index_count) - return; - - if (!(rtv = fb->render_targets[0])) - rtv = fb->depth_stencil; - if (rtv) - context = context_acquire(device, wined3d_texture_from_resource(rtv->resource), rtv->sub_resource_idx); - else - context = context_acquire(device, NULL, 0); - if (!context->valid) - { - context_release(context); - WARN("Invalid context, skipping draw.\n"); - return; - } - gl_info = context->gl_info; - - if (!use_transform_feedback(state)) - context_pause_transform_feedback(context, TRUE); - - for (i = 0; i < gl_info->limits.buffers; ++i) - { - if (!(rtv = fb->render_targets[i]) || rtv->format->id == WINED3DFMT_NULL) - continue; - - if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) - { - wined3d_rendertarget_view_load_location(rtv, context, rtv->resource->draw_binding); - wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); - } - else - { - wined3d_rendertarget_view_prepare_location(rtv, context, rtv->resource->draw_binding); - } - } - - if ((dsv = fb->depth_stencil)) - { - /* Note that this depends on the context_acquire() call above to set - * context->render_offscreen properly. We don't currently take the - * Z-compare function into account, but we could skip loading the - * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note - * that we never copy the stencil data.*/ - DWORD location = context->render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; - - if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) - wined3d_rendertarget_view_load_location(dsv, context, location); - else - wined3d_rendertarget_view_prepare_location(dsv, context, location); - } - - if (parameters->indirect) - wined3d_buffer_load(parameters->u.indirect.buffer, context, state); - - if (!context_apply_draw_state(context, device, state)) - { - context_release(context); - WARN("Unable to apply draw state, skipping draw.\n"); - return; - } - - if (dsv && state->render_states[WINED3D_RS_ZWRITEENABLE]) - { - DWORD location = context->render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; - - wined3d_rendertarget_view_validate_location(dsv, location); - wined3d_rendertarget_view_invalidate_location(dsv, ~location); - } - - stream_info = &context->stream_info; - - if (parameters->indexed) - { - struct wined3d_buffer *index_buffer = state->index_buffer; - if (!index_buffer->buffer_object || !stream_info->all_vbo) - { - idx_data = index_buffer->resource.heap_memory; - } - else - { - ib_fence = index_buffer->fence; - idx_data = NULL; - } - idx_data = (const BYTE *)idx_data + state->index_offset; - - if (state->index_format == WINED3DFMT_R16_UINT) - idx_size = 2; - else - idx_size = 4; - } - - if (!use_vs(state)) - { - if (!stream_info->position_transformed && context->num_untracked_materials - && state->render_states[WINED3D_RS_LIGHTING]) - { - static BOOL warned; - - if (!warned++) - FIXME("Using software emulation because not all material properties could be tracked.\n"); - else - WARN_(d3d_perf)("Using software emulation because not all material properties could be tracked.\n"); - emulation = TRUE; - } - else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE]) - { - static BOOL warned; - - /* Either write a pipeline replacement shader or convert the - * specular alpha from unsigned byte to a float in the vertex - * buffer. */ - if (!warned++) - FIXME("Using software emulation because manual fog coordinates are provided.\n"); - else - WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n"); - emulation = TRUE; - } - - if (emulation) - { - si_emulated = context->stream_info; - remove_vbos(context, state, &si_emulated); - stream_info = &si_emulated; - } - } - - if (use_transform_feedback(state)) - { - const struct wined3d_shader *shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]; - - if (is_rasterization_disabled(shader)) - { - glEnable(GL_RASTERIZER_DISCARD); - checkGLcall("enable rasterizer discard"); - rasterizer_discard = TRUE; - } - - if (context->transform_feedback_paused) - { - GL_EXTCALL(glResumeTransformFeedback()); - checkGLcall("glResumeTransformFeedback"); - context->transform_feedback_paused = 0; - } - else if (!context->transform_feedback_active) - { - GLenum mode = gl_tfb_primitive_type_from_d3d(shader->u.gs.output_type); - GL_EXTCALL(glBeginTransformFeedback(mode)); - checkGLcall("glBeginTransformFeedback"); - context->transform_feedback_active = 1; - } - } - - if (state->gl_primitive_type == GL_PATCHES) - { - GL_EXTCALL(glPatchParameteri(GL_PATCH_VERTICES, state->gl_patch_vertices)); - checkGLcall("glPatchParameteri"); - } - - if (parameters->indirect) - { - if (!context->use_immediate_mode_draw && !emulation) - draw_indirect(context, state, ¶meters->u.indirect, idx_size); - else - FIXME("Indirect draws with immediate mode/emulation are not supported.\n"); - } - else - { - unsigned int instance_count = parameters->u.direct.instance_count; - if (context->instance_count) - instance_count = context->instance_count; - - if (context->use_immediate_mode_draw || emulation) - draw_primitive_immediate_mode(context, state, stream_info, idx_data, - idx_size, parameters->u.direct.base_vertex_idx, - parameters->u.direct.start_idx, parameters->u.direct.index_count, instance_count); - else - draw_primitive_arrays(context, state, idx_data, idx_size, parameters->u.direct.base_vertex_idx, - parameters->u.direct.start_idx, parameters->u.direct.index_count, - parameters->u.direct.start_instance, instance_count); - } - - if (context->uses_uavs) - { - GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS)); - checkGLcall("glMemoryBarrier"); - } - - context_pause_transform_feedback(context, FALSE); - - if (rasterizer_discard) - { - glDisable(GL_RASTERIZER_DISCARD); - checkGLcall("disable rasterizer discard"); - } - - if (ib_fence) - wined3d_fence_issue(ib_fence, device); - for (i = 0; i < context->buffer_fence_count; ++i) - wined3d_fence_issue(context->buffer_fences[i], device); - - if (wined3d_settings.strict_draw_ordering) - gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ - - context_release(context); -} diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 650c1a554e27..07c7c024da6a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2135,8 +2135,6 @@ void context_alloc_occlusion_query(struct wined3d_context *context, void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN; BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state, UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN; -BOOL context_apply_draw_state(struct wined3d_context *context, - const struct wined3d_device *device, const struct wined3d_state *state) DECLSPEC_HIDDEN; void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN; void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info,