Exemple #1
0
/**
 * Render a polygon silhouette to stencil buffer.
 */
void renderer_polygon_stencil(struct renderer *renderer,
                              struct pipe_vertex_buffer *vbuf,
                              VGuint mode, VGuint start, VGuint count)
{
   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);

   cso_set_vertex_buffers(renderer->cso, 0, 1, vbuf);

   if (!renderer->u.polygon_stencil.manual_two_sides) {
      cso_draw_arrays(renderer->cso, mode, start, count);
   }
   else {
      struct pipe_rasterizer_state raster;
      struct pipe_depth_stencil_alpha_state dsa;

      raster = renderer->g3d.rasterizer;
      dsa = renderer->u.polygon_stencil.dsa;

      /* front */
      raster.cull_face = PIPE_FACE_BACK;
      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;

      cso_set_rasterizer(renderer->cso, &raster);
      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
      cso_draw_arrays(renderer->cso, mode, start, count);

      /* back */
      raster.cull_face = PIPE_FACE_FRONT;
      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;

      cso_set_rasterizer(renderer->cso, &raster);
      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
      cso_draw_arrays(renderer->cso, mode, start, count);
   }
}
Exemple #2
0
static void
util_set_dsa_disable(struct cso_context *cso)
{
   struct pipe_depth_stencil_alpha_state dsa = {{0}};

   cso_set_depth_stencil_alpha(cso, &dsa);
}
static void draw(struct program *p)
{
	/* set the render target */
	cso_set_framebuffer(p->cso, &p->framebuffer);

	/* clear the render target */
	p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0);

	/* set misc state we care about */
	cso_set_blend(p->cso, &p->blend);
	cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
	cso_set_rasterizer(p->cso, &p->rasterizer);
	cso_set_viewport(p->cso, &p->viewport);

	/* shaders */
	cso_set_fragment_shader_handle(p->cso, p->fs);
	cso_set_vertex_shader_handle(p->cso, p->vs);

	/* vertex element data */
	cso_set_vertex_elements(p->cso, 2, p->velem);

	util_draw_vertex_buffer(p->pipe, p->cso,
	                        p->vbuf, 0,
	                        PIPE_PRIM_TRIANGLES,
	                        3,  /* verts */
	                        2); /* attribs/vert */

        p->pipe->flush(p->pipe, NULL);

	debug_dump_surface_bmp(p->pipe, "result.bmp", p->framebuffer.cbufs[0]);
}
Exemple #4
0
/**
 * Prepare the renderer for polygon filling.
 */
VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
                                      VGboolean save_dsa)
{
   struct pipe_depth_stencil_alpha_state dsa;

   assert(renderer->state == RENDERER_STATE_INIT);

   if (save_dsa)
      cso_save_depth_stencil_alpha(renderer->cso);

   /* setup stencil ops */
   memset(&dsa, 0, sizeof(dsa));
   dsa.stencil[0].enabled = 1;
   dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].valuemask = ~0;
   dsa.stencil[0].writemask = ~0;
   dsa.depth = renderer->g3d.dsa.depth;
   cso_set_depth_stencil_alpha(renderer->cso, &dsa);

   renderer->state = RENDERER_STATE_POLYGON_FILL;

   return VG_TRUE;
}
Exemple #5
0
/**
 * 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_set_mvp(renderer, NULL);

   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;
}
Exemple #6
0
void
renderer_init_state(struct xa_context *r)
{
    struct pipe_depth_stencil_alpha_state dsa;
    struct pipe_rasterizer_state raster;
    unsigned i;

    /* set common initial clip state */
    memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
    cso_set_depth_stencil_alpha(r->cso, &dsa);

    /* XXX: move to renderer_init_state? */
    memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
    raster.gl_rasterization_rules = 1;
    raster.depth_clip = 1;
    cso_set_rasterizer(r->cso, &raster);

    /* vertex elements state */
    memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3);
    for (i = 0; i < 3; i++) {
	r->velems[i].src_offset = i * 4 * sizeof(float);
	r->velems[i].instance_divisor = 0;
	r->velems[i].vertex_buffer_index = 0;
	r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
}
static void
update_depth_stencil_alpha(struct st_context *st)
{
   struct pipe_depth_stencil_alpha_state *dsa = &st->state.depth_stencil;
   struct pipe_stencil_ref sr;
   struct gl_context *ctx = st->ctx;

   memset(dsa, 0, sizeof(*dsa));
   memset(&sr, 0, sizeof(sr));

   if (ctx->Depth.Test && ctx->DrawBuffer->Visual.depthBits > 0) {
      dsa->depth.enabled = 1;
      dsa->depth.writemask = ctx->Depth.Mask;
      dsa->depth.func = st_compare_func_to_pipe(ctx->Depth.Func);
   }

   if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
      dsa->stencil[0].enabled = 1;
      dsa->stencil[0].func = st_compare_func_to_pipe(ctx->Stencil.Function[0]);
      dsa->stencil[0].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[0]);
      dsa->stencil[0].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[0]);
      dsa->stencil[0].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[0]);
      dsa->stencil[0].valuemask = ctx->Stencil.ValueMask[0] & 0xff;
      dsa->stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
      sr.ref_value[0] = ctx->Stencil.Ref[0] & 0xff;

      if (ctx->Stencil._TestTwoSide) {
         const GLuint back = ctx->Stencil._BackFace;
         dsa->stencil[1].enabled = 1;
         dsa->stencil[1].func = st_compare_func_to_pipe(ctx->Stencil.Function[back]);
         dsa->stencil[1].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[back]);
         dsa->stencil[1].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[back]);
         dsa->stencil[1].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[back]);
         dsa->stencil[1].valuemask = ctx->Stencil.ValueMask[back] & 0xff;
         dsa->stencil[1].writemask = ctx->Stencil.WriteMask[back] & 0xff;
         sr.ref_value[1] = ctx->Stencil.Ref[back] & 0xff;
      }
      else {
         /* This should be unnecessary. Drivers must not expect this to
          * contain valid data, except the enabled bit
          */
         dsa->stencil[1] = dsa->stencil[0];
         dsa->stencil[1].enabled = 0;
         sr.ref_value[1] = sr.ref_value[0];
      }
   }

   if (ctx->Color.AlphaEnabled) {
      dsa->alpha.enabled = 1;
      dsa->alpha.func = st_compare_func_to_pipe(ctx->Color.AlphaFunc);
      dsa->alpha.ref_value = ctx->Color.AlphaRef;
   }

   cso_set_depth_stencil_alpha(st->cso_context, dsa);
   cso_set_stencil_ref(st->cso_context, &sr);
}
/** Setup misc state for the filter. */
void
pp_filter_misc_state(struct program *p)
{
   cso_set_blend(p->cso, &p->blend);
   cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
   cso_set_rasterizer(p->cso, &p->rasterizer);
   cso_set_viewport(p->cso, &p->viewport);

   cso_set_vertex_elements(p->cso, 2, p->velem);
}
Exemple #9
0
static void
renderer_init_state(struct xorg_renderer *r)
{
   struct pipe_depth_stencil_alpha_state dsa;
   struct pipe_rasterizer_state raster;

   /* set common initial clip state */
   memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
   cso_set_depth_stencil_alpha(r->cso, &dsa);


   /* XXX: move to renderer_init_state? */
   memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
   raster.gl_rasterization_rules = 1;
   cso_set_rasterizer(r->cso, &raster);

}
Exemple #10
0
/**
 * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
 * and scissoring states are relevant here.
 */
void renderer_validate(struct renderer *renderer,
                       VGbitfield dirty,
                       const struct st_framebuffer *stfb,
                       const struct vg_state *state)
{
   assert(renderer->state == RENDERER_STATE_INIT);

   dirty |= renderer->dirty;
   renderer->dirty = 0;

   if (dirty & FRAMEBUFFER_DIRTY) {
      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
      struct matrix *proj = &renderer->projection;

      memset(fb, 0, sizeof(struct pipe_framebuffer_state));
      fb->width  = stfb->width;
      fb->height = stfb->height;
      fb->nr_cbufs = 1;
      fb->cbufs[0] = stfb->strb->surface;
      fb->zsbuf = stfb->dsrb->surface;

      cso_set_framebuffer(renderer->cso, fb);
      vg_set_viewport(renderer, VEGA_Y0_BOTTOM);

      matrix_load_identity(proj);
      matrix_translate(proj, -1.0f, -1.0f);
      matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);

      /* we also got a new depth buffer */
      if (dirty & DEPTH_STENCIL_DIRTY) {
         renderer->pipe->clear(renderer->pipe,
               PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
      }
   }

   /* must be last because it renders to the depth buffer*/
   if (dirty & DEPTH_STENCIL_DIRTY) {
      update_clip_state(renderer, state);
      cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
   }

   if (dirty & BLEND_DIRTY)
      renderer_validate_blend(renderer, state, stfb->strb->format);
}
Exemple #11
0
void
nine_convert_dsa_state(struct cso_context *ctx, const DWORD *rs)
{
    struct pipe_depth_stencil_alpha_state dsa;

    memset(&dsa, 0, sizeof(dsa)); /* memcmp safety */

    if (rs[D3DRS_ZENABLE]) {
        dsa.depth.enabled = 1;
        dsa.depth.writemask = !!rs[D3DRS_ZWRITEENABLE];
        dsa.depth.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ZFUNC]);
    }

    if (rs[D3DRS_STENCILENABLE]) {
        dsa.stencil[0].enabled = 1;
        dsa.stencil[0].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_STENCILFUNC]);
        dsa.stencil[0].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILFAIL]);
        dsa.stencil[0].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILPASS]);
        dsa.stencil[0].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILZFAIL]);
        dsa.stencil[0].valuemask = rs[D3DRS_STENCILMASK];
        dsa.stencil[0].writemask = rs[D3DRS_STENCILWRITEMASK];

        if (rs[D3DRS_TWOSIDEDSTENCILMODE]) {
            dsa.stencil[1].enabled = 1;
            dsa.stencil[1].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_CCW_STENCILFUNC]);
            dsa.stencil[1].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILFAIL]);
            dsa.stencil[1].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILPASS]);
            dsa.stencil[1].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILZFAIL]);
            dsa.stencil[1].valuemask = dsa.stencil[0].valuemask;
            dsa.stencil[1].writemask = dsa.stencil[0].writemask;
        }
    }

    if (rs[D3DRS_ALPHATESTENABLE]) {
        dsa.alpha.enabled = 1;
        dsa.alpha.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ALPHAFUNC]);
        dsa.alpha.ref_value = (float)rs[D3DRS_ALPHAREF] / 255.0f;
    }

    cso_set_depth_stencil_alpha(ctx, &dsa);
}
Exemple #12
0
static void draw(struct program *p)
{
	const struct pipe_sampler_state *samplers[] = {&p->sampler};

	/* set the render target */
	cso_set_framebuffer(p->cso, &p->framebuffer);

	/* clear the render target */
	p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0);

	/* set misc state we care about */
	cso_set_blend(p->cso, &p->blend);
	cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
	cso_set_rasterizer(p->cso, &p->rasterizer);
	cso_set_viewport(p->cso, &p->viewport);

	/* sampler */
	cso_set_samplers(p->cso, PIPE_SHADER_FRAGMENT, 1, samplers);

	/* texture sampler view */
	cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->view);

	/* shaders */
	cso_set_fragment_shader_handle(p->cso, p->fs);
	cso_set_vertex_shader_handle(p->cso, p->vs);

	/* vertex element data */
	cso_set_vertex_elements(p->cso, 2, p->velem);

	util_draw_vertex_buffer(p->pipe, p->cso,
	                        p->vbuf, 0, 0,
	                        PIPE_PRIM_QUADS,
	                        4,  /* verts */
	                        2); /* attribs/vert */

        p->pipe->flush(p->pipe, NULL, 0);

	debug_dump_surface_bmp(p->pipe, "result.bmp", p->framebuffer.cbufs[0]);
}
Exemple #13
0
/**
 * Do glClear by drawing a quadrilateral.
 * The vertices of the quad will be computed from the
 * ctx->DrawBuffer->_X/Ymin/max fields.
 */
static void
clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
{
   struct st_context *st = st_context(ctx);
   struct cso_context *cso = st->cso_context;
   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;
   unsigned num_layers =
      util_framebuffer_get_num_layers(&st->state.framebuffer);

   /*
   printf("%s %s%s%s %f,%f %f,%f\n", __func__,
	  color ? "color, " : "",
	  depth ? "depth, " : "",
	  stencil ? "stencil" : "",
	  x0, y0,
	  x1, y1);
   */

   cso_save_state(cso, (CSO_BIT_BLEND |
                        CSO_BIT_STENCIL_REF |
                        CSO_BIT_DEPTH_STENCIL_ALPHA |
                        CSO_BIT_RASTERIZER |
                        CSO_BIT_SAMPLE_MASK |
                        CSO_BIT_MIN_SAMPLES |
                        CSO_BIT_VIEWPORT |
                        CSO_BIT_STREAM_OUTPUTS |
                        CSO_BIT_VERTEX_ELEMENTS |
                        CSO_BIT_AUX_VERTEX_BUFFER_SLOT |
                        CSO_BIT_PAUSE_QUERIES |
                        CSO_BITS_ALL_SHADERS));

   /* blend state: RGBA masking */
   {
      struct pipe_blend_state blend;
      memset(&blend, 0, sizeof(blend));
      if (clear_buffers & PIPE_CLEAR_COLOR) {
         int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
                           ctx->DrawBuffer->_NumColorDrawBuffers : 1;
         int i;

         blend.independent_blend_enable = num_buffers > 1;

         for (i = 0; i < num_buffers; i++) {
            if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
               continue;

            if (ctx->Color.ColorMask[i][0])
               blend.rt[i].colormask |= PIPE_MASK_R;
            if (ctx->Color.ColorMask[i][1])
               blend.rt[i].colormask |= PIPE_MASK_G;
            if (ctx->Color.ColorMask[i][2])
               blend.rt[i].colormask |= PIPE_MASK_B;
            if (ctx->Color.ColorMask[i][3])
               blend.rt[i].colormask |= PIPE_MASK_A;
         }

         if (ctx->Color.DitherFlag)
            blend.dither = 1;
      }
      cso_set_blend(cso, &blend);
   }

   /* depth_stencil state: always pass/set to ref value */
   {
      struct pipe_depth_stencil_alpha_state depth_stencil;
      memset(&depth_stencil, 0, sizeof(depth_stencil));
      if (clear_buffers & PIPE_CLEAR_DEPTH) {
         depth_stencil.depth.enabled = 1;
         depth_stencil.depth.writemask = 1;
         depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
      }

      if (clear_buffers & PIPE_CLEAR_STENCIL) {
         struct pipe_stencil_ref stencil_ref;
         memset(&stencil_ref, 0, sizeof(stencil_ref));
         depth_stencil.stencil[0].enabled = 1;
         depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
         depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].valuemask = 0xff;
         depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
         stencil_ref.ref_value[0] = ctx->Stencil.Clear;
         cso_set_stencil_ref(cso, &stencil_ref);
      }

      cso_set_depth_stencil_alpha(cso, &depth_stencil);
   }

   cso_set_vertex_elements(cso, 2, st->util_velems);
   cso_set_stream_outputs(cso, 0, NULL, NULL);
   cso_set_sample_mask(cso, ~0);
   cso_set_min_samples(cso, 1);
   cso_set_rasterizer(cso, &st->clear.raster);

   /* viewport state: viewport matching window dims */
   cso_set_viewport_dims(st->cso_context, fb_width, fb_height,
                         st_fb_orientation(fb) == Y_0_TOP);

   set_fragment_shader(st);
   cso_set_tessctrl_shader_handle(cso, NULL);
   cso_set_tesseval_shader_handle(cso, NULL);

   if (num_layers > 1)
      set_vertex_shader_layered(st);
   else
      set_vertex_shader(st);

   /* draw quad matching scissor rect.
    *
    * Note: if we're only clearing depth/stencil we still setup vertices
    * with color, but they'll be ignored.
    *
    * We can't translate the clear color to the colorbuffer format,
    * because different colorbuffers may have different formats.
    */
   if (!st_draw_quad(st, x0, y0, x1, y1,
                     ctx->Depth.Clear * 2.0f - 1.0f,
                     0.0f, 0.0f, 0.0f, 0.0f,
                     (const float *) &ctx->Color.ClearColor.f,
                     num_layers)) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear");
   }

   /* Restore pipe state */
   cso_restore_state(cso);
}
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
{
   struct array *polys = polyarray->array;
   struct pipe_depth_stencil_alpha_state dsa;
   struct pipe_stencil_ref sr;
   struct pipe_blend_state blend;
   VGfloat min_x = polyarray->min_x;
   VGfloat min_y = polyarray->min_y;
   VGfloat max_x = polyarray->max_x;
   VGfloat max_y = polyarray->max_y;
   VGint i;


#if DEBUG_POLYGON
   debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
                __FUNCTION__,
                min_x, min_y, max_x, max_y);
#endif

   set_blend_for_fill(&blend);

   memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
   memset(&sr, 0, sizeof(struct pipe_stencil_ref));
   /* only need a fixed 0. Rely on default or move it out at least? */
   cso_set_stencil_ref(ctx->cso_context, &sr);

   cso_save_blend(ctx->cso_context);
   cso_save_depth_stencil_alpha(ctx->cso_context);

   dsa.stencil[0].enabled = 1;
   if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
      dsa.stencil[0].writemask = 1;
      dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
      dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
      dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
      dsa.stencil[0].valuemask = ~0;

      cso_set_blend(ctx->cso_context, &blend);
      cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
      for (i = 0; i < polys->num_elements; ++i) {
         struct polygon *poly = (((struct polygon**)polys->data)[i]);
         draw_polygon(ctx, poly);
      }
   } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
      struct pipe_screen *screen = ctx->pipe->screen;

      if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
         /* front */
         dsa.stencil[0].writemask = ~0;
         dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
         dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
         dsa.stencil[0].valuemask = ~0;

         /* back */
         dsa.stencil[1].enabled = 1;
         dsa.stencil[1].writemask = ~0;
         dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
         dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
         dsa.stencil[1].valuemask = ~0;

         cso_set_blend(ctx->cso_context, &blend);
         cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
         for (i = 0; i < polys->num_elements; ++i) {
            struct polygon *poly = (((struct polygon**)polys->data)[i]);
            draw_polygon(ctx, poly);
         }
      } else {
         struct pipe_rasterizer_state raster;

         memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));

         cso_save_rasterizer(ctx->cso_context);
         dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
         dsa.stencil[0].valuemask = ~0;

         raster.cull_face = PIPE_FACE_BACK;
         dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;

         cso_set_blend(ctx->cso_context, &blend);
         cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
         cso_set_rasterizer(ctx->cso_context, &raster);
         for (i = 0; i < polys->num_elements; ++i) {
            struct polygon *poly = (((struct polygon**)polys->data)[i]);
            draw_polygon(ctx, poly);
         }

         raster.cull_face = PIPE_FACE_FRONT;
         dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
         dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
         cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
         cso_set_rasterizer(ctx->cso_context, &raster);
         for (i = 0; i < polys->num_elements; ++i) {
            struct polygon *poly = (((struct polygon**)polys->data)[i]);
            draw_polygon(ctx, poly);
         }

         cso_restore_rasterizer(ctx->cso_context);
      }
   }

   /* restore color writes */
   cso_restore_blend(ctx->cso_context);
   /* setup stencil ops */
   dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
   dsa.stencil[1].enabled = 0;
   memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
          sizeof(struct pipe_depth_state));
   cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);

   /* render the quad to propagate the rendering from stencil */
   renderer_draw_quad(ctx->renderer, min_x, min_y,
                      max_x, max_y, 0.0f/*depth should be disabled*/);

   cso_restore_depth_stencil_alpha(ctx->cso_context);
}
void vg_validate_state(struct vg_context *ctx)
{
   vg_manager_validate_framebuffer(ctx);

   if ((ctx->state.dirty & BLEND_DIRTY)) {
      struct pipe_blend_state *blend = &ctx->state.g3d.blend;
      memset(blend, 0, sizeof(struct pipe_blend_state));
      blend->rt[0].blend_enable = 1;
      blend->rt[0].colormask = PIPE_MASK_RGBA;

      switch (ctx->state.vg.blend_mode) {
      case VG_BLEND_SRC:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].blend_enable = 0;
         break;
      case VG_BLEND_SRC_OVER:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
         break;
      case VG_BLEND_DST_OVER:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_INV_DST_ALPHA;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_DST_ALPHA;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
         break;
      case VG_BLEND_SRC_IN:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_DST_ALPHA;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
         break;
      case VG_BLEND_DST_IN:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
         break;
      case VG_BLEND_MULTIPLY:
      case VG_BLEND_SCREEN:
      case VG_BLEND_DARKEN:
      case VG_BLEND_LIGHTEN:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
         blend->rt[0].blend_enable = 0;
         break;
      case VG_BLEND_ADDITIVE:
         blend->rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
         blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
         break;
      default:
         assert(!"not implemented blend mode");
      }
      cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
   }
   if ((ctx->state.dirty & RASTERIZER_DIRTY)) {
      struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer;
      memset(raster, 0, sizeof(struct pipe_rasterizer_state));
      raster->gl_rasterization_rules = 1;
      cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer);
   }
   if ((ctx->state.dirty & VIEWPORT_DIRTY)) {
      struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
      const VGint param_bytes = 8 * sizeof(VGfloat);
      VGfloat vs_consts[8] = {
         2.f/fb->width, 2.f/fb->height, 1, 1,
         -1, -1, 0, 0
      };
      struct pipe_resource **cbuf = &ctx->vs_const_buffer;

      vg_set_viewport(ctx, VEGA_Y0_BOTTOM);

      pipe_resource_reference(cbuf, NULL);
      *cbuf = pipe_buffer_create(ctx->pipe->screen, 
				 PIPE_BIND_CONSTANT_BUFFER,
				 param_bytes);

      if (*cbuf) {
         st_no_flush_pipe_buffer_write(ctx, *cbuf,
                                       0, param_bytes, vs_consts);
      }
      ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf);
   }
   if ((ctx->state.dirty & VS_DIRTY)) {
      cso_set_vertex_shader_handle(ctx->cso_context,
                                   vg_plain_vs(ctx));
   }

   /* must be last because it renders to the depth buffer*/
   if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) {
      update_clip_state(ctx);
      cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa);
   }

   shader_set_masking(ctx->shader, ctx->state.vg.masking);
   shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);

   ctx->state.dirty = NONE_DIRTY;
}
static void update_clip_state(struct vg_context *ctx)
{
   struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
   struct vg_state *state =  &ctx->state.vg;

   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 */
      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);
      }

      cso_restore_blend(ctx->cso_context);
      cso_restore_fragment_shader(ctx->cso_context);

      dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
      dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
      dsa->depth.func = PIPE_FUNC_GEQUAL;
   }
}
Exemple #17
0
struct st_context *
st_context_create(struct st_device *st_dev) 
{
   struct st_context *st_ctx;
   
   st_ctx = CALLOC_STRUCT(st_context);
   if(!st_ctx)
      return NULL;
   
   st_device_reference(&st_ctx->st_dev, st_dev);
   
   st_ctx->real_pipe = st_dev->st_ws->context_create(st_dev->real_screen);
   if(!st_ctx->real_pipe) {
      st_context_destroy(st_ctx);
      return NULL;
   }
   
   st_ctx->pipe = trace_context_create(st_dev->screen, st_ctx->real_pipe);
   if(!st_ctx->pipe) {
      st_context_destroy(st_ctx);
      return NULL;
   }

   st_ctx->cso = cso_create_context(st_ctx->pipe);
   if(!st_ctx->cso) {
      st_context_destroy(st_ctx);
      return NULL;
   }
   
   /* disabled blending/masking */
   {
      struct pipe_blend_state blend;
      memset(&blend, 0, sizeof(blend));
      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
      blend.colormask = PIPE_MASK_RGBA;
      cso_set_blend(st_ctx->cso, &blend);
   }

   /* no-op depth/stencil/alpha */
   {
      struct pipe_depth_stencil_alpha_state depthstencil;
      memset(&depthstencil, 0, sizeof(depthstencil));
      cso_set_depth_stencil_alpha(st_ctx->cso, &depthstencil);
   }

   /* rasterizer */
   {
      struct pipe_rasterizer_state rasterizer;
      memset(&rasterizer, 0, sizeof(rasterizer));
      rasterizer.front_winding = PIPE_WINDING_CW;
      rasterizer.cull_mode = PIPE_WINDING_NONE;
      cso_set_rasterizer(st_ctx->cso, &rasterizer);
   }

   /* clip */
   {
      struct pipe_clip_state clip;
      memset(&clip, 0, sizeof(clip));
      st_ctx->pipe->set_clip_state(st_ctx->pipe, &clip);
   }

   /* identity viewport */
   {
      struct pipe_viewport_state viewport;
      viewport.scale[0] = 1.0;
      viewport.scale[1] = 1.0;
      viewport.scale[2] = 1.0;
      viewport.scale[3] = 1.0;
      viewport.translate[0] = 0.0;
      viewport.translate[1] = 0.0;
      viewport.translate[2] = 0.0;
      viewport.translate[3] = 0.0;
      cso_set_viewport(st_ctx->cso, &viewport);
   }

   /* samplers */
   {
      struct pipe_sampler_state sampler;
      unsigned i;
      memset(&sampler, 0, sizeof(sampler));
      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
      sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
      sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
      sampler.normalized_coords = 1;
      for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
         cso_single_sampler(st_ctx->cso, i, &sampler);
      cso_single_sampler_done(st_ctx->cso);
   }

   /* default textures */
   {
      struct pipe_screen *screen = st_dev->screen;
      struct pipe_texture templat;
      struct pipe_transfer *transfer;
      unsigned i;

      memset( &templat, 0, sizeof( templat ) );
      templat.target = PIPE_TEXTURE_2D;
      templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
      templat.block.size = 4;
      templat.block.width = 1;
      templat.block.height = 1;
      templat.width[0] = 1;
      templat.height[0] = 1;
      templat.depth[0] = 1;
      templat.last_level = 0;
   
      st_ctx->default_texture = screen->texture_create( screen, &templat );
      if(st_ctx->default_texture) {
         transfer = screen->get_tex_transfer(screen,
                                             st_ctx->default_texture,
                                             0, 0, 0,
                                             PIPE_TRANSFER_WRITE,
                                             0, 0,
                                             st_ctx->default_texture->width[0],
                                             st_ctx->default_texture->height[0]);
         if (transfer) {
            uint32_t *map;
            map = (uint32_t *) screen->transfer_map(screen, transfer);
            if(map) {
               *map = 0x00000000;
               screen->transfer_unmap(screen, transfer);
            }
            screen->tex_transfer_destroy(transfer);
         }
      }
   
      for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
         pipe_texture_reference(&st_ctx->sampler_textures[i], st_ctx->default_texture);
      
      cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->sampler_textures);
   }
   
   /* vertex shader */
   {
      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
                                      TGSI_SEMANTIC_GENERIC };
      const uint semantic_indexes[] = { 0, 0 };
      st_ctx->vs = util_make_vertex_passthrough_shader(st_ctx->pipe, 
                                                       2, 
                                                       semantic_names,
                                                       semantic_indexes);
      cso_set_vertex_shader_handle(st_ctx->cso, st_ctx->vs);
   }

   /* fragment shader */
   {
      st_ctx->fs = util_make_fragment_passthrough_shader(st_ctx->pipe);
      cso_set_fragment_shader_handle(st_ctx->cso, st_ctx->fs);
   }

   return st_ctx;
}
Exemple #18
0
/**
 * Do glClear by drawing a quadrilateral.
 * The vertices of the quad will be computed from the
 * ctx->DrawBuffer->_X/Ymin/max fields.
 */
static void
clear_with_quad(struct gl_context *ctx,
                GLboolean color, GLboolean depth, GLboolean stencil)
{
   struct st_context *st = st_context(ctx);
   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;
   union pipe_color_union clearColor;

   /*
   printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
	  color ? "color, " : "",
	  depth ? "depth, " : "",
	  stencil ? "stencil" : "",
	  x0, y0,
	  x1, y1);
   */

   cso_save_blend(st->cso_context);
   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_fragment_shader(st->cso_context);
   cso_save_stream_outputs(st->cso_context);
   cso_save_vertex_shader(st->cso_context);
   cso_save_geometry_shader(st->cso_context);
   cso_save_vertex_elements(st->cso_context);
   cso_save_vertex_buffers(st->cso_context);

   /* blend state: RGBA masking */
   {
      struct pipe_blend_state blend;
      memset(&blend, 0, sizeof(blend));
      blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
      blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
      if (color) {
         if (ctx->Color.ColorMask[0][0])
            blend.rt[0].colormask |= PIPE_MASK_R;
         if (ctx->Color.ColorMask[0][1])
            blend.rt[0].colormask |= PIPE_MASK_G;
         if (ctx->Color.ColorMask[0][2])
            blend.rt[0].colormask |= PIPE_MASK_B;
         if (ctx->Color.ColorMask[0][3])
            blend.rt[0].colormask |= PIPE_MASK_A;
         if (st->ctx->Color.DitherFlag)
            blend.dither = 1;
      }
      cso_set_blend(st->cso_context, &blend);
   }

   /* depth_stencil state: always pass/set to ref value */
   {
      struct pipe_depth_stencil_alpha_state depth_stencil;
      memset(&depth_stencil, 0, sizeof(depth_stencil));
      if (depth) {
         depth_stencil.depth.enabled = 1;
         depth_stencil.depth.writemask = 1;
         depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
      }

      if (stencil) {
         struct pipe_stencil_ref stencil_ref;
         memset(&stencil_ref, 0, sizeof(stencil_ref));
         depth_stencil.stencil[0].enabled = 1;
         depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
         depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].valuemask = 0xff;
         depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
         stencil_ref.ref_value[0] = ctx->Stencil.Clear;
         cso_set_stencil_ref(st->cso_context, &stencil_ref);
      }

      cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
   }

   cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);

   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);
   }

   set_fragment_shader(st);
   set_vertex_shader(st);
   cso_set_geometry_shader_handle(st->cso_context, NULL);

   if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
      st_translate_color(ctx->Color.ClearColor.f,
                               ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
                               clearColor.f);
   }

   /* draw quad matching scissor rect */
   draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, &clearColor);

   /* Restore pipe state */
   cso_restore_blend(st->cso_context);
   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_fragment_shader(st->cso_context);
   cso_restore_vertex_shader(st->cso_context);
   cso_restore_geometry_shader(st->cso_context);
   cso_restore_vertex_elements(st->cso_context);
   cso_restore_vertex_buffers(st->cso_context);
   cso_restore_stream_outputs(st->cso_context);
}
Exemple #19
0
/**
 * Copy pixel block from src sampler view to dst surface.
 *
 * The sampler view's first_level field indicates the source
 * mipmap level to use.
 *
 * The sampler view's first_layer indicate the layer to use, but for
 * cube maps it must point to the first face.  Face is passed in src_face.
 *
 * The main advantage over util_blit_pixels is that it allows to specify
 * swizzles in pipe_sampler_view::swizzle_?.
 *
 * But there is no control over blitting Z and/or stencil.
 */
void
util_blit_pixels_tex(struct blit_state *ctx,
                     struct pipe_sampler_view *src_sampler_view,
                     int srcX0, int srcY0,
                     int srcX1, int srcY1,
                     unsigned src_face,
                     struct pipe_surface *dst,
                     int dstX0, int dstY0,
                     int dstX1, int dstY1,
                     float z, enum pipe_tex_filter filter,
                     boolean src_xrbias)
{
   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
   struct pipe_framebuffer_state fb;
   float s0, t0, s1, t1;
   unsigned offset;
   struct pipe_resource *tex = src_sampler_view->texture;

   assert(filter == PIPE_TEX_FILTER_NEAREST ||
          filter == PIPE_TEX_FILTER_LINEAR);

   assert(tex);
   assert(tex->width0 != 0);
   assert(tex->height0 != 0);

   s0 = (float) srcX0;
   s1 = (float) srcX1;
   t0 = (float) srcY0;
   t1 = (float) srcY1;

   if (normalized) {
      /* normalize according to the mipmap level's size */
      int level = src_sampler_view->u.tex.first_level;
      float w = (float) u_minify(tex->width0, level);
      float h = (float) u_minify(tex->height0, level);
      s0 /= w;
      s1 /= w;
      t0 /= h;
      t1 /= h;
   }

   assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
                                                 PIPE_TEXTURE_2D,
                                                 dst->texture->nr_samples,
                                                 PIPE_BIND_RENDER_TARGET));

   /* save state (restored below) */
   cso_save_state(ctx->cso, (CSO_BIT_BLEND |
                             CSO_BIT_DEPTH_STENCIL_ALPHA |
                             CSO_BIT_RASTERIZER |
                             CSO_BIT_SAMPLE_MASK |
                             CSO_BIT_MIN_SAMPLES |
                             CSO_BIT_FRAGMENT_SAMPLERS |
                             CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
                             CSO_BIT_STREAM_OUTPUTS |
                             CSO_BIT_VIEWPORT |
                             CSO_BIT_FRAMEBUFFER |
                             CSO_BIT_PAUSE_QUERIES |
                             CSO_BIT_FRAGMENT_SHADER |
                             CSO_BIT_VERTEX_SHADER |
                             CSO_BIT_TESSCTRL_SHADER |
                             CSO_BIT_TESSEVAL_SHADER |
                             CSO_BIT_GEOMETRY_SHADER |
                             CSO_BIT_VERTEX_ELEMENTS |
                             CSO_BIT_AUX_VERTEX_BUFFER_SLOT));

   /* set misc state we care about */
   cso_set_blend(ctx->cso, &ctx->blend_write_color);
   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
   cso_set_sample_mask(ctx->cso, ~0);
   cso_set_min_samples(ctx->cso, 1);
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);

   /* sampler */
   ctx->sampler.normalized_coords = normalized;
   ctx->sampler.min_img_filter = filter;
   ctx->sampler.mag_img_filter = filter;
   {
      const struct pipe_sampler_state *samplers[] = {&ctx->sampler};
      cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 1, samplers);
   }

   /* 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.translate[0] = 0.5f * dst->width;
   ctx->viewport.translate[1] = 0.5f * dst->height;
   ctx->viewport.translate[2] = 0.5f;
   cso_set_viewport(ctx->cso, &ctx->viewport);

   /* texture */
   cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);

   /* shaders */
   set_fragment_shader(ctx, src_sampler_view->format,
                       src_xrbias,
                       src_sampler_view->texture->target);
   set_vertex_shader(ctx);
   cso_set_tessctrl_shader_handle(ctx->cso, NULL);
   cso_set_tesseval_shader_handle(ctx->cso, NULL);
   cso_set_geometry_shader_handle(ctx->cso, NULL);

   /* drawing dest */
   memset(&fb, 0, sizeof(fb));
   fb.width = dst->width;
   fb.height = dst->height;
   fb.nr_cbufs = 1;
   fb.cbufs[0] = dst;
   cso_set_framebuffer(ctx->cso, &fb);

   /* draw quad */
   offset = setup_vertex_data_tex(ctx,
                                  src_sampler_view->texture->target,
                                  src_face,
                                  (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);

   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
                           cso_get_aux_vertex_buffer_slot(ctx->cso),
                           offset,
                           PIPE_PRIM_TRIANGLE_FAN,
                           4,  /* verts */
                           2); /* attribs/vert */

   /* restore state we changed */
   cso_restore_state(ctx->cso);
}
Exemple #20
0
static void
draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                   GLsizei width, GLsizei height,
                   GLfloat zoomX, GLfloat zoomY,
                   struct pipe_sampler_view **sv,
                   int num_sampler_view,
                   void *driver_vp,
                   void *driver_fp,
                   const GLfloat *color,
                   GLboolean invertTex,
                   GLboolean write_depth, GLboolean write_stencil)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct cso_context *cso = st->cso_context;
   GLfloat x0, y0, x1, y1;
   GLsizei maxSize;
   boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT;

   /* limit checks */
   /* XXX if DrawPixels image is larger than max texture size, break
    * it up into chunks.
    */
   maxSize = 1 << (pipe->screen->get_param(pipe->screen,
                                        PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
   assert(width <= maxSize);
   assert(height <= maxSize);

   cso_save_rasterizer(cso);
   cso_save_viewport(cso);
   cso_save_samplers(cso);
   cso_save_fragment_sampler_views(cso);
   cso_save_fragment_shader(cso);
   cso_save_vertex_shader(cso);
   cso_save_vertex_elements(cso);
   cso_save_vertex_buffers(cso);
   if (write_stencil) {
      cso_save_depth_stencil_alpha(cso);
      cso_save_blend(cso);
   }

   /* rasterizer state: just scissor */
   {
      struct pipe_rasterizer_state rasterizer;
      memset(&rasterizer, 0, sizeof(rasterizer));
      rasterizer.clamp_fragment_color = ctx->Color._ClampFragmentColor;
      rasterizer.gl_rasterization_rules = 1;
      rasterizer.scissor = ctx->Scissor.Enabled;
      cso_set_rasterizer(cso, &rasterizer);
   }

   if (write_stencil) {
      /* Stencil writing bypasses the normal fragment pipeline to
       * disable color writing and set stencil test to always pass.
       */
      struct pipe_depth_stencil_alpha_state dsa;
      struct pipe_blend_state blend;

      /* depth/stencil */
      memset(&dsa, 0, sizeof(dsa));
      dsa.stencil[0].enabled = 1;
      dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
      dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
      if (write_depth) {
         /* writing depth+stencil: depth test always passes */
         dsa.depth.enabled = 1;
         dsa.depth.writemask = ctx->Depth.Mask;
         dsa.depth.func = PIPE_FUNC_ALWAYS;
      }
      cso_set_depth_stencil_alpha(cso, &dsa);

      /* blend (colormask) */
      memset(&blend, 0, sizeof(blend));
      cso_set_blend(cso, &blend);
   }

   /* fragment shader state: TEX lookup program */
   cso_set_fragment_shader_handle(cso, driver_fp);

   /* vertex shader state: position + texcoord pass-through */
   cso_set_vertex_shader_handle(cso, driver_vp);


   /* texture sampling state: */
   {
      struct pipe_sampler_state sampler;
      memset(&sampler, 0, sizeof(sampler));
      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
      sampler.normalized_coords = normalized;

      cso_single_sampler(cso, 0, &sampler);
      if (num_sampler_view > 1) {
         cso_single_sampler(cso, 1, &sampler);
      }
      cso_single_sampler_done(cso);
   }

   /* viewport state: viewport matching window dims */
   {
      const float w = (float) ctx->DrawBuffer->Width;
      const float h = (float) ctx->DrawBuffer->Height;
      struct pipe_viewport_state vp;
      vp.scale[0] =  0.5f * w;
      vp.scale[1] = -0.5f * h;
      vp.scale[2] = 0.5f;
      vp.scale[3] = 1.0f;
      vp.translate[0] = 0.5f * w;
      vp.translate[1] = 0.5f * h;
      vp.translate[2] = 0.5f;
      vp.translate[3] = 0.0f;
      cso_set_viewport(cso, &vp);
   }

   cso_set_vertex_elements(cso, 3, st->velems_util_draw);

   /* texture state: */
   cso_set_fragment_sampler_views(cso, num_sampler_view, sv);

   /* Compute Gallium window coords (y=0=top) with pixel zoom.
    * Recall that these coords are transformed by the current
    * vertex shader and viewport transformation.
    */
   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
      y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY);
      invertTex = !invertTex;
   }

   x0 = (GLfloat) x;
   x1 = x + width * ctx->Pixel.ZoomX;
   y0 = (GLfloat) y;
   y1 = y + height * ctx->Pixel.ZoomY;

   /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
   z = z * 2.0 - 1.0;

   draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
             normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width,
             normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height);

   /* restore state */
   cso_restore_rasterizer(cso);
   cso_restore_viewport(cso);
   cso_restore_samplers(cso);
   cso_restore_fragment_sampler_views(cso);
   cso_restore_fragment_shader(cso);
   cso_restore_vertex_shader(cso);
   cso_restore_vertex_elements(cso);
   cso_restore_vertex_buffers(cso);
   if (write_stencil) {
      cso_restore_depth_stencil_alpha(cso);
      cso_restore_blend(cso);
   }
}
Exemple #21
0
/**
 * Do glClear by drawing a quadrilateral.
 * The vertices of the quad will be computed from the
 * ctx->DrawBuffer->_X/Ymin/max fields.
 */
static void
clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
{
   struct st_context *st = st_context(ctx);
   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;
   unsigned num_layers =
      util_framebuffer_get_num_layers(&st->state.framebuffer);

   /*
   printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
	  color ? "color, " : "",
	  depth ? "depth, " : "",
	  stencil ? "stencil" : "",
	  x0, y0,
	  x1, y1);
   */

   cso_save_blend(st->cso_context);
   cso_save_stencil_ref(st->cso_context);
   cso_save_depth_stencil_alpha(st->cso_context);
   cso_save_rasterizer(st->cso_context);
   cso_save_sample_mask(st->cso_context);
   cso_save_viewport(st->cso_context);
   cso_save_fragment_shader(st->cso_context);
   cso_save_stream_outputs(st->cso_context);
   cso_save_vertex_shader(st->cso_context);
   cso_save_geometry_shader(st->cso_context);
   cso_save_vertex_elements(st->cso_context);
   cso_save_aux_vertex_buffer_slot(st->cso_context);

   /* blend state: RGBA masking */
   {
      struct pipe_blend_state blend;
      memset(&blend, 0, sizeof(blend));
      if (clear_buffers & PIPE_CLEAR_COLOR) {
         int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
                           ctx->DrawBuffer->_NumColorDrawBuffers : 1;
         int i;

         blend.independent_blend_enable = num_buffers > 1;

         for (i = 0; i < num_buffers; i++) {
            if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
               continue;

            if (ctx->Color.ColorMask[i][0])
               blend.rt[i].colormask |= PIPE_MASK_R;
            if (ctx->Color.ColorMask[i][1])
               blend.rt[i].colormask |= PIPE_MASK_G;
            if (ctx->Color.ColorMask[i][2])
               blend.rt[i].colormask |= PIPE_MASK_B;
            if (ctx->Color.ColorMask[i][3])
               blend.rt[i].colormask |= PIPE_MASK_A;
         }

         if (st->ctx->Color.DitherFlag)
            blend.dither = 1;
      }
      cso_set_blend(st->cso_context, &blend);
   }

   /* depth_stencil state: always pass/set to ref value */
   {
      struct pipe_depth_stencil_alpha_state depth_stencil;
      memset(&depth_stencil, 0, sizeof(depth_stencil));
      if (clear_buffers & PIPE_CLEAR_DEPTH) {
         depth_stencil.depth.enabled = 1;
         depth_stencil.depth.writemask = 1;
         depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
      }

      if (clear_buffers & PIPE_CLEAR_STENCIL) {
         struct pipe_stencil_ref stencil_ref;
         memset(&stencil_ref, 0, sizeof(stencil_ref));
         depth_stencil.stencil[0].enabled = 1;
         depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
         depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].valuemask = 0xff;
         depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
         stencil_ref.ref_value[0] = ctx->Stencil.Clear;
         cso_set_stencil_ref(st->cso_context, &stencil_ref);
      }

      cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
   }

   cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
   cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
   cso_set_sample_mask(st->cso_context, ~0);
   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);
   }

   set_fragment_shader(st);
   cso_set_geometry_shader_handle(st->cso_context, NULL);

   if (num_layers > 1)
      set_vertex_shader_layered(st);
   else
      set_vertex_shader(st);

   /* We can't translate the clear color to the colorbuffer format,
    * because different colorbuffers may have different formats.
    */

   /* draw quad matching scissor rect */
   draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, num_layers,
             (union pipe_color_union*)&ctx->Color.ClearColor);

   /* Restore pipe state */
   cso_restore_blend(st->cso_context);
   cso_restore_stencil_ref(st->cso_context);
   cso_restore_depth_stencil_alpha(st->cso_context);
   cso_restore_rasterizer(st->cso_context);
   cso_restore_sample_mask(st->cso_context);
   cso_restore_viewport(st->cso_context);
   cso_restore_fragment_shader(st->cso_context);
   cso_restore_vertex_shader(st->cso_context);
   cso_restore_geometry_shader(st->cso_context);
   cso_restore_vertex_elements(st->cso_context);
   cso_restore_aux_vertex_buffer_slot(st->cso_context);
   cso_restore_stream_outputs(st->cso_context);
}
Exemple #22
0
/**
 * Prepare the renderer for polygon silhouette rendering.
 */
VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
                                         struct pipe_vertex_element *velem,
                                         VGFillRule rule,
                                         VGboolean restore_dsa)
{
   struct pipe_depth_stencil_alpha_state *dsa;
   VGboolean manual_two_sides;

   assert(renderer->state == RENDERER_STATE_INIT);

   cso_save_vertex_elements(renderer->cso);
   cso_save_blend(renderer->cso);
   cso_save_depth_stencil_alpha(renderer->cso);

   cso_set_vertex_elements(renderer->cso, 1, velem);

   /* disable color writes */
   renderer_set_blend(renderer, 0);

   manual_two_sides = VG_FALSE;
   dsa = &renderer->u.polygon_stencil.dsa;
   memset(dsa, 0, sizeof(*dsa));
   if (rule == VG_EVEN_ODD) {
      dsa->stencil[0].enabled = 1;
      dsa->stencil[0].writemask = 1;
      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
      dsa->stencil[0].valuemask = ~0;
   }
   else {
      assert(rule == VG_NON_ZERO);

      /* front face */
      dsa->stencil[0].enabled = 1;
      dsa->stencil[0].writemask = ~0;
      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
      dsa->stencil[0].valuemask = ~0;

      if (renderer->pipe->screen->get_param(renderer->pipe->screen,
                                            PIPE_CAP_TWO_SIDED_STENCIL)) {
         /* back face */
         dsa->stencil[1] = dsa->stencil[0];
         dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
      }
      else {
         manual_two_sides = VG_TRUE;
      }
   }
   cso_set_depth_stencil_alpha(renderer->cso, dsa);

   if (manual_two_sides)
      cso_save_rasterizer(renderer->cso);

   renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
   renderer->u.polygon_stencil.restore_dsa = restore_dsa;
   renderer->state = RENDERER_STATE_POLYGON_STENCIL;

   return VG_TRUE;
}
Exemple #23
0
/**
 * Copy pixel block from src surface to dst surface.
 * Overlapping regions are acceptable.
 * Flipping and stretching are supported.
 * \param filter  one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
 * \param writemask  controls which channels in the dest surface are sourced
 *                   from the src surface.  Disabled channels are sourced
 *                   from (0,0,0,1).
 */
void
util_blit_pixels(struct blit_state *ctx,
                 struct pipe_resource *src_tex,
                 unsigned src_level,
                 int srcX0, int srcY0,
                 int srcX1, int srcY1,
                 int srcZ0,
                 struct pipe_surface *dst,
                 int dstX0, int dstY0,
                 int dstX1, int dstY1,
                 float z, uint filter,
                 uint writemask, uint zs_writemask)
{
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format src_format, dst_format;
   struct pipe_sampler_view *sampler_view = NULL;
   struct pipe_sampler_view sv_templ;
   struct pipe_surface *dst_surface;
   struct pipe_framebuffer_state fb;
   const int srcW = abs(srcX1 - srcX0);
   const int srcH = abs(srcY1 - srcY0);
   unsigned offset;
   boolean overlap;
   float s0, t0, s1, t1;
   boolean normalized;
   boolean is_stencil, is_depth, blit_depth, blit_stencil;
   const struct util_format_description *src_desc =
         util_format_description(src_tex->format);

   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
          filter == PIPE_TEX_MIPFILTER_LINEAR);

   assert(src_level <= src_tex->last_level);

   /* do the regions overlap? */
   overlap = src_tex == dst->texture &&
             dst->u.tex.level == src_level &&
             dst->u.tex.first_layer == srcZ0 &&
      regions_overlap(srcX0, srcY0, srcX1, srcY1,
                      dstX0, dstY0, dstX1, dstY1);

   src_format = util_format_linear(src_tex->format);
   dst_format = util_format_linear(dst->texture->format);

   /* See whether we will blit depth or stencil. */
   is_depth = util_format_has_depth(src_desc);
   is_stencil = util_format_has_stencil(src_desc);

   blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
   blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);

   assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
          (!writemask && (blit_depth || blit_stencil)));

   /*
    * Check for simple case:  no format conversion, no flipping, no stretching,
    * no overlapping, same number of samples.
    * Filter mode should not matter since there's no stretching.
    */
   if (formats_compatible(src_format, dst_format) &&
       src_tex->nr_samples == dst->texture->nr_samples &&
       is_stencil == blit_stencil &&
       is_depth == blit_depth &&
       srcX0 < srcX1 &&
       dstX0 < dstX1 &&
       srcY0 < srcY1 &&
       dstY0 < dstY1 &&
       (dstX1 - dstX0) == (srcX1 - srcX0) &&
       (dstY1 - dstY0) == (srcY1 - srcY0) &&
       !overlap) {
      struct pipe_box src_box;
      src_box.x = srcX0;
      src_box.y = srcY0;
      src_box.z = srcZ0;
      src_box.width = srcW;
      src_box.height = srcH;
      src_box.depth = 1;
      pipe->resource_copy_region(pipe,
                                 dst->texture, dst->u.tex.level,
                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
                                 src_tex, src_level,
                                 &src_box);
      return;
   }

   /* XXX Reading multisample textures is unimplemented. */
   assert(src_tex->nr_samples <= 1);
   if (src_tex->nr_samples > 1) {
      return;
   }

   /* It's a mistake to call this function with a stencil format and
    * without shader stencil export. We don't do software fallbacks here.
    * Ignore stencil and only copy depth.
    */
   if (blit_stencil && !ctx->has_stencil_export) {
      blit_stencil = FALSE;

      if (!blit_depth)
         return;
   }

   if (dst_format == dst->format) {
      dst_surface = dst;
   } else {
      struct pipe_surface templ = *dst;
      templ.format = dst_format;
      dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
   }

   /* Create a temporary texture when src and dest alias.
    */
   if (src_tex == dst_surface->texture &&
       dst_surface->u.tex.level == src_level &&
       dst_surface->u.tex.first_layer == srcZ0) {
      /* Make a temporary texture which contains a copy of the source pixels.
       * Then we'll sample from the temporary texture.
       */
      struct pipe_resource texTemp;
      struct pipe_resource *tex;
      struct pipe_sampler_view sv_templ;
      struct pipe_box src_box;
      const int srcLeft = MIN2(srcX0, srcX1);
      const int srcTop = MIN2(srcY0, srcY1);

      if (srcLeft != srcX0) {
         /* left-right flip */
         int tmp = dstX0;
         dstX0 = dstX1;
         dstX1 = tmp;
      }

      if (srcTop != srcY0) {
         /* up-down flip */
         int tmp = dstY0;
         dstY0 = dstY1;
         dstY1 = tmp;
      }

      /* create temp texture */
      memset(&texTemp, 0, sizeof(texTemp));
      texTemp.target = ctx->internal_target;
      texTemp.format = src_format;
      texTemp.last_level = 0;
      texTemp.width0 = srcW;
      texTemp.height0 = srcH;
      texTemp.depth0 = 1;
      texTemp.array_size = 1;
      texTemp.bind = PIPE_BIND_SAMPLER_VIEW;

      tex = screen->resource_create(screen, &texTemp);
      if (!tex)
         return;

      src_box.x = srcLeft;
      src_box.y = srcTop;
      src_box.z = srcZ0;
      src_box.width = srcW;
      src_box.height = srcH;
      src_box.depth = 1;
      /* load temp texture */
      pipe->resource_copy_region(pipe,
                                 tex, 0, 0, 0, 0,  /* dest */
                                 src_tex, src_level, &src_box);

      normalized = tex->target != PIPE_TEXTURE_RECT;
      if(normalized) {
         s0 = 0.0f;
         s1 = 1.0f;
         t0 = 0.0f;
         t1 = 1.0f;
      }
      else {
         s0 = 0;
         s1 = srcW;
         t0 = 0;
         t1 = srcH;
      }

      u_sampler_view_default_template(&sv_templ, tex, tex->format);
      if (!blit_depth && blit_stencil) {
         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
         sv_templ.format = util_format_stencil_only(tex->format);
         assert(sv_templ.format != PIPE_FORMAT_NONE);
      }
      sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);

      if (!sampler_view) {
         pipe_resource_reference(&tex, NULL);
         return;
      }
      pipe_resource_reference(&tex, NULL);
   }
   else {
      /* Directly sample from the source resource/texture */
      u_sampler_view_default_template(&sv_templ, src_tex, src_format);
      if (!blit_depth && blit_stencil) {
         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
         sv_templ.format = util_format_stencil_only(src_format);
         assert(sv_templ.format != PIPE_FORMAT_NONE);
      }
      sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);

      if (!sampler_view) {
         return;
      }

      s0 = srcX0;
      s1 = srcX1;
      t0 = srcY0;
      t1 = srcY1;
      normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
      if(normalized)
      {
         s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
         s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
         t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
         t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
      }
   }

   assert(screen->is_format_supported(screen, sampler_view->format,
                     ctx->internal_target, sampler_view->texture->nr_samples,
                     PIPE_BIND_SAMPLER_VIEW));
   assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
                     dst_surface->texture->nr_samples,
                     is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
                                              PIPE_BIND_RENDER_TARGET));

   /* save state (restored below) */
   cso_save_blend(ctx->cso);
   cso_save_depth_stencil_alpha(ctx->cso);
   cso_save_rasterizer(ctx->cso);
   cso_save_sample_mask(ctx->cso);
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_stream_outputs(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_geometry_shader(ctx->cso);
   cso_save_vertex_elements(ctx->cso);
   cso_save_aux_vertex_buffer_slot(ctx->cso);
   cso_save_render_condition(ctx->cso);

   /* set misc state we care about */
   if (writemask)
      cso_set_blend(ctx->cso, &ctx->blend_write_color);
   else
      cso_set_blend(ctx->cso, &ctx->blend_keep_color);

   cso_set_sample_mask(ctx->cso, ~0);
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
   cso_set_render_condition(ctx->cso, NULL, 0);

   /* default sampler state */
   ctx->sampler.normalized_coords = normalized;
   ctx->sampler.min_img_filter = filter;
   ctx->sampler.mag_img_filter = filter;
   ctx->sampler.min_lod = src_level;
   ctx->sampler.max_lod = src_level;

   /* Depth stencil state, fragment shader and sampler setup depending on what
    * we blit.
    */
   if (blit_depth && blit_stencil) {
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
      /* don't filter stencil */
      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);

      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
      set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
   }
   else if (blit_depth) {
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
      set_depth_fragment_shader(ctx, sampler_view->texture->target);
   }
   else if (blit_stencil) {
      /* don't filter stencil */
      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);

      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
      set_stencil_fragment_shader(ctx, sampler_view->texture->target);
   }
   else { /* color */
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
      set_fragment_shader(ctx, writemask, sampler_view->texture->target);
   }
   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);

   /* textures */
   if (blit_depth && blit_stencil) {
      /* Setup two samplers, one for depth and the other one for stencil. */
      struct pipe_sampler_view templ;
      struct pipe_sampler_view *views[2];

      templ = *sampler_view;
      templ.format = util_format_stencil_only(templ.format);
      assert(templ.format != PIPE_FORMAT_NONE);

      views[0] = sampler_view;
      views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);

      pipe_sampler_view_reference(&views[1], NULL);
   }
   else {
      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
   }

   /* viewport */
   ctx->viewport.scale[0] = 0.5f * dst_surface->width;
   ctx->viewport.scale[1] = 0.5f * dst_surface->height;
   ctx->viewport.scale[2] = 0.5f;
   ctx->viewport.scale[3] = 1.0f;
   ctx->viewport.translate[0] = 0.5f * dst_surface->width;
   ctx->viewport.translate[1] = 0.5f * dst_surface->height;
   ctx->viewport.translate[2] = 0.5f;
   ctx->viewport.translate[3] = 0.0f;
   cso_set_viewport(ctx->cso, &ctx->viewport);

   set_vertex_shader(ctx);
   cso_set_geometry_shader_handle(ctx->cso, NULL);

   /* drawing dest */
   memset(&fb, 0, sizeof(fb));
   fb.width = dst_surface->width;
   fb.height = dst_surface->height;
   if (blit_depth || blit_stencil) {
      fb.zsbuf = dst_surface;
   } else {
      fb.nr_cbufs = 1;
      fb.cbufs[0] = dst_surface;
   }
   cso_set_framebuffer(ctx->cso, &fb);

   /* draw quad */
   offset = setup_vertex_data_tex(ctx,
                                  (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
                                  (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
                                  (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
                                  (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
                                  s0, t0,
                                  s1, t1,
                                  z);

   if (ctx->vbuf) {
      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
                              cso_get_aux_vertex_buffer_slot(ctx->cso),
                              offset,
                              PIPE_PRIM_TRIANGLE_FAN,
                              4,  /* verts */
                              2); /* attribs/vert */
   }

   /* restore state we changed */
   cso_restore_blend(ctx->cso);
   cso_restore_depth_stencil_alpha(ctx->cso);
   cso_restore_rasterizer(ctx->cso);
   cso_restore_sample_mask(ctx->cso);
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_viewport(ctx->cso);
   cso_restore_framebuffer(ctx->cso);
   cso_restore_fragment_shader(ctx->cso);
   cso_restore_vertex_shader(ctx->cso);
   cso_restore_geometry_shader(ctx->cso);
   cso_restore_vertex_elements(ctx->cso);
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
   cso_restore_stream_outputs(ctx->cso);
   cso_restore_render_condition(ctx->cso);

   pipe_sampler_view_reference(&sampler_view, NULL);
   if (dst_surface != dst)
      pipe_surface_reference(&dst_surface, NULL);
}
/**
 * Copy pixel block from src sampler view to dst surface.
 *
 * The sampler view's first_level field indicates the source
 * mipmap level to use.
 *
 * The sampler view's first_layer indicate the layer to use, but for
 * cube maps it must point to the first face.  Face is passed in src_face.
 *
 * The main advantage over util_blit_pixels is that it allows to specify swizzles in
 * pipe_sampler_view::swizzle_?.
 *
 * But there is no control over blitting Z and/or stencil.
 */
void
util_blit_pixels_tex(struct blit_state *ctx,
                     struct pipe_sampler_view *src_sampler_view,
                     int srcX0, int srcY0,
                     int srcX1, int srcY1,
                     unsigned src_face,
                     struct pipe_surface *dst,
                     int dstX0, int dstY0,
                     int dstX1, int dstY1,
                     float z, uint filter)
{
   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
   struct pipe_framebuffer_state fb;
   float s0, t0, s1, t1;
   unsigned offset;
   struct pipe_resource *tex = src_sampler_view->texture;

   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
          filter == PIPE_TEX_MIPFILTER_LINEAR);

   assert(tex);
   assert(tex->width0 != 0);
   assert(tex->height0 != 0);

   s0 = (float) srcX0;
   s1 = (float) srcX1;
   t0 = (float) srcY0;
   t1 = (float) srcY1;

   if(normalized)
   {
      /* normalize according to the mipmap level's size */
      int level = src_sampler_view->u.tex.first_level;
      float w = (float) u_minify(tex->width0, level);
      float h = (float) u_minify(tex->height0, level);
      s0 /= w;
      s1 /= w;
      t0 /= h;
      t1 /= h;
   }

   assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
                                                 PIPE_TEXTURE_2D,
                                                 dst->texture->nr_samples,
                                                 PIPE_BIND_RENDER_TARGET));

   /* save state (restored below) */
   cso_save_blend(ctx->cso);
   cso_save_depth_stencil_alpha(ctx->cso);
   cso_save_rasterizer(ctx->cso);
   cso_save_sample_mask(ctx->cso);
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_stream_outputs(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_geometry_shader(ctx->cso);
   cso_save_vertex_elements(ctx->cso);
   cso_save_aux_vertex_buffer_slot(ctx->cso);

   /* set misc state we care about */
   cso_set_blend(ctx->cso, &ctx->blend_write_color);
   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
   cso_set_sample_mask(ctx->cso, ~0);
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);

   /* sampler */
   ctx->sampler.normalized_coords = normalized;
   ctx->sampler.min_img_filter = filter;
   ctx->sampler.mag_img_filter = filter;
   cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);

   /* 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_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);

   /* shaders */
   set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
                       src_sampler_view->texture->target);
   set_vertex_shader(ctx);
   cso_set_geometry_shader_handle(ctx->cso, NULL);

   /* drawing dest */
   memset(&fb, 0, sizeof(fb));
   fb.width = dst->width;
   fb.height = dst->height;
   fb.nr_cbufs = 1;
   fb.cbufs[0] = dst;
   cso_set_framebuffer(ctx->cso, &fb);

   /* draw quad */
   offset = setup_vertex_data_tex(ctx,
                                  src_sampler_view->texture->target,
                                  src_face,
                                  (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);

   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
                           cso_get_aux_vertex_buffer_slot(ctx->cso),
                           offset,
                           PIPE_PRIM_TRIANGLE_FAN,
                           4,  /* verts */
                           2); /* attribs/vert */

   /* restore state we changed */
   cso_restore_blend(ctx->cso);
   cso_restore_depth_stencil_alpha(ctx->cso);
   cso_restore_rasterizer(ctx->cso);
   cso_restore_sample_mask(ctx->cso);
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_viewport(ctx->cso);
   cso_restore_framebuffer(ctx->cso);
   cso_restore_fragment_shader(ctx->cso);
   cso_restore_vertex_shader(ctx->cso);
   cso_restore_geometry_shader(ctx->cso);
   cso_restore_vertex_elements(ctx->cso);
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
   cso_restore_stream_outputs(ctx->cso);
}
Exemple #25
0
/**
 * Do glClear by drawing a quadrilateral.
 * The vertices of the quad will be computed from the
 * ctx->DrawBuffer->_X/Ymin/max fields.
 */
static void
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;
   }

   /*
   printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
	  color ? "color, " : "",
	  depth ? "depth, " : "",
	  stencil ? "stencil" : "",
	  x0, y0,
	  x1, y1);
   */

   cso_save_blend(st->cso_context);
   cso_save_depth_stencil_alpha(st->cso_context);
   cso_save_rasterizer(st->cso_context);
   cso_save_fragment_shader(st->cso_context);
   cso_save_vertex_shader(st->cso_context);

   /* blend state: RGBA masking */
   {
      struct pipe_blend_state blend;
      memset(&blend, 0, sizeof(blend));
      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
      if (color) {
         if (ctx->Color.ColorMask[0])
            blend.colormask |= PIPE_MASK_R;
         if (ctx->Color.ColorMask[1])
            blend.colormask |= PIPE_MASK_G;
         if (ctx->Color.ColorMask[2])
            blend.colormask |= PIPE_MASK_B;
         if (ctx->Color.ColorMask[3])
            blend.colormask |= PIPE_MASK_A;
         if (st->ctx->Color.DitherFlag)
            blend.dither = 1;
      }
      cso_set_blend(st->cso_context, &blend);
   }

   /* depth_stencil state: always pass/set to ref value */
   {
      struct pipe_depth_stencil_alpha_state depth_stencil;
      memset(&depth_stencil, 0, sizeof(depth_stencil));
      if (depth) {
         depth_stencil.depth.enabled = 1;
         depth_stencil.depth.writemask = 1;
         depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
      }

      if (stencil) {
         depth_stencil.stencil[0].enabled = 1;
         depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
         depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
         depth_stencil.stencil[0].ref_value = ctx->Stencil.Clear;
         depth_stencil.stencil[0].valuemask = 0xff;
         depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
      }

      cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
   }

   cso_set_rasterizer(st->cso_context, &st->clear.raster);

   cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
   cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);

   /* draw quad matching scissor rect (XXX verify coord round-off) */
   draw_quad(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);

   /* Restore pipe state */
   cso_restore_blend(st->cso_context);
   cso_restore_depth_stencil_alpha(st->cso_context);
   cso_restore_rasterizer(st->cso_context);
   cso_restore_fragment_shader(st->cso_context);
   cso_restore_vertex_shader(st->cso_context);
}
Exemple #26
0
/** Run function of the MLAA filter. */
static void
pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
                   struct pipe_resource *out, unsigned int n, bool iscolor)
{

   struct pp_program *p = ppq->p;

   struct pipe_depth_stencil_alpha_state mstencil;
   struct pipe_sampler_view v_tmp, *arr[3];

   unsigned int w = 0;
   unsigned int h = 0;

   const struct pipe_stencil_ref ref = { {1} };

   /* Insufficient initialization checks. */
   assert(p);
   assert(ppq);
   assert(ppq->constbuf);
   assert(ppq->areamaptex);
   assert(ppq->inner_tmp);
   assert(ppq->shaders[n]);

   w = p->framebuffer.width;
   h = p->framebuffer.height;

   memset(&mstencil, 0, sizeof(mstencil));

   cso_set_stencil_ref(p->cso, &ref);

   /* Init the pixel size constant */
   if (dimensions[0] != p->framebuffer.width ||
       dimensions[1] != p->framebuffer.height) {
      constants[0] = 1.0f / p->framebuffer.width;
      constants[1] = 1.0f / p->framebuffer.height;

      up_consts(ppq);
      dimensions[0] = p->framebuffer.width;
      dimensions[1] = p->framebuffer.height;
   }

   cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_VERTEX,
                                    0, ppq->constbuf);
   cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_FRAGMENT,
                                    0, ppq->constbuf);

   mstencil.stencil[0].enabled = 1;
   mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0;
   mstencil.stencil[0].func = PIPE_FUNC_ALWAYS;
   mstencil.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
   mstencil.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
   mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;

   p->framebuffer.zsbuf = ppq->stencils;

   /* First pass: depth edge detection */
   if (iscolor)
      pp_filter_setup_in(p, in);
   else
      pp_filter_setup_in(p, ppq->depth);

   pp_filter_setup_out(p, ppq->inner_tmp[0]);

   pp_filter_set_fb(p);
   pp_filter_misc_state(p);
   cso_set_depth_stencil_alpha(p->cso, &mstencil);
   p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR0,
                  &p->clear_color, 0, 0);

   cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 0, &p->sampler_point);
   cso_single_sampler_done(p->cso, PIPE_SHADER_FRAGMENT);
   cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->view);

   cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]);    /* offsetvs */
   cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][2]);

   pp_filter_draw(p);
   pp_filter_end_pass(p);


   /* Second pass: blend weights */
   /* Sampler order: areamap, edgesmap, edgesmapL (reversed, thx compiler) */
   mstencil.stencil[0].func = PIPE_FUNC_EQUAL;
   mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP;
   cso_set_depth_stencil_alpha(p->cso, &mstencil);

   pp_filter_setup_in(p, ppq->areamaptex);
   pp_filter_setup_out(p, ppq->inner_tmp[1]);

   u_sampler_view_default_template(&v_tmp, ppq->inner_tmp[0],
                                   ppq->inner_tmp[0]->format);
   arr[1] = arr[2] = p->pipe->create_sampler_view(p->pipe,
                                                  ppq->inner_tmp[0], &v_tmp);

   pp_filter_set_clear_fb(p);

   cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 0, &p->sampler_point);
   cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->sampler_point);
   cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 2, &p->sampler);
   cso_single_sampler_done(p->cso, PIPE_SHADER_FRAGMENT);

   arr[0] = p->view;
   cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 3, arr);

   cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][0]);    /* passvs */
   cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][3]);

   pp_filter_draw(p);
   pp_filter_end_pass(p);
   pipe_sampler_view_reference(&arr[1], NULL);


   /* Third pass: smoothed edges */
   /* Sampler order: colormap, blendmap (wtf compiler) */
   pp_filter_setup_in(p, ppq->inner_tmp[1]);
   pp_filter_setup_out(p, out);

   pp_filter_set_fb(p);

   /* Blit the input to the output */
   pp_blit(p->pipe, in, 0, 0,
           w, h, 0, p->framebuffer.cbufs[0],
           0, 0, w, h);

   u_sampler_view_default_template(&v_tmp, in, in->format);
   arr[0] = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);

   cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 0, &p->sampler_point);
   cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->sampler_point);
   cso_single_sampler_done(p->cso, PIPE_SHADER_FRAGMENT);

   arr[1] = p->view;
   cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 2, arr);

   cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]);    /* offsetvs */
   cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][4]);

   p->blend.rt[0].blend_enable = 1;
   cso_set_blend(p->cso, &p->blend);

   pp_filter_draw(p);
   pp_filter_end_pass(p);
   pipe_sampler_view_reference(&arr[0], NULL);

   p->blend.rt[0].blend_enable = 0;
   p->framebuffer.zsbuf = NULL;
}
Exemple #27
0
/**
 * Generate mipmap images.  It's assumed all needed texture memory is
 * already allocated.
 *
 * \param psv  the sampler view to the texture to generate mipmap levels for
 * \param face  which cube face to generate mipmaps for (0 for non-cube maps)
 * \param baseLevel  the first mipmap level to use as a src
 * \param lastLevel  the last mipmap level to generate
 * \param filter  the minification filter used to generate mipmap levels with
 * \param filter  one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
 */
void
util_gen_mipmap(struct gen_mipmap_state *ctx,
                struct pipe_sampler_view *psv,
                uint face, uint baseLevel, uint lastLevel, uint filter)
{
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_framebuffer_state fb;
   struct pipe_resource *pt = psv->texture;
   uint dstLevel;
   uint offset;
   uint type;
   boolean is_depth = util_format_is_depth_or_stencil(psv->format);

   /* The texture object should have room for the levels which we're
    * about to generate.
    */
   assert(lastLevel <= pt->last_level);

   /* If this fails, why are we here? */
   assert(lastLevel > baseLevel);

   assert(filter == PIPE_TEX_FILTER_LINEAR ||
          filter == PIPE_TEX_FILTER_NEAREST);

   type = util_pipe_tex_to_tgsi_tex(pt->target, 1);

   /* check if we can render in the texture's format */
   if (!screen->is_format_supported(screen, psv->format, pt->target,
                                    pt->nr_samples,
                                    is_depth ? PIPE_BIND_DEPTH_STENCIL :
                                               PIPE_BIND_RENDER_TARGET)) {
      /* The caller should check if the format is renderable. */
      assert(0);
      return;
   }

   /* save state (restored below) */
   cso_save_blend(ctx->cso);
   cso_save_depth_stencil_alpha(ctx->cso);
   cso_save_rasterizer(ctx->cso);
   cso_save_sample_mask(ctx->cso);
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_stream_outputs(ctx->cso);
   cso_save_framebuffer(ctx->cso);
   cso_save_fragment_shader(ctx->cso);
   cso_save_vertex_shader(ctx->cso);
   cso_save_geometry_shader(ctx->cso);
   cso_save_viewport(ctx->cso);
   cso_save_vertex_elements(ctx->cso);
   cso_save_aux_vertex_buffer_slot(ctx->cso);
   cso_save_render_condition(ctx->cso);

   /* bind our state */
   cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color :
                                      &ctx->blend_write_color);
   cso_set_depth_stencil_alpha(ctx->cso, is_depth ? &ctx->dsa_write_depth :
                                                    &ctx->dsa_keep_depth);
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
   cso_set_sample_mask(ctx->cso, ~0);
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
   cso_set_render_condition(ctx->cso, NULL, FALSE, 0);

   set_fragment_shader(ctx, type, is_depth);
   set_vertex_shader(ctx);
   cso_set_geometry_shader_handle(ctx->cso, NULL);

   /* init framebuffer state */
   memset(&fb, 0, sizeof(fb));

   /* set min/mag to same filter for faster sw speed */
   ctx->sampler.mag_img_filter = filter;
   ctx->sampler.min_img_filter = filter;

   for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
      const uint srcLevel = dstLevel - 1;
      struct pipe_viewport_state vp;
      unsigned nr_layers, layer, i;
      float rcoord = 0.0f;

      if (pt->target == PIPE_TEXTURE_3D)
         nr_layers = u_minify(pt->depth0, dstLevel);
      else if (pt->target == PIPE_TEXTURE_2D_ARRAY ||
               pt->target == PIPE_TEXTURE_1D_ARRAY ||
               pt->target == PIPE_TEXTURE_CUBE_ARRAY)
	 nr_layers = pt->array_size;
      else
         nr_layers = 1;

      for (i = 0; i < nr_layers; i++) {
         struct pipe_surface *surf, surf_templ;
         if (pt->target == PIPE_TEXTURE_3D) {
            /* in theory with geom shaders and driver with full layer support
               could do that in one go. */
            layer = i;
            /* XXX hmm really? */
            rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
         } else if (pt->target == PIPE_TEXTURE_2D_ARRAY ||
                    pt->target == PIPE_TEXTURE_1D_ARRAY) {
	    layer = i;
	    rcoord = (float)layer;
         } else if (pt->target == PIPE_TEXTURE_CUBE_ARRAY) {
            layer = i;
            face = layer % 6;
            rcoord = layer / 6;
	 } else
            layer = face;

         u_surface_default_template(&surf_templ, pt);
         surf_templ.u.tex.level = dstLevel;
         surf_templ.u.tex.first_layer = layer;
         surf_templ.u.tex.last_layer = layer;
         surf = pipe->create_surface(pipe, pt, &surf_templ);

         /*
          * Setup framebuffer / dest surface
          */
         if (is_depth) {
            fb.nr_cbufs = 0;
            fb.zsbuf = surf;
         }
         else {
            fb.nr_cbufs = 1;
            fb.cbufs[0] = surf;
         }
         fb.width = u_minify(pt->width0, dstLevel);
         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
          * we grab texels from the right mipmap level.  But some hardware
          * has trouble with min clamping so we also set the lod_bias to
          * try to work around that.
          */
         ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
         ctx->sampler.lod_bias = (float) srcLevel;
         cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
         cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);

         cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &psv);

         /* quad coords in clip coords */
         offset = set_vertex_data(ctx,
                                  pt->target,
                                  face,
                                  rcoord);

         util_draw_vertex_buffer(ctx->pipe,
                                 ctx->cso,
                                 ctx->vbuf,
                                 cso_get_aux_vertex_buffer_slot(ctx->cso),
                                 offset,
                                 PIPE_PRIM_TRIANGLE_FAN,
                                 4,  /* verts */
                                 2); /* attribs/vert */

         /* need to signal that the texture has changed _after_ rendering to it */
         pipe_surface_reference( &surf, NULL );
      }
   }

   /* restore state we changed */
   cso_restore_blend(ctx->cso);
   cso_restore_depth_stencil_alpha(ctx->cso);
   cso_restore_rasterizer(ctx->cso);
   cso_restore_sample_mask(ctx->cso);
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_framebuffer(ctx->cso);
   cso_restore_fragment_shader(ctx->cso);
   cso_restore_vertex_shader(ctx->cso);
   cso_restore_geometry_shader(ctx->cso);
   cso_restore_viewport(ctx->cso);
   cso_restore_vertex_elements(ctx->cso);
   cso_restore_stream_outputs(ctx->cso);
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
   cso_restore_render_condition(ctx->cso);
}