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.
This commit is contained in:
Chia-I Wu 2010-11-26 22:49:20 +08:00
parent e31a04ea3b
commit 54cb382ea5
3 changed files with 122 additions and 45 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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;
renderer_scissor_begin(ctx->renderer, VG_FALSE);
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 */
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;
VGint x0, y0, x1, y1, iw, ih;
minx = 0;
miny = 0;
maxx = fb->width;
maxy = fb->height;
x0 = (VGint) x;
y0 = (VGint) y;
if (x0 < 0)
x0 = 0;
if (y0 < 0)
y0 = 0;
if (x > minx)
minx = x;
if (y > miny)
miny = y;
/* 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;
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);
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);*/