diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index b5241fa64c6..a7335c340ca 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -90,6 +90,9 @@ struct cso_context { void *fragment_shader, *fragment_shader_saved, *geometry_shader; void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved; + struct pipe_clip_state clip; + struct pipe_clip_state clip_saved; + struct pipe_framebuffer_state fb, fb_saved; struct pipe_viewport_state vp, vp_saved; struct pipe_blend_color blend_color; @@ -1126,3 +1129,54 @@ void cso_restore_geometry_shader(struct cso_context *ctx) } ctx->geometry_shader_saved = NULL; } + + +/* clip state */ + +static INLINE void +clip_state_cpy(struct pipe_clip_state *dst, + const struct pipe_clip_state *src) +{ + dst->nr = src->nr; + if (src->nr) { + memcpy(dst->ucp, src->ucp, src->nr * sizeof(src->ucp[0])); + } +} + +static INLINE int +clip_state_cmp(const struct pipe_clip_state *a, + const struct pipe_clip_state *b) +{ + if (a->nr != b->nr) { + return 1; + } + if (a->nr) { + return memcmp(a->ucp, b->ucp, a->nr * sizeof(a->ucp[0])); + } + return 0; +} + +void +cso_set_clip(struct cso_context *ctx, + const struct pipe_clip_state *clip) +{ + if (clip_state_cmp(&ctx->clip, clip)) { + clip_state_cpy(&ctx->clip, clip); + ctx->pipe->set_clip_state(ctx->pipe, clip); + } +} + +void +cso_save_clip(struct cso_context *ctx) +{ + clip_state_cpy(&ctx->clip_saved, &ctx->clip); +} + +void +cso_restore_clip(struct cso_context *ctx) +{ + if (clip_state_cmp(&ctx->clip, &ctx->clip_saved)) { + clip_state_cpy(&ctx->clip, &ctx->clip_saved); + ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved); + } +} diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 707b3c2cee2..251a9a644f8 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -180,6 +180,19 @@ void cso_save_stencil_ref(struct cso_context *cso); void cso_restore_stencil_ref(struct cso_context *cso); +/* clip state */ + +void +cso_set_clip(struct cso_context *cso, + const struct pipe_clip_state *clip); + +void +cso_save_clip(struct cso_context *cso); + +void +cso_restore_clip(struct cso_context *cso); + + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index d5ddc4a6a92..bb0988543f5 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -128,9 +128,7 @@ void draw_set_rasterizer_state( struct draw_context *draw, draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->rasterizer = raster; - draw->bypass_clipping = - ((draw->rasterizer && draw->rasterizer->bypass_vs_clip_and_viewport) || - draw->driver.bypass_clipping); + draw->bypass_clipping = draw->driver.bypass_clipping; } @@ -140,9 +138,7 @@ void draw_set_driver_clipping( struct draw_context *draw, draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->driver.bypass_clipping = bypass_clipping; - draw->bypass_clipping = - ((draw->rasterizer && draw->rasterizer->bypass_vs_clip_and_viewport) || - draw->driver.bypass_clipping); + draw->bypass_clipping = draw->driver.bypass_clipping; } diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 341353f6289..6d90a6c42fd 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -87,9 +87,7 @@ draw_pt_arrays(struct draw_context *draw, opt |= PT_CLIPTEST; } - if (!draw->rasterizer->bypass_vs_clip_and_viewport) { - opt |= PT_SHADE; - } + opt |= PT_SHADE; } if (opt == 0) diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c index c5dfbcfa3cb..1aecb510777 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -100,8 +100,7 @@ static void fse_prepare( struct draw_pt_middle_end *middle, fse->key.nr_elements = MAX2(fse->key.nr_outputs, /* outputs - translate to hw format */ fse->key.nr_inputs); /* inputs - fetch from api format */ - fse->key.viewport = (!draw->rasterizer->bypass_vs_clip_and_viewport && - !draw->identity_viewport); + fse->key.viewport = !draw->identity_viewport; fse->key.clip = !draw->bypass_clipping; fse->key.const_vbuffers = 0; diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index 56b69354b21..da5106463a7 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -96,8 +96,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, */ draw_pt_post_vs_prepare( fpme->post_vs, (boolean)draw->bypass_clipping, - (boolean)(draw->identity_viewport || - draw->rasterizer->bypass_vs_clip_and_viewport), + (boolean)draw->identity_viewport, (boolean)draw->rasterizer->gl_rasterization_rules, (draw->vs.edgeflag_output ? true : false) ); @@ -154,9 +153,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, (char *)pipeline_verts ); /* Run the shader, note that this overwrites the data[] parts of - * the pipeline verts. If there is no shader, eg if - * bypass_vs_clip_and_viewport, then the inputs == outputs, and are - * already in the correct place. + * the pipeline verts. */ if (opt & PT_SHADE) { @@ -239,9 +236,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, (char *)pipeline_verts ); /* Run the shader, note that this overwrites the data[] parts of - * the pipeline verts. If there is no shader, ie if - * bypass_vs_clip_and_viewport, then the inputs == outputs, and are - * already in the correct place. + * the pipeline verts. */ if (opt & PT_SHADE) { @@ -319,9 +314,7 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle (char *)pipeline_verts ); /* Run the shader, note that this overwrites the data[] parts of - * the pipeline verts. If there is no shader, ie if - * bypass_vs_clip_and_viewport, then the inputs == outputs, and are - * already in the correct place. + * the pipeline verts. */ if (opt & PT_SHADE) { diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index f0bc58a558f..0b263a9db5c 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -62,6 +62,7 @@ struct blit_state struct pipe_rasterizer_state rasterizer; struct pipe_sampler_state sampler; struct pipe_viewport_state viewport; + struct pipe_clip_state clip; void *vs; void *fs[TGSI_WRITEMASK_XYZW + 1]; @@ -101,7 +102,6 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); ctx->rasterizer.front_winding = PIPE_WINDING_CW; ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; - ctx->rasterizer.bypass_vs_clip_and_viewport = 1; ctx->rasterizer.gl_rasterization_rules = 1; /* samplers */ @@ -114,7 +114,6 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) ctx->sampler.mag_img_filter = 0; /* set later */ ctx->sampler.normalized_coords = 1; - /* vertex shader - still required to provide the linkage between * fragment shader input semantics and vertex_element/buffers. */ @@ -266,7 +265,6 @@ regions_overlap(int srcX0, int srcY0, * \param writemask controls which channels in the dest surface are sourced * from the src surface. Disabled channels are sourced * from (0,0,0,1). - * XXX what about clipping??? * XXX need some control over blitting Z and/or stencil. */ void @@ -407,14 +405,17 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_sampler_textures(ctx->cso); + cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); + cso_save_clip(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend); cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_clip(ctx->cso, &ctx->clip); /* sampler */ ctx->sampler.min_img_filter = filter; @@ -422,6 +423,17 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_single_sampler(ctx->cso, 0, &ctx->sampler); cso_single_sampler_done(ctx->cso); + /* viewport */ + ctx->viewport.scale[0] = 0.5f * dst->width; + ctx->viewport.scale[1] = 0.5f * dst->height; + ctx->viewport.scale[2] = 0.5f; + ctx->viewport.scale[3] = 1.0f; + ctx->viewport.translate[0] = 0.5f * dst->width; + ctx->viewport.translate[1] = 0.5f * dst->height; + ctx->viewport.translate[2] = 0.5f; + ctx->viewport.translate[3] = 0.0f; + cso_set_viewport(ctx->cso, &ctx->viewport); + /* texture */ cso_set_sampler_textures(ctx->cso, 1, &tex); @@ -444,8 +456,10 @@ util_blit_pixels_writemask(struct blit_state *ctx, /* draw quad */ offset = setup_vertex_data_tex(ctx, - (float) dstX0, (float) dstY0, - (float) dstX1, (float) dstY1, + (float) dstX0 / dst->width * 2.0f - 1.0f, + (float) dstY0 / dst->height * 2.0f - 1.0f, + (float) dstX1 / dst->width * 2.0f - 1.0f, + (float) dstY1 / dst->height * 2.0f - 1.0f, s0, t0, s1, t1, z); @@ -461,9 +475,11 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); cso_restore_sampler_textures(ctx->cso); + cso_restore_viewport(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); + cso_restore_clip(ctx->cso); pipe_texture_reference(&tex, NULL); } @@ -547,11 +563,13 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); + cso_save_clip(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend); cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_clip(ctx->cso, &ctx->clip); /* sampler */ ctx->sampler.min_img_filter = filter; @@ -559,6 +577,17 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_single_sampler(ctx->cso, 0, &ctx->sampler); cso_single_sampler_done(ctx->cso); + /* viewport */ + ctx->viewport.scale[0] = 0.5f * dst->width; + ctx->viewport.scale[1] = 0.5f * dst->height; + ctx->viewport.scale[2] = 0.5f; + ctx->viewport.scale[3] = 1.0f; + ctx->viewport.translate[0] = 0.5f * dst->width; + ctx->viewport.translate[1] = 0.5f * dst->height; + ctx->viewport.translate[2] = 0.5f; + ctx->viewport.translate[3] = 0.0f; + cso_set_viewport(ctx->cso, &ctx->viewport); + /* texture */ cso_set_sampler_textures(ctx->cso, 1, &tex); @@ -576,8 +605,10 @@ util_blit_pixels_tex(struct blit_state *ctx, /* draw quad */ offset = setup_vertex_data_tex(ctx, - (float) dstX0, (float) dstY0, - (float) dstX1, (float) dstY1, + (float) dstX0 / dst->width * 2.0f - 1.0f, + (float) dstY0 / dst->height * 2.0f - 1.0f, + (float) dstX1 / dst->width * 2.0f - 1.0f, + (float) dstY1 / dst->height * 2.0f - 1.0f, s0, t0, s1, t1, z); @@ -596,4 +627,5 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); + cso_restore_clip(ctx->cso); } diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 18f86068183..0ba09d33bfc 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -93,6 +93,12 @@ struct blitter_context_priv /* Rasterizer state. */ void *rs_state; + + /* Viewport state. */ + struct pipe_viewport_state viewport; + + /* Clip state. */ + struct pipe_clip_state clip; }; struct blitter_context *util_blitter_create(struct pipe_context *pipe) @@ -160,7 +166,6 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) memset(&rs_state, 0, sizeof(rs_state)); rs_state.front_winding = PIPE_WINDING_CW; rs_state.cull_mode = PIPE_WINDING_NONE; - rs_state.bypass_vs_clip_and_viewport = 1; rs_state.gl_rasterization_rules = 1; rs_state.flatshade = 1; ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); @@ -263,6 +268,9 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) pipe->set_stencil_ref(pipe, &ctx->blitter.saved_stencil_ref); + pipe->set_viewport_state(pipe, &ctx->blitter.saved_viewport); + pipe->set_clip_state(pipe, &ctx->blitter.saved_clip); + /* restore the state objects which are required to be saved before copy/fill */ if (ctx->blitter.saved_fb_state.nr_cbufs != ~0) { @@ -288,25 +296,40 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) static void blitter_set_rectangle(struct blitter_context_priv *ctx, unsigned x1, unsigned y1, unsigned x2, unsigned y2, + unsigned width, unsigned height, float depth) { int i; /* set vertex positions */ - ctx->vertices[0][0][0] = x1; /*v0.x*/ - ctx->vertices[0][0][1] = y1; /*v0.y*/ + ctx->vertices[0][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v0.x*/ + ctx->vertices[0][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v0.y*/ - ctx->vertices[1][0][0] = x2; /*v1.x*/ - ctx->vertices[1][0][1] = y1; /*v1.y*/ + ctx->vertices[1][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v1.x*/ + ctx->vertices[1][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v1.y*/ - ctx->vertices[2][0][0] = x2; /*v2.x*/ - ctx->vertices[2][0][1] = y2; /*v2.y*/ + ctx->vertices[2][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v2.x*/ + ctx->vertices[2][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v2.y*/ - ctx->vertices[3][0][0] = x1; /*v3.x*/ - ctx->vertices[3][0][1] = y2; /*v3.y*/ + ctx->vertices[3][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v3.x*/ + ctx->vertices[3][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v3.y*/ for (i = 0; i < 4; i++) ctx->vertices[i][0][2] = depth; /*z*/ + + /* viewport */ + ctx->viewport.scale[0] = 0.5f * width; + ctx->viewport.scale[1] = 0.5f * height; + ctx->viewport.scale[2] = 1.0f; + ctx->viewport.scale[3] = 1.0f; + ctx->viewport.translate[0] = 0.5f * width; + ctx->viewport.translate[1] = 0.5f * height; + ctx->viewport.translate[2] = 0.0f; + ctx->viewport.translate[3] = 0.0f; + ctx->pipe->set_viewport_state(ctx->pipe, &ctx->viewport); + + /* clip */ + ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip); } static void blitter_set_clear_color(struct blitter_context_priv *ctx, @@ -550,7 +573,7 @@ void util_blitter_clear(struct blitter_context *blitter, pipe->bind_vs_state(pipe, ctx->vs_col); blitter_set_clear_color(ctx, rgba); - blitter_set_rectangle(ctx, 0, 0, width, height, depth); + blitter_set_rectangle(ctx, 0, 0, width, height, width, height, depth); blitter_draw_quad(ctx); blitter_restore_CSOs(ctx); } @@ -633,7 +656,7 @@ static void util_blitter_do_copy(struct blitter_context *blitter, assert(0); } - blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); + blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, dst->width, dst->height, 0); blitter_draw_quad(ctx); } @@ -794,7 +817,7 @@ void util_blitter_fill(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); blitter_set_clear_color(ctx, rgba); - blitter_set_rectangle(ctx, 0, 0, width, height, 0); + blitter_set_rectangle(ctx, 0, 0, width, height, dst->width, dst->height, 0); blitter_draw_quad(ctx); blitter_restore_CSOs(ctx); } diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index a2f17073ac6..92008fce992 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -48,6 +48,8 @@ struct blitter_context struct pipe_framebuffer_state saved_fb_state; /**< framebuffer state */ struct pipe_stencil_ref saved_stencil_ref; /**< stencil ref */ + struct pipe_viewport_state saved_viewport; + struct pipe_clip_state saved_clip; int saved_num_sampler_states; void *saved_sampler_states[32]; @@ -205,6 +207,20 @@ void util_blitter_save_framebuffer(struct blitter_context *blitter, blitter->saved_fb_state = *state; } +static INLINE +void util_blitter_save_viewport(struct blitter_context *blitter, + struct pipe_viewport_state *state) +{ + blitter->saved_viewport = *state; +} + +static INLINE +void util_blitter_save_clip(struct blitter_context *blitter, + struct pipe_clip_state *state) +{ + blitter->saved_clip = *state; +} + static INLINE void util_blitter_save_fragment_sampler_states( struct blitter_context *blitter, diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c index eaf4ec90f25..ae7afd7311e 100644 --- a/src/gallium/auxiliary/util/u_dump_state.c +++ b/src/gallium/auxiliary/util/u_dump_state.c @@ -318,7 +318,6 @@ util_dump_rasterizer_state(struct os_stream *stream, const struct pipe_rasterize util_dump_member(stream, uint, state, line_stipple_factor); util_dump_member(stream, uint, state, line_stipple_pattern); util_dump_member(stream, bool, state, line_last_pixel); - util_dump_member(stream, bool, state, bypass_vs_clip_and_viewport); util_dump_member(stream, bool, state, flatshade_first); util_dump_member(stream, bool, state, gl_rasterization_rules); diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 1d7329d422b..f423882ca20 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -61,6 +61,7 @@ struct gen_mipmap_state struct pipe_depth_stencil_alpha_state depthstencil; struct pipe_rasterizer_state rasterizer; struct pipe_sampler_state sampler; + struct pipe_clip_state clip; void *vs; void *fs2d, *fsCube; @@ -1296,7 +1297,6 @@ util_create_gen_mipmap(struct pipe_context *pipe, memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); ctx->rasterizer.front_winding = PIPE_WINDING_CW; ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; - ctx->rasterizer.bypass_vs_clip_and_viewport = 1; ctx->rasterizer.gl_rasterization_rules = 1; /* sampler state */ @@ -1361,25 +1361,25 @@ get_next_slot(struct gen_mipmap_state *ctx) static unsigned set_vertex_data(struct gen_mipmap_state *ctx, enum pipe_texture_target tex_target, - uint face, float width, float height) + uint face) { unsigned offset; /* vert[0].position */ - ctx->vertices[0][0][0] = 0.0f; /*x*/ - ctx->vertices[0][0][1] = 0.0f; /*y*/ + ctx->vertices[0][0][0] = -1.0f; /*x*/ + ctx->vertices[0][0][1] = -1.0f; /*y*/ /* vert[1].position */ - ctx->vertices[1][0][0] = width; - ctx->vertices[1][0][1] = 0.0f; + ctx->vertices[1][0][0] = 1.0f; + ctx->vertices[1][0][1] = -1.0f; /* vert[2].position */ - ctx->vertices[2][0][0] = width; - ctx->vertices[2][0][1] = height; + ctx->vertices[2][0][0] = 1.0f; + ctx->vertices[2][0][1] = 1.0f; /* vert[3].position */ - ctx->vertices[3][0][0] = 0.0f; - ctx->vertices[3][0][1] = height; + ctx->vertices[3][0][0] = -1.0f; + ctx->vertices[3][0][1] = 1.0f; /* Setup vertex texcoords. This is a little tricky for cube maps. */ if (tex_target == PIPE_TEXTURE_CUBE) { @@ -1499,11 +1499,14 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); + cso_save_viewport(ctx->cso); + cso_save_clip(ctx->cso); /* bind our state */ cso_set_blend(ctx->cso, &ctx->blend); cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_clip(ctx->cso, &ctx->clip); cso_set_fragment_shader_handle(ctx->cso, fs); cso_set_vertex_shader_handle(ctx->cso, ctx->vs); @@ -1522,6 +1525,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, */ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; + struct pipe_viewport_state vp; struct pipe_surface *surf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice, @@ -1535,6 +1539,17 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, fb.height = u_minify(pt->height0, dstLevel); cso_set_framebuffer(ctx->cso, &fb); + /* viewport */ + vp.scale[0] = 0.5f * fb.width; + vp.scale[1] = 0.5f * fb.height; + vp.scale[2] = 1.0f; + vp.scale[3] = 1.0f; + vp.translate[0] = 0.5f * fb.width; + vp.translate[1] = 0.5f * fb.height; + vp.translate[2] = 0.0f; + vp.translate[3] = 0.0f; + cso_set_viewport(ctx->cso, &vp); + /* * Setup sampler state * Note: we should only have to set the min/max LOD clamps to ensure @@ -1549,12 +1564,10 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_set_sampler_textures(ctx->cso, 1, &pt); - /* quad coords in window coords (bypassing vs, clip and viewport) */ + /* quad coords in clip coords */ offset = set_vertex_data(ctx, pt->target, - face, - (float) u_minify(pt->width0, dstLevel), - (float) u_minify(pt->height0, dstLevel)); + face); util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, @@ -1578,4 +1591,6 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); + cso_restore_viewport(ctx->cso); + cso_restore_clip(ctx->cso); } diff --git a/src/gallium/docs/source/cso/rasterizer.rst b/src/gallium/docs/source/cso/rasterizer.rst index 24cc78c68de..ccd9136a2eb 100644 --- a/src/gallium/docs/source/cso/rasterizer.rst +++ b/src/gallium/docs/source/cso/rasterizer.rst @@ -10,18 +10,6 @@ multisample state, scissoring and flat/smooth shading. Members ------- -bypass_vs_clip_and_viewport -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Whether the entire TCL pipeline should be bypassed. This implies that -vertices are pre-transformed for the viewport, and will not be run -through the vertex shader. - -.. note:: - - Implementations may still clip away vertices that are not in the viewport - when this is set. - flatshade ^^^^^^^^^ diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index ca3d6aca7fa..ea259aadf35 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -101,7 +101,6 @@ struct nv30_blend_state { struct nv30_state { unsigned scissor_enabled; unsigned stipple_enabled; - unsigned viewport_bypass; unsigned fp_samplers; uint64_t dirty; diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c index 2d7781292bd..6fccd6b60e7 100644 --- a/src/gallium/drivers/nv30/nv30_state_viewport.c +++ b/src/gallium/drivers/nv30/nv30_state_viewport.c @@ -5,55 +5,25 @@ nv30_state_viewport_validate(struct nv30_context *nv30) { struct pipe_viewport_state *vpt = &nv30->viewport; struct nouveau_stateobj *so; - unsigned bypass; - - if (/*nv30->render_mode == HW &&*/ - !nv30->rasterizer->pipe.bypass_vs_clip_and_viewport) - bypass = 0; - else - bypass = 1; if (nv30->state.hw[NV30_STATE_VIEWPORT] && - (bypass || !(nv30->dirty & NV30_NEW_VIEWPORT)) && - nv30->state.viewport_bypass == bypass) + !(nv30->dirty & NV30_NEW_VIEWPORT)) return FALSE; - nv30->state.viewport_bypass = bypass; so = so_new(3, 10, 0); - if (!bypass) { - so_method(so, nv30->screen->rankine, - NV34TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(vpt->translate[0])); - so_data (so, fui(vpt->translate[1])); - so_data (so, fui(vpt->translate[2])); - so_data (so, fui(vpt->translate[3])); - so_data (so, fui(vpt->scale[0])); - so_data (so, fui(vpt->scale[1])); - so_data (so, fui(vpt->scale[2])); - so_data (so, fui(vpt->scale[3])); -/* so_method(so, nv30->screen->rankine, 0x1d78, 1); - so_data (so, 1); -*/ } else { - so_method(so, nv30->screen->rankine, - NV34TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); - so_data (so, fui(1.0)); - so_data (so, fui(1.0)); - so_data (so, fui(0.0)); - /* Not entirely certain what this is yet. The DDX uses this - * value also as it fixes rendering when you pass - * pre-transformed vertices to the GPU. My best gusss is that - * this bypasses some culling/clipping stage. Might be worth - * noting that points/lines are uneffected by whatever this - * value fixes, only filled polygons are effected. - */ -/* so_method(so, nv30->screen->rankine, 0x1d78, 1); - so_data (so, 0x110); -*/ } + so_method(so, nv30->screen->rankine, + NV34TCL_VIEWPORT_TRANSLATE_X, 8); + so_data (so, fui(vpt->translate[0])); + so_data (so, fui(vpt->translate[1])); + so_data (so, fui(vpt->translate[2])); + so_data (so, fui(vpt->translate[3])); + so_data (so, fui(vpt->scale[0])); + so_data (so, fui(vpt->scale[1])); + so_data (so, fui(vpt->scale[2])); + so_data (so, fui(vpt->scale[3])); +/* so_method(so, nv30->screen->rankine, 0x1d78, 1); + so_data (so, 1); +*/ /* TODO/FIXME: never saw value 0x0110 in renouveau dumps, only 0x0001 */ so_method(so, nv30->screen->rankine, 0x1d78, 1); so_data (so, 1); diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index 4861924dac7..97fb6a2ef94 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -101,7 +101,6 @@ struct nv40_blend_state { struct nv40_state { unsigned scissor_enabled; unsigned stipple_enabled; - unsigned viewport_bypass; unsigned fp_samplers; uint64_t dirty; diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c index 9919ba1d0b0..3aacb00f996 100644 --- a/src/gallium/drivers/nv40/nv40_state_viewport.c +++ b/src/gallium/drivers/nv40/nv40_state_viewport.c @@ -5,55 +5,24 @@ nv40_state_viewport_validate(struct nv40_context *nv40) { struct pipe_viewport_state *vpt = &nv40->viewport; struct nouveau_stateobj *so; - unsigned bypass; - - if (nv40->render_mode == HW && - !nv40->rasterizer->pipe.bypass_vs_clip_and_viewport) - bypass = 0; - else - bypass = 1; if (nv40->state.hw[NV40_STATE_VIEWPORT] && - (bypass || !(nv40->dirty & NV40_NEW_VIEWPORT)) && - nv40->state.viewport_bypass == bypass) + !(nv40->dirty & NV40_NEW_VIEWPORT)) return FALSE; - nv40->state.viewport_bypass = bypass; so = so_new(2, 9, 0); - if (!bypass) { - so_method(so, nv40->screen->curie, - NV40TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(vpt->translate[0])); - so_data (so, fui(vpt->translate[1])); - so_data (so, fui(vpt->translate[2])); - so_data (so, fui(vpt->translate[3])); - so_data (so, fui(vpt->scale[0])); - so_data (so, fui(vpt->scale[1])); - so_data (so, fui(vpt->scale[2])); - so_data (so, fui(vpt->scale[3])); - so_method(so, nv40->screen->curie, 0x1d78, 1); - so_data (so, 1); - } else { - so_method(so, nv40->screen->curie, - NV40TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); - so_data (so, fui(1.0)); - so_data (so, fui(1.0)); - so_data (so, fui(0.0)); - /* Not entirely certain what this is yet. The DDX uses this - * value also as it fixes rendering when you pass - * pre-transformed vertices to the GPU. My best gusss is that - * this bypasses some culling/clipping stage. Might be worth - * noting that points/lines are uneffected by whatever this - * value fixes, only filled polygons are effected. - */ - so_method(so, nv40->screen->curie, 0x1d78, 1); - so_data (so, 0x110); - } + so_method(so, nv40->screen->curie, + NV40TCL_VIEWPORT_TRANSLATE_X, 8); + so_data (so, fui(vpt->translate[0])); + so_data (so, fui(vpt->translate[1])); + so_data (so, fui(vpt->translate[2])); + so_data (so, fui(vpt->translate[3])); + so_data (so, fui(vpt->scale[0])); + so_data (so, fui(vpt->scale[1])); + so_data (so, fui(vpt->scale[2])); + so_data (so, fui(vpt->scale[3])); + so_method(so, nv40->screen->curie, 0x1d78, 1); + so_data (so, 1); so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]); so_ref(NULL, &so); diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index b4de3e2ba57..c540594b949 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -127,7 +127,6 @@ struct nv50_state { struct nouveau_stateobj *scissor; unsigned scissor_enabled; struct nouveau_stateobj *viewport; - unsigned viewport_bypass; struct nouveau_stateobj *tsc_upload; struct nouveau_stateobj *tic_upload; unsigned miptree_nr[PIPE_SHADER_TYPES]; diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index efab94cab74..a91b31015e2 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -375,50 +375,32 @@ nv50_state_validate(struct nv50_context *nv50) scissor_uptodate: if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) { - unsigned bypass; - - if (!nv50->rasterizer->pipe.bypass_vs_clip_and_viewport) - bypass = 0; - else - bypass = 1; - if (nv50->state.viewport && - (bypass || !(nv50->dirty & NV50_NEW_VIEWPORT)) && - nv50->state.viewport_bypass == bypass) + !(nv50->dirty & NV50_NEW_VIEWPORT)) goto viewport_uptodate; - nv50->state.viewport_bypass = bypass; so = so_new(5, 9, 0); - if (!bypass) { - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3); - so_data (so, fui(nv50->viewport.translate[0])); - so_data (so, fui(nv50->viewport.translate[1])); - so_data (so, fui(nv50->viewport.translate[2])); - so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3); - so_data (so, fui(nv50->viewport.scale[0])); - so_data (so, fui(nv50->viewport.scale[1])); - so_data (so, fui(nv50->viewport.scale[2])); + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3); + so_data (so, fui(nv50->viewport.translate[0])); + so_data (so, fui(nv50->viewport.translate[1])); + so_data (so, fui(nv50->viewport.translate[2])); + so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3); + so_data (so, fui(nv50->viewport.scale[0])); + so_data (so, fui(nv50->viewport.scale[1])); + so_data (so, fui(nv50->viewport.scale[2])); - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); - so_data (so, 1); - /* 0x0000 = remove whole primitive only (xyz) - * 0x1018 = remove whole primitive only (xy), clamp z - * 0x1080 = clip primitive (xyz) - * 0x1098 = clip primitive (xy), clamp z - */ - so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); - so_data (so, 0x1080); - /* no idea what 0f90 does */ - so_method(so, tesla, 0x0f90, 1); - so_data (so, 0); - } else { - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); - so_data (so, 0); - so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); - so_data (so, 0x0000); - so_method(so, tesla, 0x0f90, 1); - so_data (so, 1); - } + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); + so_data (so, 1); + /* 0x0000 = remove whole primitive only (xyz) + * 0x1018 = remove whole primitive only (xy), clamp z + * 0x1080 = clip primitive (xyz) + * 0x1098 = clip primitive (xy), clamp z + */ + so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); + so_data (so, 0x1080); + /* no idea what 0f90 does */ + so_method(so, tesla, 0x0f90, 1); + so_data (so, 0); so_ref(so, &nv50->state.viewport); so_ref(NULL, &so); diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 32d05749bdb..8acb1098b96 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -34,6 +34,8 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state); util_blitter_save_fragment_shader(r300->blitter, r300->fs); util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); + util_blitter_save_viewport(r300->blitter, &r300->viewport); + util_blitter_save_clip(r300->blitter, &r300->clip); } /* Clear currently bound buffers. */ diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index b98fe347b88..0d1518a05bc 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -356,12 +356,14 @@ struct r300_context { struct pipe_stencil_ref stencil_ref; + struct pipe_clip_state clip; + + struct pipe_viewport_state viewport; + /* Bitmask of dirty state objects. */ uint32_t dirty_state; /* Flag indicating whether or not the HW is dirty. */ uint32_t dirty_hw; - /* Whether the TCL engine should be in bypass mode. */ - boolean tcl_bypass; /* Whether polygon offset is enabled. */ boolean polygon_offset_enabled; /* Z buffer bit depth. */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 17d55ba3b43..addb28bded3 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -175,23 +175,15 @@ static const float * get_shader_constant( break; case RC_STATE_R300_VIEWPORT_SCALE: - if (r300->tcl_bypass) { - vec[0] = 1; - vec[1] = 1; - vec[2] = 1; - } else { - vec[0] = viewport->xscale; - vec[1] = viewport->yscale; - vec[2] = viewport->zscale; - } + vec[0] = viewport->xscale; + vec[1] = viewport->yscale; + vec[2] = viewport->zscale; break; case RC_STATE_R300_VIEWPORT_OFFSET: - if (!r300->tcl_bypass) { - vec[0] = viewport->xoffset; - vec[1] = viewport->yoffset; - vec[2] = viewport->zoffset; - } + vec[0] = viewport->xoffset; + vec[1] = viewport->yoffset; + vec[2] = viewport->zoffset; break; default: @@ -946,22 +938,16 @@ void r300_emit_viewport_state(struct r300_context* r300, struct r300_viewport_state* viewport = (struct r300_viewport_state*)state; CS_LOCALS(r300); - if (r300->tcl_bypass) { - BEGIN_CS(2); /* XXX tcl_bypass will be removed in gallium anyway */ - OUT_CS_REG(R300_VAP_VTE_CNTL, 0); - END_CS; - } else { - BEGIN_CS(size); - OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); - OUT_CS_32F(viewport->xscale); - OUT_CS_32F(viewport->xoffset); - OUT_CS_32F(viewport->yscale); - OUT_CS_32F(viewport->yoffset); - OUT_CS_32F(viewport->zscale); - OUT_CS_32F(viewport->zoffset); - OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); - END_CS; - } + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); + OUT_CS_32F(viewport->xscale); + OUT_CS_32F(viewport->xoffset); + OUT_CS_32F(viewport->yscale); + OUT_CS_32F(viewport->yoffset); + OUT_CS_32F(viewport->zscale); + OUT_CS_32F(viewport->zoffset); + OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); + END_CS; } void r300_emit_ztop_state(struct r300_context* r300, diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 12bf0838711..b732380a145 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -376,6 +376,8 @@ static void r300_set_clip_state(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); + r300->clip = *state; + if (r300_screen(pipe->screen)->caps->has_tcl) { memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state)); r300->clip_state.size = 29; @@ -714,8 +716,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, /* If bypassing TCL, or if no TCL engine is present, turn off the HW TCL. * Else, enable HW TCL and force Draw's TCL off. */ - if (state->bypass_vs_clip_and_viewport || - !r300screen->caps->has_tcl) { + if (!r300screen->caps->has_tcl) { rs->vap_control_status |= R300_VAP_TCL_BYPASS; } @@ -811,11 +812,9 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) } if (rs) { - r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport; r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; r300->rs_state.dirty = TRUE; } else { - r300->tcl_bypass = FALSE; r300->polygon_offset_enabled = FALSE; } @@ -982,6 +981,8 @@ static void r300_set_viewport_state(struct pipe_context* pipe, struct r300_viewport_state* viewport = (struct r300_viewport_state*)r300->viewport_state.state; + r300->viewport = *state; + /* Do the transform in HW. */ viewport->vte_control = R300_VTX_W0_FMT; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 6eb7f2bfd19..9c8e907fdf7 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -119,13 +119,7 @@ static void r300_vertex_psc(struct r300_context* r300) memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); - /* If TCL is bypassed, map vertex streams to equivalent VS output - * locations. */ - if (r300->tcl_bypass) { - stream_tab = vs->stream_loc_notcl; - } else { - stream_tab = identity; - } + stream_tab = identity; /* Vertex shaders have no semantics on their inputs, * so PSC should just route stuff based on the vertex elements, diff --git a/src/gallium/drivers/softpipe/sp_video_context.c b/src/gallium/drivers/softpipe/sp_video_context.c index 272ad40a902..242aaac4665 100644 --- a/src/gallium/drivers/softpipe/sp_video_context.c +++ b/src/gallium/drivers/softpipe/sp_video_context.c @@ -176,7 +176,6 @@ init_pipe_state(struct sp_mpeg12_context *ctx) rast.line_stipple_factor = 0; rast.line_stipple_pattern = 0; rast.line_last_pixel = 0; - rast.bypass_vs_clip_and_viewport = 0; rast.line_width = 1; rast.point_smooth = 0; rast.point_quad_rasterization = 0; diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c index b4cafb8f219..4d0c06bd77e 100644 --- a/src/gallium/drivers/svga/svga_state_framebuffer.c +++ b/src/gallium/drivers/svga/svga_state_framebuffer.c @@ -120,174 +120,153 @@ static int emit_viewport( struct svga_context *svga, float fb_width = svga->curr.framebuffer.width; float fb_height = svga->curr.framebuffer.height; + float fx = viewport->scale[0] * -1.0 + viewport->translate[0]; + float fy = flip * viewport->scale[1] * -1.0 + viewport->translate[1]; + float fw = viewport->scale[0] * 2; + float fh = flip * viewport->scale[1] * 2; + memset( &prescale, 0, sizeof(prescale) ); - if (svga->curr.rast->templ.bypass_vs_clip_and_viewport) { + /* Examine gallium viewport transformation and produce a screen + * rectangle and possibly vertex shader pre-transformation to + * get the same results. + */ - /* Avoid POSITIONT as it has a non trivial implementation outside the D3D - * API. Always generate a vertex shader. - */ - rect.x = 0; - rect.y = 0; - rect.w = svga->curr.framebuffer.width; - rect.h = svga->curr.framebuffer.height; + SVGA_DBG(DEBUG_VIEWPORT, + "\ninitial %f,%f %fx%f\n", + fx, + fy, + fw, + fh); - prescale.scale[0] = 2.0 / (float)rect.w; - prescale.scale[1] = - 2.0 / (float)rect.h; - prescale.scale[2] = 1.0; - prescale.scale[3] = 1.0; - prescale.translate[0] = -1.0f; - prescale.translate[1] = 1.0f; - prescale.translate[2] = 0; - prescale.translate[3] = 0; - prescale.enabled = TRUE; - } else { - - /* Examine gallium viewport transformation and produce a screen - * rectangle and possibly vertex shader pre-transformation to - * get the same results. - */ - float fx = viewport->scale[0] * -1.0 + viewport->translate[0]; - float fy = flip * viewport->scale[1] * -1.0 + viewport->translate[1]; - float fw = viewport->scale[0] * 2; - float fh = flip * viewport->scale[1] * 2; - - SVGA_DBG(DEBUG_VIEWPORT, - "\ninitial %f,%f %fx%f\n", - fx, - fy, - fw, - fh); - - prescale.scale[0] = 1.0; - prescale.scale[1] = 1.0; - prescale.scale[2] = 1.0; - prescale.scale[3] = 1.0; - prescale.translate[0] = 0; - prescale.translate[1] = 0; - prescale.translate[2] = 0; - prescale.translate[3] = 0; - prescale.enabled = TRUE; + prescale.scale[0] = 1.0; + prescale.scale[1] = 1.0; + prescale.scale[2] = 1.0; + prescale.scale[3] = 1.0; + prescale.translate[0] = 0; + prescale.translate[1] = 0; + prescale.translate[2] = 0; + prescale.translate[3] = 0; + prescale.enabled = TRUE; - if (fw < 0) { - prescale.scale[0] *= -1.0; - prescale.translate[0] += -fw; - fw = -fw; - fx = viewport->scale[0] * 1.0 + viewport->translate[0]; - } + if (fw < 0) { + prescale.scale[0] *= -1.0; + prescale.translate[0] += -fw; + fw = -fw; + fx = viewport->scale[0] * 1.0 + viewport->translate[0]; + } - if (fh < 0) { - prescale.scale[1] *= -1.0; - prescale.translate[1] += -fh; - fh = -fh; - fy = flip * viewport->scale[1] * 1.0 + viewport->translate[1]; - } + if (fh < 0) { + prescale.scale[1] *= -1.0; + prescale.translate[1] += -fh; + fh = -fh; + fy = flip * viewport->scale[1] * 1.0 + viewport->translate[1]; + } - if (fx < 0) { - prescale.translate[0] += fx; - prescale.scale[0] *= fw / (fw + fx); - fw += fx; - fx = 0; - } + if (fx < 0) { + prescale.translate[0] += fx; + prescale.scale[0] *= fw / (fw + fx); + fw += fx; + fx = 0; + } - if (fy < 0) { - prescale.translate[1] += fy; - prescale.scale[1] *= fh / (fh + fy); - fh += fy; - fy = 0; - } + if (fy < 0) { + prescale.translate[1] += fy; + prescale.scale[1] *= fh / (fh + fy); + fh += fy; + fy = 0; + } - if (fx + fw > fb_width) { - prescale.scale[0] *= fw / (fb_width - fx); - prescale.translate[0] -= fx * (fw / (fb_width - fx)); - prescale.translate[0] += fx; - fw = fb_width - fx; - - } - - if (fy + fh > fb_height) { - prescale.scale[1] *= fh / (fb_height - fy); - prescale.translate[1] -= fy * (fh / (fb_height - fy)); - prescale.translate[1] += fy; - fh = fb_height - fy; - } - - if (fw < 0 || fh < 0) { - fw = fh = fx = fy = 0; - degenerate = TRUE; - goto out; - } - - - /* D3D viewport is integer space. Convert fx,fy,etc. to - * integers. - * - * TODO: adjust pretranslate correct for any subpixel error - * introduced converting to integers. - */ - rect.x = fx; - rect.y = fy; - rect.w = fw; - rect.h = fh; - - SVGA_DBG(DEBUG_VIEWPORT, - "viewport error %f,%f %fx%f\n", - fabs((float)rect.x - fx), - fabs((float)rect.y - fy), - fabs((float)rect.w - fw), - fabs((float)rect.h - fh)); - - SVGA_DBG(DEBUG_VIEWPORT, - "viewport %d,%d %dx%d\n", - rect.x, - rect.y, - rect.w, - rect.h); + if (fx + fw > fb_width) { + prescale.scale[0] *= fw / (fb_width - fx); + prescale.translate[0] -= fx * (fw / (fb_width - fx)); + prescale.translate[0] += fx; + fw = fb_width - fx; + } - /* Finally, to get GL rasterization rules, need to tweak the - * screen-space coordinates slightly relative to D3D which is - * what hardware implements natively. - */ - if (svga->curr.rast->templ.gl_rasterization_rules) { - float adjust_x = 0.0; - float adjust_y = 0.0; + if (fy + fh > fb_height) { + prescale.scale[1] *= fh / (fb_height - fy); + prescale.translate[1] -= fy * (fh / (fb_height - fy)); + prescale.translate[1] += fy; + fh = fb_height - fy; + } - switch (svga->curr.reduced_prim) { - case PIPE_PRIM_LINES: - adjust_x = -0.5; - adjust_y = 0; - break; - case PIPE_PRIM_POINTS: - case PIPE_PRIM_TRIANGLES: - adjust_x = -0.375; - adjust_y = -0.5; - break; - } + if (fw < 0 || fh < 0) { + fw = fh = fx = fy = 0; + degenerate = TRUE; + goto out; + } - prescale.translate[0] += adjust_x; - prescale.translate[1] += adjust_y; - prescale.translate[2] = 0.5; /* D3D clip space */ - prescale.scale[2] = 0.5; /* D3D clip space */ + + /* D3D viewport is integer space. Convert fx,fy,etc. to + * integers. + * + * TODO: adjust pretranslate correct for any subpixel error + * introduced converting to integers. + */ + rect.x = fx; + rect.y = fy; + rect.w = fw; + rect.h = fh; + + SVGA_DBG(DEBUG_VIEWPORT, + "viewport error %f,%f %fx%f\n", + fabs((float)rect.x - fx), + fabs((float)rect.y - fy), + fabs((float)rect.w - fw), + fabs((float)rect.h - fh)); + + SVGA_DBG(DEBUG_VIEWPORT, + "viewport %d,%d %dx%d\n", + rect.x, + rect.y, + rect.w, + rect.h); + + + /* Finally, to get GL rasterization rules, need to tweak the + * screen-space coordinates slightly relative to D3D which is + * what hardware implements natively. + */ + if (svga->curr.rast->templ.gl_rasterization_rules) { + float adjust_x = 0.0; + float adjust_y = 0.0; + + switch (svga->curr.reduced_prim) { + case PIPE_PRIM_LINES: + adjust_x = -0.5; + adjust_y = 0; + break; + case PIPE_PRIM_POINTS: + case PIPE_PRIM_TRIANGLES: + adjust_x = -0.375; + adjust_y = -0.5; + break; } + prescale.translate[0] += adjust_x; + prescale.translate[1] += adjust_y; + prescale.translate[2] = 0.5; /* D3D clip space */ + prescale.scale[2] = 0.5; /* D3D clip space */ + } - range_min = viewport->scale[2] * -1.0 + viewport->translate[2]; - range_max = viewport->scale[2] * 1.0 + viewport->translate[2]; - /* D3D (and by implication SVGA) doesn't like dealing with zmax - * less than zmin. Detect that case, flip the depth range and - * invert our z-scale factor to achieve the same effect. - */ - if (range_min > range_max) { - float range_tmp; - range_tmp = range_min; - range_min = range_max; - range_max = range_tmp; - prescale.scale[2] = -prescale.scale[2]; - } + range_min = viewport->scale[2] * -1.0 + viewport->translate[2]; + range_max = viewport->scale[2] * 1.0 + viewport->translate[2]; + + /* D3D (and by implication SVGA) doesn't like dealing with zmax + * less than zmin. Detect that case, flip the depth range and + * invert our z-scale factor to achieve the same effect. + */ + if (range_min > range_max) { + float range_tmp; + range_tmp = range_min; + range_min = range_max; + range_max = range_tmp; + prescale.scale[2] = -prescale.scale[2]; } if (prescale.enabled) { diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c index dd13a89d24d..a6ed18599c4 100644 --- a/src/gallium/drivers/svga/svga_state_need_swtnl.c +++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c @@ -129,8 +129,7 @@ static int update_need_pipeline( struct svga_context *svga, /* SVGA_NEW_CLIP */ - if (!svga->curr.rast->templ.bypass_vs_clip_and_viewport && - svga->curr.clip.nr) { + if (svga->curr.clip.nr) { SVGA_DBG(DEBUG_SWTNL, "%s: userclip\n", __FUNCTION__); need_pipeline = TRUE; } diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 6da186a6555..f97d963dba6 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -112,7 +112,6 @@ void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state) trace_dump_member(uint, state, line_stipple_factor); trace_dump_member(uint, state, line_stipple_pattern); trace_dump_member(bool, state, line_last_pixel); - trace_dump_member(bool, state, bypass_vs_clip_and_viewport); trace_dump_member(bool, state, flatshade_first); trace_dump_member(bool, state, gl_rasterization_rules); diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 5ac5c878135..02558520bfe 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -113,16 +113,6 @@ struct pipe_rasterizer_state unsigned line_stipple_pattern:16; unsigned line_last_pixel:1; - /** - * Vertex coordinates are pre-transformed to screen space. Skip - * the vertex shader, clipping and viewport processing. Note that - * a vertex shader is still needed though, to indicate the mapping - * from vertex elements to fragment shader input semantics. - * - * XXX: considered for removal. - */ - unsigned bypass_vs_clip_and_viewport:1; - /** * Use the first vertex of a primitive as the provoking vertex for * flat shading. diff --git a/src/mesa/state_tracker/st_atom_clip.c b/src/mesa/state_tracker/st_atom_clip.c index 23d709b814c..80c0e921398 100644 --- a/src/mesa/state_tracker/st_atom_clip.c +++ b/src/mesa/state_tracker/st_atom_clip.c @@ -35,6 +35,8 @@ #include "pipe/p_context.h" #include "st_atom.h" +#include "cso_cache/cso_context.h" + /* Second state atom for user clip planes: */ @@ -56,7 +58,7 @@ static void update_clip( struct st_context *st ) if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) { st->state.clip = clip; - st->pipe->set_clip_state(st->pipe, &clip); + cso_set_clip(st->cso_context, &clip); } } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 898c32293d1..9e66eed3634 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -62,11 +62,9 @@ st_init_clear(struct st_context *st) { struct pipe_context *pipe = st->pipe; - memset(&st->clear.raster, 0, sizeof(st->clear.raster)); - st->clear.raster.gl_rasterization_rules = 1; + memset(&st->clear, 0, sizeof(st->clear)); - /* rasterizer state: bypass vertex shader, clipping and viewport */ - st->clear.raster.bypass_vs_clip_and_viewport = 1; + st->clear.raster.gl_rasterization_rules = 1; /* fragment shader state: color pass-through program */ st->clear.fs = @@ -104,9 +102,7 @@ st_destroy_clear(struct st_context *st) /** * Draw a screen-aligned quadrilateral. - * Coords are window coords with y=0=bottom. These will be passed - * through unmodified to the rasterizer as we have set - * rasterizer->bypass_vs_clip_and_viewport. + * Coords are clip coords with y=0=bottom. */ static void draw_quad(GLcontext *ctx, @@ -192,18 +188,13 @@ clear_with_quad(GLcontext *ctx, GLboolean color, GLboolean depth, GLboolean stencil) { struct st_context *st = ctx->st; - const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin; - const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax; - GLfloat y0, y1; - - if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { - y0 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax); - y1 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin); - } - else { - y0 = (GLfloat) ctx->DrawBuffer->_Ymin; - y1 = (GLfloat) ctx->DrawBuffer->_Ymax; - } + const struct gl_framebuffer *fb = ctx->DrawBuffer; + const GLfloat fb_width = (GLfloat) fb->Width; + const GLfloat fb_height = (GLfloat) fb->Height; + const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f; + const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; + const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; + const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, @@ -218,6 +209,8 @@ clear_with_quad(GLcontext *ctx, cso_save_stencil_ref(st->cso_context); cso_save_depth_stencil_alpha(st->cso_context); cso_save_rasterizer(st->cso_context); + cso_save_viewport(st->cso_context); + cso_save_clip(st->cso_context); cso_save_fragment_shader(st->cso_context); cso_save_vertex_shader(st->cso_context); @@ -273,6 +266,22 @@ clear_with_quad(GLcontext *ctx, cso_set_rasterizer(st->cso_context, &st->clear.raster); + /* viewport state: viewport matching window dims */ + { + const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); + struct pipe_viewport_state vp; + vp.scale[0] = 0.5f * fb_width; + vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f); + vp.scale[2] = 1.0f; + vp.scale[3] = 1.0f; + vp.translate[0] = 0.5f * fb_width; + vp.translate[1] = 0.5f * fb_height; + vp.translate[2] = 0.0f; + vp.translate[3] = 0.0f; + cso_set_viewport(st->cso_context, &vp); + } + + cso_set_clip(st->cso_context, &st->clear.clip); cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); @@ -284,9 +293,10 @@ clear_with_quad(GLcontext *ctx, cso_restore_stencil_ref(st->cso_context); cso_restore_depth_stencil_alpha(st->cso_context); cso_restore_rasterizer(st->cso_context); + cso_restore_viewport(st->cso_context); + cso_restore_clip(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); - } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 13b7b0e22d7..045c029c305 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -166,6 +166,7 @@ struct st_context struct { struct pipe_rasterizer_state raster; struct pipe_viewport_state viewport; + struct pipe_clip_state clip; void *vs; void *fs; float vertices[4][2][4]; /**< vertex pos + color */