[PATCH 4/7] wined3d: Merge drawprim.c into context.c.

Józef Kucia joseph.kucia at gmail.com
Sun Feb 25 16:23:31 CST 2018


From: Józef Kucia <jkucia at codeweavers.com>

Signed-off-by: Józef Kucia <jkucia at 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, &parameters->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, &parameters->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,
-- 
2.16.1




More information about the wine-devel mailing list