From 54cb382ea55610688c97465ef048a4990b8fd4d7 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 26 Nov 2010 22:49:20 +0800 Subject: [PATCH] st/vega: Add SCISSOR renderer state. The state can be used to set rectangles of the depth buffer to 0.0f. update_clip_state is changed to use the state for scissor update. --- src/gallium/state_trackers/vega/renderer.c | 93 ++++++++++++++++++++ src/gallium/state_trackers/vega/renderer.h | 8 ++ src/gallium/state_trackers/vega/vg_context.c | 74 ++++++---------- 3 files changed, 126 insertions(+), 49 deletions(-) diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 179b6f6c834..60c4315a1fd 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -47,6 +47,7 @@ typedef enum { RENDERER_STATE_INIT, RENDERER_STATE_COPY, RENDERER_STATE_DRAWTEX, + RENDERER_STATE_SCISSOR, NUM_RENDERER_STATES } RendererState; @@ -60,6 +61,7 @@ typedef enum { typedef enum { RENDERER_FS_COLOR, RENDERER_FS_TEXTURE, + RENDERER_FS_SCISSOR, NUM_RENDERER_FS } RendererFs; @@ -89,6 +91,10 @@ struct renderer { VGint tex_width; VGint tex_height; } drawtex; + + struct { + VGboolean restore_dsa; + } scissor; } u; }; @@ -174,6 +180,25 @@ static void renderer_set_vs(struct renderer *r, RendererVs id) cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]); } +/** + * Create a simple fragment shader that sets the depth to 0.0f. + */ +static void *create_scissor_fs(struct pipe_context *pipe) +{ + struct ureg_program *ureg; + struct ureg_dst out; + struct ureg_src imm; + + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f); + + ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm); + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + /** * Set renderer fragment shader. * @@ -193,6 +218,9 @@ static void renderer_set_fs(struct renderer *r, RendererFs id) fs = util_make_fragment_tex_shader(r->pipe, TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR); break; + case RENDERER_FS_SCISSOR: + fs = create_scissor_fs(r->pipe); + break; default: assert(!"Unknown renderer fs id"); break; @@ -530,6 +558,71 @@ void renderer_drawtex_end(struct renderer *renderer) renderer->state = RENDERER_STATE_INIT; } +/** + * Prepare the renderer for scissor update. This will reset the depth buffer + * to 1.0f. + */ +VGboolean renderer_scissor_begin(struct renderer *renderer, + VGboolean restore_dsa) +{ + struct pipe_depth_stencil_alpha_state dsa; + + assert(renderer->state == RENDERER_STATE_INIT); + + if (restore_dsa) + cso_save_depth_stencil_alpha(renderer->cso); + cso_save_blend(renderer->cso); + cso_save_fragment_shader(renderer->cso); + + /* enable depth writes */ + memset(&dsa, 0, sizeof(dsa)); + dsa.depth.enabled = 1; + dsa.depth.writemask = 1; + dsa.depth.func = PIPE_FUNC_ALWAYS; + cso_set_depth_stencil_alpha(renderer->cso, &dsa); + + /* disable color writes */ + renderer_set_blend(renderer, 0); + renderer_set_fs(renderer, RENDERER_FS_SCISSOR); + + renderer->u.scissor.restore_dsa = restore_dsa; + renderer->state = RENDERER_STATE_SCISSOR; + + /* clear the depth buffer to 1.0f */ + renderer->pipe->clear(renderer->pipe, + PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0); + + return VG_TRUE; +} + +/** + * Add a scissor rectangle. Depth values inside the rectangle will be set to + * 0.0f. + */ +void renderer_scissor(struct renderer *renderer, + VGint x, VGint y, VGint width, VGint height) +{ + assert(renderer->state == RENDERER_STATE_SCISSOR); + + renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE); + renderer_quad_draw(renderer); +} + +/** + * End scissor update and restore the states. + */ +void renderer_scissor_end(struct renderer *renderer) +{ + assert(renderer->state == RENDERER_STATE_SCISSOR); + + if (renderer->u.scissor.restore_dsa) + cso_restore_depth_stencil_alpha(renderer->cso); + cso_restore_blend(renderer->cso); + cso_restore_fragment_shader(renderer->cso); + + renderer->state = RENDERER_STATE_INIT; +} + static void setup_shaders(struct renderer *ctx) { struct pipe_context *pipe = ctx->pipe; diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h index cc9e3ddb1a4..2644c9f580d 100644 --- a/src/gallium/state_trackers/vega/renderer.h +++ b/src/gallium/state_trackers/vega/renderer.h @@ -60,6 +60,14 @@ void renderer_drawtex(struct renderer *renderer, void renderer_drawtex_end(struct renderer *renderer); +VGboolean renderer_scissor_begin(struct renderer *renderer, + VGboolean restore_dsa); + +void renderer_scissor(struct renderer *renderer, + VGint x, VGint y, VGint width, VGint height); + +void renderer_scissor_end(struct renderer *renderer); + void renderer_draw_quad(struct renderer *, VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2, diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index bd82a81e3dd..d5347838807 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -44,6 +44,7 @@ #include "util/u_memory.h" #include "util/u_blit.h" #include "util/u_sampler.h" +#include "util/u_math.h" struct vg_context *_vg_context = 0; @@ -276,65 +277,40 @@ static void update_clip_state(struct vg_context *ctx) memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); if (state->scissoring) { - struct pipe_blend_state *blend = &ctx->state.g3d.blend; struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; int i; - dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/ - dsa->depth.func = PIPE_FUNC_ALWAYS; - dsa->depth.enabled = 1; - - cso_save_blend(ctx->cso_context); - cso_save_fragment_shader(ctx->cso_context); - /* set a passthrough shader */ - if (!ctx->pass_through_depth_fs) - ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe, - pass_through_depth_asm, - 40, - PIPE_SHADER_FRAGMENT); - cso_set_fragment_shader_handle(ctx->cso_context, - ctx->pass_through_depth_fs->driver); - cso_set_depth_stencil_alpha(ctx->cso_context, dsa); - - ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); - - /* disable color writes */ - blend->rt[0].colormask = 0; /*disable colorwrites*/ - cso_set_blend(ctx->cso_context, blend); - - /* enable scissoring */ + renderer_scissor_begin(ctx->renderer, VG_FALSE); + for (i = 0; i < state->scissor_rects_num; ++i) { const float x = state->scissor_rects[i * 4 + 0].f; const float y = state->scissor_rects[i * 4 + 1].f; const float width = state->scissor_rects[i * 4 + 2].f; const float height = state->scissor_rects[i * 4 + 3].f; - VGfloat minx, miny, maxx, maxy; - - minx = 0; - miny = 0; - maxx = fb->width; - maxy = fb->height; - - if (x > minx) - minx = x; - if (y > miny) - miny = y; - - if (x + width < maxx) - maxx = x + width; - if (y + height < maxy) - maxy = y + height; - - /* check for null space */ - if (minx >= maxx || miny >= maxy) - minx = miny = maxx = maxy = 0; - - /*glClear(GL_DEPTH_BUFFER_BIT);*/ - renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f); + VGint x0, y0, x1, y1, iw, ih; + + x0 = (VGint) x; + y0 = (VGint) y; + if (x0 < 0) + x0 = 0; + if (y0 < 0) + y0 = 0; + + /* note that x1 and y1 are exclusive */ + x1 = (VGint) ceilf(x + width); + y1 = (VGint) ceilf(y + height); + if (x1 > fb->width) + x1 = fb->width; + if (y1 > fb->height) + y1 = fb->height; + + iw = x1 - x0; + ih = y1 - y0; + if (iw > 0 && ih> 0 ) + renderer_scissor(ctx->renderer, x0, y0, iw, ih); } - cso_restore_blend(ctx->cso_context); - cso_restore_fragment_shader(ctx->cso_context); + renderer_scissor_end(ctx->renderer); dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ -- 2.30.2