From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/context.c | 61 +++++++++++++++++++++++++++++++++++++++++- dlls/wined3d/drawprim.c | 59 ---------------------------------------- dlls/wined3d/wined3d_private.h | 2 -- 3 files changed, 60 insertions(+), 62 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 4929b843c244..e36898f84fd9 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -4003,7 +4003,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, return TRUE; }
-void context_apply_compute_state(struct wined3d_context *context, +static void context_apply_compute_state(struct wined3d_context *context, const struct wined3d_device *device, const struct wined3d_state *state) { const struct StateEntry *state_table = context->state_table; @@ -4227,3 +4227,62 @@ struct wined3d_context *context_reacquire(const struct wined3d_device *device, ERR("Acquired context %p instead of %p.\n", current_context, context); return current_context; } + +void dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state, + const struct wined3d_dispatch_parameters *parameters) +{ + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + + context = context_acquire(device, NULL, 0); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping dispatch.\n"); + return; + } + gl_info = context->gl_info; + + if (!gl_info->supported[ARB_COMPUTE_SHADER]) + { + context_release(context); + FIXME("OpenGL implementation does not support compute shaders.\n"); + return; + } + + if (parameters->indirect) + wined3d_buffer_load(parameters->u.indirect.buffer, context, state); + + context_apply_compute_state(context, device, state); + + if (!state->shader[WINED3D_SHADER_TYPE_COMPUTE]) + { + context_release(context); + WARN("No compute shader bound, skipping dispatch.\n"); + return; + } + + if (parameters->indirect) + { + const struct wined3d_indirect_dispatch_parameters *indirect = ¶meters->u.indirect; + struct wined3d_buffer *buffer = indirect->buffer; + + GL_EXTCALL(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->buffer_object)); + GL_EXTCALL(glDispatchComputeIndirect((GLintptr)indirect->offset)); + GL_EXTCALL(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0)); + } + else + { + const struct wined3d_direct_dispatch_parameters *direct = ¶meters->u.direct; + GL_EXTCALL(glDispatchCompute(direct->group_count_x, direct->group_count_y, direct->group_count_z)); + } + checkGLcall("dispatch compute"); + + GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS)); + checkGLcall("glMemoryBarrier"); + + 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 index 7eccc8f7d621..f87f0919c166 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -727,62 +727,3 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
TRACE("Done all gl drawing.\n"); } - -void dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state, - const struct wined3d_dispatch_parameters *parameters) -{ - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; - - context = context_acquire(device, NULL, 0); - if (!context->valid) - { - context_release(context); - WARN("Invalid context, skipping dispatch.\n"); - return; - } - gl_info = context->gl_info; - - if (!gl_info->supported[ARB_COMPUTE_SHADER]) - { - context_release(context); - FIXME("OpenGL implementation does not support compute shaders.\n"); - return; - } - - if (parameters->indirect) - wined3d_buffer_load(parameters->u.indirect.buffer, context, state); - - context_apply_compute_state(context, device, state); - - if (!state->shader[WINED3D_SHADER_TYPE_COMPUTE]) - { - context_release(context); - WARN("No compute shader bound, skipping dispatch.\n"); - return; - } - - if (parameters->indirect) - { - const struct wined3d_indirect_dispatch_parameters *indirect = ¶meters->u.indirect; - struct wined3d_buffer *buffer = indirect->buffer; - - GL_EXTCALL(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->buffer_object)); - GL_EXTCALL(glDispatchComputeIndirect((GLintptr)indirect->offset)); - GL_EXTCALL(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0)); - } - else - { - const struct wined3d_direct_dispatch_parameters *direct = ¶meters->u.direct; - GL_EXTCALL(glDispatchCompute(direct->group_count_x, direct->group_count_y, direct->group_count_z)); - } - checkGLcall("dispatch compute"); - - GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS)); - checkGLcall("glMemoryBarrier"); - - 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 b4d15c5b5f95..650c1a554e27 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; -void context_apply_compute_state(struct wined3d_context *context, - const struct wined3d_device *device, const struct wined3d_state *state) 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,
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/drawprim.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index f87f0919c166..2f3390b5b083 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -44,27 +44,29 @@ static void draw_primitive_arrays(struct wined3d_context *context, const struct 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(state->gl_primitive_type, start_idx, count); + 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(state->gl_primitive_type, count, idx_type, - (const char *)idx_data + (idx_size * start_idx), base_vertex_idx)); + GL_EXTCALL(glDrawElementsBaseVertex(mode, count, idx_type, indices, base_vertex_idx)); checkGLcall("glDrawElementsBaseVertex"); return; }
- gl_info->gl_ops.gl.p_glDrawElements(state->gl_primitive_type, count, - idx_type, (const char *)idx_data + (idx_size * start_idx)); + gl_info->gl_ops.gl.p_glDrawElements(mode, count, idx_type, indices); checkGLcall("glDrawElements"); return; } @@ -78,33 +80,32 @@ static void draw_primitive_arrays(struct wined3d_context *context, const struct { if (gl_info->supported[ARB_BASE_INSTANCE]) { - GL_EXTCALL(glDrawArraysInstancedBaseInstance(state->gl_primitive_type, start_idx, count, instance_count, start_instance)); + GL_EXTCALL(glDrawArraysInstancedBaseInstance(mode, start_idx, count, instance_count, start_instance)); checkGLcall("glDrawArraysInstancedBaseInstance"); return; }
- GL_EXTCALL(glDrawArraysInstanced(state->gl_primitive_type, start_idx, count, instance_count)); + GL_EXTCALL(glDrawArraysInstanced(mode, start_idx, count, instance_count)); checkGLcall("glDrawArraysInstanced"); return; }
if (gl_info->supported[ARB_BASE_INSTANCE]) { - GL_EXTCALL(glDrawElementsInstancedBaseVertexBaseInstance(state->gl_primitive_type, count, idx_type, - (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_idx, start_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(state->gl_primitive_type, count, idx_type, - (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_idx)); + GL_EXTCALL(glDrawElementsInstancedBaseVertex(mode, count, idx_type, + indices, instance_count, base_vertex_idx)); checkGLcall("glDrawElementsInstancedBaseVertex"); return; }
- GL_EXTCALL(glDrawElementsInstanced(state->gl_primitive_type, count, idx_type, - (const char *)idx_data + (idx_size * start_idx), instance_count)); + GL_EXTCALL(glDrawElementsInstanced(mode, count, idx_type, indices, instance_count)); checkGLcall("glDrawElementsInstanced"); return; } @@ -120,7 +121,7 @@ static void draw_primitive_arrays(struct wined3d_context *context, const struct * has a different meaning in that situation. */ if (!idx_size) { - FIXME("Non-indexed instanced drawing is not supported\n"); + FIXME("Non-indexed instanced drawing is not supported.\n"); return; }
@@ -152,14 +153,12 @@ static void draw_primitive_arrays(struct wined3d_context *context, const struct
if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) { - GL_EXTCALL(glDrawElementsBaseVertex(state->gl_primitive_type, count, idx_type, - (const char *)idx_data + (idx_size * start_idx), base_vertex_idx)); + GL_EXTCALL(glDrawElementsBaseVertex(mode, count, idx_type, indices, base_vertex_idx)); checkGLcall("glDrawElementsBaseVertex"); } else { - gl_info->gl_ops.gl.p_glDrawElements(state->gl_primitive_type, count, idx_type, - (const char *)idx_data + (idx_size * start_idx)); + gl_info->gl_ops.gl.p_glDrawElements(mode, count, idx_type, indices); checkGLcall("glDrawElements"); } }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/drawprim.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 2f3390b5b083..19a578a17f94 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -29,9 +29,8 @@
#include "wined3d_private.h"
-WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw); +WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); -WINE_DECLARE_DEBUG_CHANNEL(d3d);
/* Context activation is done by the caller. */ static void draw_primitive_arrays(struct wined3d_context *context, const struct wined3d_state *state, @@ -391,7 +390,7 @@ static void draw_primitive_immediate_mode(struct wined3d_context *context, const }
gl_info->gl_ops.gl.p_glEnd(); - checkGLcall("glEnd and previous calls"); + checkGLcall("draw immediate mode"); }
static void draw_indirect(struct wined3d_context *context, const struct wined3d_state *state, @@ -399,6 +398,7 @@ static void draw_indirect(struct wined3d_context *context, const struct wined3d_ { 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]) { @@ -408,18 +408,17 @@ static void draw_indirect(struct wined3d_context *context, const struct wined3d_
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, - (void *)(GLintptr)parameters->offset)); + GL_EXTCALL(glDrawElementsIndirect(state->gl_primitive_type, idx_type, offset)); } else { - GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type, - (void *)(GLintptr)parameters->offset)); + GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type, offset)); }
GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0)); @@ -723,6 +722,4 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
context_release(context); - - TRACE("Done all gl drawing.\n"); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
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,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
D3D_MAX_SIMULTANEOUS_RENDERTARGETS is defined in d3d9types.h.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d9/d3d9_private.h | 3 +-- dlls/d3d9/device.c | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index ee385d9c939c..ba19e5fb08fe 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -42,7 +42,6 @@
#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256 #define D3D9_MAX_TEXTURE_UNITS 20 -#define D3D9_MAX_SIMULTANEOUS_RENDERTARGETS 4
#define D3DPRESENTFLAGS_MASK 0x00000fffu
@@ -103,7 +102,7 @@ struct d3d9_device UINT index_buffer_pos;
struct d3d9_texture *textures[D3D9_MAX_TEXTURE_UNITS]; - struct d3d9_surface *render_targets[D3D9_MAX_SIMULTANEOUS_RENDERTARGETS]; + struct d3d9_surface *render_targets[D3D_MAX_SIMULTANEOUS_RENDERTARGETS];
LONG device_state; BOOL in_destruction; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 1c9a625223c6..e8798a746ccd 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -453,7 +453,7 @@ void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps) D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2| D3DPTEXTURECAPS_NOPROJECTEDBUMPENV;
caps->MaxVertexShaderConst = min(D3D9_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst); - caps->NumSimultaneousRTs = min(D3D9_MAX_SIMULTANEOUS_RENDERTARGETS, caps->NumSimultaneousRTs); + caps->NumSimultaneousRTs = min(D3D_MAX_SIMULTANEOUS_RENDERTARGETS, caps->NumSimultaneousRTs);
if (caps->PixelShaderVersion > 3) { @@ -1784,7 +1784,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
- if (idx >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS) + if (idx >= D3D_MAX_SIMULTANEOUS_RENDERTARGETS) { WARN("Invalid index %u specified.\n", idx); return D3DERR_INVALIDCALL; @@ -1825,7 +1825,7 @@ static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWO if (!surface) return D3DERR_INVALIDCALL;
- if (idx >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS) + if (idx >= D3D_MAX_SIMULTANEOUS_RENDERTARGETS) { WARN("Invalid index %u specified.\n", idx); return D3DERR_INVALIDCALL;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Virtually all relatively modern GPUs support 8 render targets.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/context.c | 4 ++-- dlls/wined3d/cs.c | 24 +++++------------------- dlls/wined3d/device.c | 28 +++++++++------------------- dlls/wined3d/directx.c | 2 +- dlls/wined3d/wined3d_private.h | 3 ++- 5 files changed, 19 insertions(+), 42 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 235b75b9a86b..2ae1715e249b 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -3019,7 +3019,7 @@ static BOOL context_validate_rt_config(UINT rt_count, struct wined3d_rendertarge BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state, UINT rt_count, const struct wined3d_fb_state *fb) { - struct wined3d_rendertarget_view **rts = fb->render_targets; + struct wined3d_rendertarget_view * const *rts = fb->render_targets; struct wined3d_rendertarget_view *dsv = fb->depth_stencil; const struct wined3d_gl_info *gl_info = context->gl_info; DWORD rt_mask = 0, *cur_mask; @@ -3128,7 +3128,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_state *state) { - struct wined3d_rendertarget_view **rts = state->fb->render_targets; + struct wined3d_rendertarget_view * const *rts = state->fb->render_targets; struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL]; DWORD rt_mask, rt_mask_bits; unsigned int i; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 2f77c7b0b7e8..9f3ff4691d1a 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -563,17 +563,11 @@ void wined3d_cs_emit_clear_rendertarget_view(struct wined3d_cs *cs, struct wined const RECT *rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) { struct wined3d_cs_clear *op; - struct - { - struct wined3d_rendertarget_view *rt; - struct wined3d_fb_state fb; - } *extra; + size_t size;
- op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_clear, rects[1]) + sizeof(*extra), - WINED3D_CS_QUEUE_DEFAULT); - extra = (void *)&op->rects[1]; - extra->fb.render_targets = &extra->rt; - op->fb = &extra->fb; + size = FIELD_OFFSET(struct wined3d_cs_clear, rects[1]) + sizeof(struct wined3d_fb_state); + op = cs->ops->require_space(cs, size, WINED3D_CS_QUEUE_DEFAULT); + op->fb = (void *)&op->rects[1];
op->opcode = WINED3D_CS_OP_CLEAR; op->flags = flags; @@ -994,7 +988,7 @@ static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const v { const struct wined3d_cs_set_rendertarget_view *op = data;
- cs->state.fb->render_targets[op->view_idx] = op->view; + cs->fb.render_targets[op->view_idx] = op->view; device_invalidate_state(cs->device, STATE_FRAMEBUFFER); }
@@ -2734,12 +2728,6 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) cs->ops = &wined3d_cs_st_ops; cs->device = device;
- if (!(cs->fb.render_targets = heap_calloc(gl_info->limits.buffers, sizeof(*cs->fb.render_targets)))) - { - heap_free(cs); - return NULL; - } - state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info, WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT);
@@ -2782,7 +2770,6 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
fail: state_cleanup(&cs->state); - heap_free(cs->fb.render_targets); heap_free(cs); return NULL; } @@ -2798,7 +2785,6 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) }
state_cleanup(&cs->state); - heap_free(cs->fb.render_targets); heap_free(cs->data); heap_free(cs); } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 6e275e1cffef..1318a1c4537b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1045,7 +1045,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, struct wined3d_swapchain_desc *swapchain_desc) { static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f}; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_swapchain *swapchain = NULL; DWORD clear_flags = 0; HRESULT hr; @@ -1057,16 +1056,14 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, if (device->wined3d->flags & WINED3D_NO3D) return WINED3DERR_INVALIDCALL;
- if (!(device->fb.render_targets = heap_calloc(gl_info->limits.buffers, sizeof(*device->fb.render_targets)))) - return E_OUTOFMEMORY; + memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets));
/* Setup the implicit swapchain. This also initializes a context. */ - TRACE("Creating implicit swapchain\n"); - hr = device->device_parent->ops->create_swapchain(device->device_parent, - swapchain_desc, &swapchain); - if (FAILED(hr)) + TRACE("Creating implicit swapchain.\n"); + if (FAILED(hr = device->device_parent->ops->create_swapchain(device->device_parent, + swapchain_desc, &swapchain))) { - WARN("Failed to create implicit swapchain\n"); + WARN("Failed to create implicit swapchain.\n"); goto err_out; }
@@ -1103,7 +1100,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
device->contexts[0]->last_was_rhw = 0;
- TRACE("All defaults now set up, leaving 3D init.\n"); + TRACE("All defaults now set up.\n");
/* Clear the screen */ if (swapchain->back_buffers && swapchain->back_buffers[0]) @@ -1126,7 +1123,6 @@ err_out: wined3d_rendertarget_view_decref(device->back_buffer_view); if (swapchain) wined3d_swapchain_decref(swapchain); - heap_free(device->fb.render_targets);
return hr; } @@ -1181,7 +1177,7 @@ static void device_free_sampler(struct wine_rb_entry *entry, void *context)
HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) { - UINT i; + unsigned int i;
TRACE("device %p.\n", device);
@@ -1241,9 +1237,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) device->swapchains = NULL; device->swapchain_count = 0;
- heap_free(device->fb.render_targets); - device->fb.render_targets = NULL; - device->d3d_initialized = FALSE;
return WINED3D_OK; @@ -4753,12 +4746,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, state_unbind_resources(&device->state); }
- if (device->fb.render_targets) + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) { - for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) - { - wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); - } + wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); } wined3d_device_set_depth_stencil_view(device, NULL);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index f7f6452fa953..a1577c2aac3c 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3521,7 +3521,7 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info) if (gl_info->supported[ARB_DRAW_BUFFERS] && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max); - gl_info->limits.buffers = gl_max; + gl_info->limits.buffers = min(MAX_RENDER_TARGET_VIEWS, gl_max); TRACE("Max draw buffers: %u.\n", gl_max); } if (gl_info->supported[ARB_MULTITEXTURE]) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 07c7c024da6a..7813df5b6ef3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -271,6 +271,7 @@ static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup #define MAX_CONSTANT_BUFFERS 15 #define MAX_SAMPLER_OBJECTS 16 #define MAX_SHADER_RESOURCE_VIEWS 128 +#define MAX_RENDER_TARGET_VIEWS 8 #define MAX_UNORDERED_ACCESS_VIEWS 8 #define MAX_TGSM_REGISTERS 8192 #define MAX_VERTEX_BLENDS 4 @@ -1993,7 +1994,7 @@ struct wined3d_context
struct wined3d_fb_state { - struct wined3d_rendertarget_view **render_targets; + struct wined3d_rendertarget_view *render_targets[MAX_RENDER_TARGET_VIEWS]; struct wined3d_rendertarget_view *depth_stencil; };
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/context.c | 75 +++++++++++++++--------------------------- dlls/wined3d/wined3d_private.h | 6 ++-- 2 files changed, 29 insertions(+), 52 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 2ae1715e249b..c5fb5f494c9c 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -372,18 +372,19 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ const struct wined3d_gl_info *gl_info = context->gl_info; GLenum status;
- if (!FIXME_ON(d3d)) return; + if (!FIXME_ON(d3d)) + return;
status = gl_info->fbo_ops.glCheckFramebufferStatus(target); if (status == GL_FRAMEBUFFER_COMPLETE) { - TRACE("FBO complete\n"); + TRACE("FBO complete.\n"); } else { unsigned int i;
- FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status); + FIXME("FBO status %s (%#x).\n", debug_fbostatus(status), status);
if (!context->current_fbo) { @@ -396,7 +397,6 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ
for (i = 0; i < gl_info->limits.buffers; ++i) context_dump_fbo_attachment(gl_info, target, GL_COLOR_ATTACHMENT0 + i); - checkGLcall("Dump FBO attachments"); } }
@@ -493,9 +493,9 @@ static inline void context_set_fbo_key_for_render_target(const struct wined3d_co
static void context_generate_fbo_key(const struct wined3d_context *context, struct wined3d_fbo_entry_key *key, struct wined3d_rendertarget_info *render_targets, - struct wined3d_surface *depth_stencil_surface, DWORD color_location, - DWORD ds_location) + struct wined3d_surface *depth_stencil_surface, DWORD color_location, DWORD ds_location) { + unsigned int buffers = context->gl_info->limits.buffers; struct wined3d_rendertarget_info depth_stencil = {{0}}; unsigned int i;
@@ -508,8 +508,10 @@ static void context_generate_fbo_key(const struct wined3d_context *context, } context_set_fbo_key_for_render_target(context, key, 0, &depth_stencil, ds_location);
- for (i = 0; i < context->gl_info->limits.buffers; ++i) + for (i = 0; i < buffers; ++i) context_set_fbo_key_for_render_target(context, key, i + 1, &render_targets[i], color_location); + + memset(&key->objects[buffers + 1], 0, (ARRAY_SIZE(key->objects) - buffers - 1) * sizeof(*key->objects)); }
static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context, @@ -517,11 +519,9 @@ static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context * DWORD color_location, DWORD ds_location) { const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int object_count = gl_info->limits.buffers + 1; struct fbo_entry *entry;
- entry = heap_alloc(FIELD_OFFSET(struct fbo_entry, key.objects[object_count])); - memset(&entry->key, 0, FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[object_count])); + entry = heap_alloc(sizeof(*entry)); context_generate_fbo_key(context, &entry->key, render_targets, depth_stencil, color_location, ds_location); entry->flags = 0; if (depth_stencil) @@ -579,8 +579,8 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, DWORD color_location, DWORD ds_location) { const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int object_count = gl_info->limits.buffers + 1; struct wined3d_texture *rt_texture, *ds_texture; + struct wined3d_fbo_entry_key fbo_key; struct fbo_entry *entry; unsigned int i, level;
@@ -610,8 +610,7 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, surface_set_compatible_renderbuffer(depth_stencil, &render_targets[0]); }
- context_generate_fbo_key(context, context->fbo_key, render_targets, depth_stencil, color_location, - ds_location); + context_generate_fbo_key(context, &fbo_key, render_targets, depth_stencil, color_location, ds_location);
if (TRACE_ON(d3d)) { @@ -641,8 +640,8 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
TRACE(" Color attachment %u: %p, %u format %s, %s %u, %ux%u, %u samples.\n", i, resource, render_targets[i].sub_resource_idx, debug_d3dformat(resource->format->id), - context->fbo_key->rb_namespace & (1 << (i + 1)) ? "renderbuffer" : resource_type, - context->fbo_key->objects[i + 1].object, width, height, resource->multisample_type); + fbo_key.rb_namespace & (1 << (i + 1)) ? "renderbuffer" : resource_type, + fbo_key.objects[i + 1].object, width, height, resource->multisample_type); } } if (depth_stencil) @@ -650,8 +649,7 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, ds_texture = depth_stencil->container; TRACE(" Depth attachment: %p format %s, %s %u, %ux%u, %u samples.\n", depth_stencil, debug_d3dformat(ds_texture->resource.format->id), - context->fbo_key->rb_namespace & (1 << 0) ? "renderbuffer" : "texture", - context->fbo_key->objects[0].object, + fbo_key.rb_namespace & (1 << 0) ? "renderbuffer" : "texture", fbo_key.objects[0].object, wined3d_texture_get_level_pow2_width(ds_texture, depth_stencil->texture_level), wined3d_texture_get_level_pow2_height(ds_texture, depth_stencil->texture_level), ds_texture->resource.multisample_type); @@ -660,7 +658,7 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry) { - if (memcmp(context->fbo_key, &entry->key, FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[object_count]))) + if (memcmp(&fbo_key, &entry->key, sizeof(fbo_key))) continue;
list_remove(&entry->entry); @@ -762,7 +760,7 @@ static void context_apply_fbo_state(struct wined3d_context *context, GLenum targ void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) { - memset(context->blit_targets, 0, context->gl_info->limits.buffers * sizeof(*context->blit_targets)); + memset(context->blit_targets, 0, sizeof(context->blit_targets)); if (render_target) { context->blit_targets[0].resource = &render_target->container->resource; @@ -1001,7 +999,7 @@ typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct static void context_enum_fbo_entries(const struct wined3d_device *device, GLuint name, BOOL rb_namespace, context_fbo_entry_func_t *callback) { - UINT i; + unsigned int i, j;
for (i = 0; i < device->context_count; ++i) { @@ -1011,8 +1009,6 @@ static void context_enum_fbo_entries(const struct wined3d_device *device,
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) { - UINT j; - for (j = 0; j < gl_info->limits.buffers + 1; ++j) { if (entry->key.objects[j].object == name @@ -1868,16 +1864,6 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, if (!(ret = heap_alloc_zero(sizeof(*ret)))) return NULL;
- if (!(ret->blit_targets = heap_calloc(gl_info->limits.buffers, sizeof(*ret->blit_targets)))) - goto out; - - if (!(ret->draw_buffers = heap_calloc(gl_info->limits.buffers, sizeof(*ret->draw_buffers)))) - goto out; - - if (!(ret->fbo_key = heap_alloc_zero(FIELD_OFFSET(struct wined3d_fbo_entry_key, - objects[gl_info->limits.buffers + 1])))) - goto out; - ret->free_timestamp_query_size = 4; if (!(ret->free_timestamp_queries = heap_calloc(ret->free_timestamp_query_size, sizeof(*ret->free_timestamp_queries)))) @@ -2252,9 +2238,6 @@ out: heap_free(ret->free_fences); heap_free(ret->free_occlusion_queries); heap_free(ret->free_timestamp_queries); - heap_free(ret->fbo_key); - heap_free(ret->draw_buffers); - heap_free(ret->blit_targets); heap_free(ret); return NULL; } @@ -2298,9 +2281,6 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont device->shader_backend->shader_free_context_data(context); device->adapter->fragment_pipe->free_context_data(context); heap_free(context->texture_type); - heap_free(context->fbo_key); - heap_free(context->draw_buffers); - heap_free(context->blit_targets); device_context_remove(device, context); if (destroy) heap_free(context); @@ -2629,16 +2609,15 @@ static inline GLenum draw_buffer_from_rt_mask(DWORD rt_mask) static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt_mask) { const struct wined3d_gl_info *gl_info = context->gl_info; + GLenum draw_buffers[MAX_RENDER_TARGET_VIEWS];
if (!rt_mask) { gl_info->gl_ops.gl.p_glDrawBuffer(GL_NONE); - checkGLcall("glDrawBuffer()"); } else if (is_rt_mask_onscreen(rt_mask)) { gl_info->gl_ops.gl.p_glDrawBuffer(draw_buffer_from_rt_mask(rt_mask)); - checkGLcall("glDrawBuffer()"); } else { @@ -2649,9 +2628,9 @@ static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt while (rt_mask) { if (rt_mask & 1) - context->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i; + draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i; else - context->draw_buffers[i] = GL_NONE; + draw_buffers[i] = GL_NONE;
rt_mask >>= 1; ++i; @@ -2659,13 +2638,11 @@ static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt
if (gl_info->supported[ARB_DRAW_BUFFERS]) { - GL_EXTCALL(glDrawBuffers(i, context->draw_buffers)); - checkGLcall("glDrawBuffers()"); + GL_EXTCALL(glDrawBuffers(i, draw_buffers)); } else { - gl_info->gl_ops.gl.p_glDrawBuffer(context->draw_buffers[0]); - checkGLcall("glDrawBuffer()"); + gl_info->gl_ops.gl.p_glDrawBuffer(draw_buffers[0]); } } else @@ -2673,6 +2650,8 @@ static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt ERR("Unexpected draw buffers mask with backbuffer ORM.\n"); } } + + checkGLcall("apply draw buffers"); }
/* Context activation is done by the caller. */ @@ -3037,7 +3016,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource)) { - memset(context->blit_targets, 0, gl_info->limits.buffers * sizeof(*context->blit_targets)); + memset(context->blit_targets, 0, sizeof(context->blit_targets)); for (i = 0; i < rt_count; ++i) { if (rts[i]) @@ -3172,7 +3151,7 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat { unsigned int i;
- memset(context->blit_targets, 0, context->gl_info->limits.buffers * sizeof (*context->blit_targets)); + memset(context->blit_targets, 0, sizeof(context->blit_targets)); for (i = 0; i < context->gl_info->limits.buffers; ++i) { if (fb->render_targets[i]) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7813df5b6ef3..f085f2d8b85e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1945,9 +1945,7 @@ struct wined3d_context struct fbo_entry *current_fbo; GLuint fbo_read_binding; GLuint fbo_draw_binding; - struct wined3d_rendertarget_info *blit_targets; - struct wined3d_fbo_entry_key *fbo_key; - GLenum *draw_buffers; + struct wined3d_rendertarget_info blit_targets[MAX_RENDER_TARGET_VIEWS]; DWORD draw_buffers_mask; /* Enabled draw buffers, 31 max. */
/* Queries */ @@ -3299,7 +3297,7 @@ struct fbo_entry struct wined3d_fbo_entry_key { DWORD rb_namespace; - struct wined3d_fbo_resource objects[1]; + struct wined3d_fbo_resource objects[MAX_RENDER_TARGET_VIEWS + 1]; } key; };