commit 0deb0ba0475d1a9fd9032640dc14175939763eb0 Author: Matteo Bruni Date: Fri Oct 23 23:12:55 2015 +0200 wined3d: Put FFP blit setup in a separate function. To be able to avoid setting up states that aren't relevant for some blitters. FIXME: context_apply_blit_ffp_state() should probably manage its own context flag (last_was_ffp_blit?) to avoid redundant work and avoid potential performance regressions. diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 6941a2bb3c..894c715427 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -7833,6 +7833,7 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl wined3d_texture_load(src_texture, context, FALSE); context_apply_blit_state(context, device); + context_apply_blit_ffp_state(context, device); if (dst_location == WINED3D_LOCATION_DRAWABLE) { diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 23f63aacda..fe9a011825 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2379,55 +2379,17 @@ void context_enable_clip_distances(struct wined3d_context *context, unsigned int checkGLcall("toggle clip distances"); } -/***************************************************************************** - * SetupForBlit - * - * Sets up a context for DirectDraw blitting. - * All texture units are disabled, texture unit 0 is set as current unit - * fog, lighting, blending, alpha test, z test, scissor test, culling disabled - * color writing enabled for all channels - * register combiners disabled, shaders disabled - * world matrix is set to identity, texture matrix 0 too - * projection matrix is setup for drawing screen coordinates - * - * Params: - * This: Device to activate the context for - * context: Context to setup - * - *****************************************************************************/ +/* Setup OpenGL states for fixed-function blitting. */ /* Context activation is done by the caller. */ -static void SetupForBlit(const struct wined3d_device *device, struct wined3d_context *context) +void context_apply_blit_ffp_state(struct wined3d_context *context, const struct wined3d_device *device) { int i; const struct wined3d_gl_info *gl_info = context->gl_info; DWORD sampler; SIZE rt_size; - TRACE("Setting up context %p for blitting\n", context); - - context_get_rt_size(context, &rt_size); - - if (context->last_was_blit) - { - if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy) - { - set_blit_dimension(gl_info, rt_size.cx, rt_size.cy); - context->blit_w = rt_size.cx; - context->blit_h = rt_size.cy; - /* No need to dirtify here, the states are still dirtified because - * they weren't applied since the last SetupForBlit() call. */ - } - TRACE("Context is already set up for blitting, nothing to do\n"); - return; - } - context->last_was_blit = TRUE; - /* Disable all textures. The caller can then bind a texture it wants to blit - * from - * - * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed - * function texture unit. No need to care for higher samplers - */ + * from. */ for (i = gl_info->limits.textures - 1; i > 0 ; --i) { sampler = context->rev_tex_unit_map[i]; @@ -2458,11 +2420,8 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con context_invalidate_state(context, STATE_SAMPLER(sampler)); } } - if (gl_info->supported[ARB_SAMPLER_OBJECTS]) - GL_EXTCALL(glBindSampler(0, 0)); - context_active_texture(context, gl_info, 0); - sampler = context->rev_tex_unit_map[0]; + context_active_texture(context, gl_info, 0); if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) { @@ -2486,60 +2445,12 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con gl_info->gl_ops.gl.p_glLoadIdentity(); checkGLcall("glLoadIdentity()"); - if (gl_info->supported[EXT_TEXTURE_LOD_BIAS]) - { - gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, - GL_TEXTURE_LOD_BIAS_EXT, 0.0f); - checkGLcall("glTexEnvf GL_TEXTURE_LOD_BIAS_EXT ..."); - } - - if (sampler != WINED3D_UNMAPPED_STAGE) - { - if (sampler < MAX_TEXTURES) - { - context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + sampler)); - context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)); - } - context_invalidate_state(context, STATE_SAMPLER(sampler)); - } - - /* Other misc states */ - gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); - checkGLcall("glDisable(GL_ALPHA_TEST)"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE)); gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING); checkGLcall("glDisable GL_LIGHTING"); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING)); - gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST); - checkGLcall("glDisable GL_DEPTH_TEST"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE)); glDisableWINE(GL_FOG); checkGLcall("glDisable GL_FOG"); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_BLEND); - checkGLcall("glDisable GL_BLEND"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE); - checkGLcall("glDisable GL_CULL_FACE"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE)); - gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); - checkGLcall("glDisable GL_STENCIL_TEST"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); - checkGLcall("glDisable GL_SCISSOR_TEST"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE)); - if (gl_info->supported[ARB_POINT_SPRITE]) - { - gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB); - checkGLcall("glDisable GL_POINT_SPRITE_ARB"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE)); - } - gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE); - checkGLcall("glColorMask"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE)); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1)); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2)); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3)); if (gl_info->supported[EXT_SECONDARY_COLOR]) { gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT); @@ -2553,24 +2464,8 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con gl_info->gl_ops.gl.p_glLoadIdentity(); checkGLcall("glLoadIdentity()"); context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))); - - context->last_was_rhw = TRUE; - context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */ - - context_enable_clip_distances(context, 0); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING)); - - /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */ - if (gl_info->supported[ARB_CLIP_CONTROL]) - GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE)); - + context_get_rt_size(context, &rt_size); set_blit_dimension(gl_info, rt_size.cx, rt_size.cy); - - /* Disable shaders */ - device->shader_backend->shader_disable(device->shader_priv, context); - - context->blit_w = rt_size.cx; - context->blit_h = rt_size.cy; context_invalidate_state(context, STATE_VIEWPORT); context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); } @@ -2911,10 +2806,14 @@ static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *conte /* Context activation is done by the caller. */ void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) { + const struct wined3d_gl_info *gl_info = context->gl_info; struct wined3d_texture *rt = context->current_rt.texture; struct wined3d_surface *surface; DWORD rt_mask, *cur_mask; + DWORD sampler; + SIZE rt_size; + TRACE("Setting up context %p for blitting.\n", context); if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { context_validate_onscreen_formats(context, NULL); @@ -2955,8 +2854,98 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine context_check_fbo_status(context, GL_FRAMEBUFFER); } - SetupForBlit(device, context); + context_get_rt_size(context, &rt_size); + + if (context->last_was_blit) + { + if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy) + { + context->blit_w = rt_size.cx; + context->blit_h = rt_size.cy; + /* No need to dirtify here, the states are still dirtified because + * they weren't applied since the last context_apply_blit_state() + * call. */ + } + TRACE("Context is already set up for blitting, nothing to do\n"); + return; + } + context->last_was_blit = TRUE; + + if (gl_info->supported[ARB_SAMPLER_OBJECTS]) + GL_EXTCALL(glBindSampler(0, 0)); + context_active_texture(context, gl_info, 0); + sampler = context->rev_tex_unit_map[0]; + + if (gl_info->supported[EXT_TEXTURE_LOD_BIAS]) + { + gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, + GL_TEXTURE_LOD_BIAS_EXT, 0.0f); + checkGLcall("glTexEnvf(GL_TEXTURE_LOD_BIAS_EXT)"); + } + + if (sampler != WINED3D_UNMAPPED_STAGE) + { + if (sampler < MAX_TEXTURES) + { + context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + sampler)); + context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)); + } + context_invalidate_state(context, STATE_SAMPLER(sampler)); + } + + gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); + checkGLcall("glDisable(GL_ALPHA_TEST)"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST); + checkGLcall("glDisable(GL_DEPTH_TEST)"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_BLEND); + checkGLcall("glDisable(GL_BLEND)"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE); + checkGLcall("glDisable(GL_CULL_FACE)"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE)); + gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); + checkGLcall("glDisable(GL_STENCIL_TEST)"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); + checkGLcall("glDisable(GL_SCISSOR_TEST)"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE)); + /* Commenting out this (and the FBO blits) breaks test_pointsize() in + * d3d9:visual on r600g (legacy profile only, core doesn't have the toggle + * and that works fine). + * This seems to be a driver bug, Nvidia works fine. */ + if (gl_info->supported[ARB_POINT_SPRITE]) + { + gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB); + checkGLcall("glDisable GL_POINT_SPRITE_ARB"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE)); + } + gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + checkGLcall("glColorMask"); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE)); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1)); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2)); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3)); + + context->last_was_rhw = TRUE; + context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */ + + context_enable_clip_distances(context, 0); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING)); + + device->shader_backend->shader_disable(device->shader_priv, context); + + context->blit_w = rt_size.cx; + context->blit_h = rt_size.cy; + context_invalidate_state(context, STATE_FRAMEBUFFER); + + /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */ + if (gl_info->supported[ARB_CLIP_CONTROL]) + GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE)); + gl_info->gl_ops.gl.p_glViewport(0, 0, rt_size.cx, rt_size.cy); + context_invalidate_state(context, STATE_VIEWPORT); } static BOOL context_validate_rt_config(UINT rt_count, struct wined3d_rendertarget_view * const *rts, diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 02e0c70382..71e414c0e7 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1649,6 +1649,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st context = context_acquire(device, src_texture, src_sub_resource_idx); gl_info = context->gl_info; context_apply_blit_state(context, device); + context_apply_blit_ffp_state(context, device); wined3d_texture_load(dst_texture, context, FALSE); offscreen_buffer = context_get_offscreen_gl_buffer(context); @@ -2798,8 +2799,8 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit * unless we're overwriting it completely. */ wined3d_texture_load(src_texture, context, FALSE); - /* Activate the destination context, set it up for blitting. */ context_apply_blit_state(context, device); + context_apply_blit_ffp_state(context, device); if (dst_location == WINED3D_LOCATION_DRAWABLE) { @@ -2858,7 +2859,6 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit checkGLcall("glDisable(GL_ALPHA_TEST)"); } - /* Leave the OpenGL state valid for blitting. */ gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); checkGLcall("glDisable(GL_TEXTURE_2D)"); if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1d0b39df03..e33a2139e4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2127,6 +2127,7 @@ void context_alloc_fence(struct wined3d_context *context, struct wined3d_fence * void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN; +void context_apply_blit_ffp_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,