Beispiel #1
0
/**
 * Restore the state which was saved by cso_save_state().
 */
void
cso_restore_state(struct cso_context *cso)
{
    unsigned state_mask = cso->saved_state;

    assert(state_mask);

    if (state_mask & CSO_BIT_AUX_VERTEX_BUFFER_SLOT)
        cso_restore_aux_vertex_buffer_slot(cso);
    if (state_mask & CSO_BIT_BLEND)
        cso_restore_blend(cso);
    if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA)
        cso_restore_depth_stencil_alpha(cso);
    if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS)
        cso_restore_fragment_samplers(cso);
    if (state_mask & CSO_BIT_FRAGMENT_SAMPLER_VIEWS)
        cso_restore_fragment_sampler_views(cso);
    if (state_mask & CSO_BIT_FRAGMENT_SHADER)
        cso_restore_fragment_shader(cso);
    if (state_mask & CSO_BIT_FRAMEBUFFER)
        cso_restore_framebuffer(cso);
    if (state_mask & CSO_BIT_GEOMETRY_SHADER)
        cso_restore_geometry_shader(cso);
    if (state_mask & CSO_BIT_MIN_SAMPLES)
        cso_restore_min_samples(cso);
    if (state_mask & CSO_BIT_RASTERIZER)
        cso_restore_rasterizer(cso);
    if (state_mask & CSO_BIT_RENDER_CONDITION)
        cso_restore_render_condition(cso);
    if (state_mask & CSO_BIT_SAMPLE_MASK)
        cso_restore_sample_mask(cso);
    if (state_mask & CSO_BIT_STENCIL_REF)
        cso_restore_stencil_ref(cso);
    if (state_mask & CSO_BIT_STREAM_OUTPUTS)
        cso_restore_stream_outputs(cso);
    if (state_mask & CSO_BIT_TESSCTRL_SHADER)
        cso_restore_tessctrl_shader(cso);
    if (state_mask & CSO_BIT_TESSEVAL_SHADER)
        cso_restore_tesseval_shader(cso);
    if (state_mask & CSO_BIT_VERTEX_ELEMENTS)
        cso_restore_vertex_elements(cso);
    if (state_mask & CSO_BIT_VERTEX_SHADER)
        cso_restore_vertex_shader(cso);
    if (state_mask & CSO_BIT_VIEWPORT)
        cso_restore_viewport(cso);
    if (state_mask & CSO_BIT_PAUSE_QUERIES)
        cso->pipe->set_active_query_state(cso->pipe, true);

    cso->saved_state = 0;
}
Beispiel #2
0
/**
 * End polygon silhouette rendering.
 */
void renderer_polygon_stencil_end(struct renderer *renderer)
{
   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);

   if (renderer->u.polygon_stencil.manual_two_sides)
      cso_restore_rasterizer(renderer->cso);

   cso_restore_vertex_elements(renderer->cso);

   /* restore color writes */
   cso_restore_blend(renderer->cso);

   if (renderer->u.polygon_stencil.restore_dsa)
      cso_restore_depth_stencil_alpha(renderer->cso);

   renderer->state = RENDERER_STATE_INIT;
}
/**
 * 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);
}
Beispiel #4
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);
}
Beispiel #5
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);
}
Beispiel #6
0
/**
 * Render a glBitmap by drawing a textured quad
 */
static void
draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                 GLsizei width, GLsizei height,
                 struct pipe_sampler_view *sv,
                 const GLfloat *color)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct cso_context *cso = st->cso_context;
   struct st_fp_variant *fpv;
   struct st_fp_variant_key key;
   GLuint maxSize;
   GLuint offset;
   struct pipe_resource *vbuf = NULL;

   memset(&key, 0, sizeof(key));
   key.st = st;
   key.bitmap = GL_TRUE;
   key.clamp_color = st->clamp_frag_color_in_shader &&
                     st->ctx->Color._ClampFragmentColor;

   fpv = st_get_fp_variant(st, st->fp, &key);

   /* As an optimization, Mesa's fragment programs will sometimes get the
    * primary color from a statevar/constant rather than a varying variable.
    * when that's the case, we need to ensure that we use the 'color'
    * parameter and not the current attribute color (which may have changed
    * through glRasterPos and state validation.
    * So, we force the proper color here.  Not elegant, but it works.
    */
   {
      GLfloat colorSave[4];
      COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
      COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
      st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
      COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
   }


   /* limit checks */
   /* XXX if the bitmap is larger than the 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 <= (GLsizei)maxSize);
   assert(height <= (GLsizei)maxSize);

   cso_save_rasterizer(cso);
   cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
   cso_save_viewport(cso);
   cso_save_fragment_shader(cso);
   cso_save_stream_outputs(cso);
   cso_save_vertex_shader(cso);
   cso_save_tessctrl_shader(cso);
   cso_save_tesseval_shader(cso);
   cso_save_geometry_shader(cso);
   cso_save_vertex_elements(cso);
   cso_save_aux_vertex_buffer_slot(cso);

   /* rasterizer state: just scissor */
   st->bitmap.rasterizer.scissor = ctx->Scissor.EnableFlags & 1;
   cso_set_rasterizer(cso, &st->bitmap.rasterizer);

   /* fragment shader state: TEX lookup program */
   cso_set_fragment_shader_handle(cso, fpv->driver_shader);

   /* vertex shader state: position + texcoord pass-through */
   cso_set_vertex_shader_handle(cso, st->bitmap.vs);

   /* disable other shaders */
   cso_set_tessctrl_shader_handle(cso, NULL);
   cso_set_tesseval_shader_handle(cso, NULL);
   cso_set_geometry_shader_handle(cso, NULL);

   /* user samplers, plus our bitmap sampler */
   {
      struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
      uint num = MAX2(fpv->bitmap_sampler + 1,
                      st->state.num_samplers[PIPE_SHADER_FRAGMENT]);
      uint i;
      for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++) {
         samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i];
      }
      samplers[fpv->bitmap_sampler] =
         &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
      cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num,
                       (const struct pipe_sampler_state **) samplers);
   }

   /* user textures, plus the bitmap texture */
   {
      struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
      uint num = MAX2(fpv->bitmap_sampler + 1,
                      st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
      memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT],
             sizeof(sampler_views));
      sampler_views[fpv->bitmap_sampler] = sv;
      cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num, sampler_views);
   }

   /* viewport state: viewport matching window dims */
   {
      const GLboolean invert = st->state.fb_orientation == Y_0_TOP;
      const GLfloat width = (GLfloat)st->state.framebuffer.width;
      const GLfloat height = (GLfloat)st->state.framebuffer.height;
      struct pipe_viewport_state vp;
      vp.scale[0] =  0.5f * width;
      vp.scale[1] = height * (invert ? -0.5f : 0.5f);
      vp.scale[2] = 0.5f;
      vp.translate[0] = 0.5f * width;
      vp.translate[1] = 0.5f * height;
      vp.translate[2] = 0.5f;
      cso_set_viewport(cso, &vp);
   }

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

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

   /* draw textured quad */
   setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT,
			    x, y, width, height, z, color, &vbuf, &offset);

   if (vbuf) {
      util_draw_vertex_buffer(pipe, st->cso_context, vbuf,
                              cso_get_aux_vertex_buffer_slot(st->cso_context),
                              offset,
                              PIPE_PRIM_TRIANGLE_FAN,
                              4,  /* verts */
                              3); /* attribs/vert */
   }

   /* restore state */
   cso_restore_rasterizer(cso);
   cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
   cso_restore_viewport(cso);
   cso_restore_fragment_shader(cso);
   cso_restore_vertex_shader(cso);
   cso_restore_tessctrl_shader(cso);
   cso_restore_tesseval_shader(cso);
   cso_restore_geometry_shader(cso);
   cso_restore_vertex_elements(cso);
   cso_restore_aux_vertex_buffer_slot(cso);
   cso_restore_stream_outputs(cso);

   pipe_resource_reference(&vbuf, NULL);
}
Beispiel #7
0
/**
*	Main run function of the PP queue. Called on swapbuffers/flush.
*
*	Runs all requested filters in order and handles shuffling the temp
*	buffers in between.
*/
void
pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
       struct pipe_resource *out, struct pipe_resource *indepth)
{
   struct pipe_resource *refin = NULL, *refout = NULL;
   unsigned int i;
   struct cso_context *cso = ppq->p->cso;

   if (in->width0 != ppq->p->framebuffer.width ||
       in->height0 != ppq->p->framebuffer.height) {
      pp_debug("Resizing the temp pp buffers\n");
      pp_free_fbos(ppq);
      pp_init_fbos(ppq, in->width0, in->height0);
   }

   if (in == out && ppq->n_filters == 1) {
      /* Make a copy of in to tmp[0] in this case. */
      unsigned int w = ppq->p->framebuffer.width;
      unsigned int h = ppq->p->framebuffer.height;

      util_blit_pixels(ppq->p->blitctx, in, 0, 0, 0,
                       w, h, 0, ppq->tmps[0],
                       0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST,
                       TGSI_WRITEMASK_XYZW, 0);

      in = ppq->tmp[0];
   }

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

   /* set default state */
   cso_set_sample_mask(cso, ~0);
   cso_set_stream_outputs(cso, 0, NULL, 0);
   cso_set_geometry_shader_handle(cso, NULL);
   cso_set_render_condition(cso, NULL, 0);

   // Kept only for this frame.
   pipe_resource_reference(&ppq->depth, indepth);
   pipe_resource_reference(&refin, in);
   pipe_resource_reference(&refout, out);

   switch (ppq->n_filters) {
   case 1:                     /* No temp buf */
      ppq->pp_queue[0] (ppq, in, out, 0);
      break;
   case 2:                     /* One temp buf */

      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
      ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);

      break;
   default:                    /* Two temp bufs */
      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);

      for (i = 1; i < (ppq->n_filters - 1); i++) {
         if (i % 2 == 0)
            ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);

         else
            ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
      }

      if (i % 2 == 0)
         ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);

      else
         ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);

      break;
   }

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

   pipe_resource_reference(&ppq->depth, NULL);
   pipe_resource_reference(&refin, NULL);
   pipe_resource_reference(&refout, NULL);
}
Beispiel #8
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);
   }
}
Beispiel #9
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);
}
Beispiel #10
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);
}
Beispiel #11
0
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);
}
Beispiel #12
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);
}
Beispiel #13
0
static void
draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
                   GLsizei width, GLsizei height,
                   GLfloat zoomX, GLfloat zoomY,
                   struct pipe_texture *pt,
                   struct st_vertex_program *stvp,
                   struct st_fragment_program *stfp,
                   const GLfloat *color,
                   GLboolean invertTex)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = ctx->st->pipe;
   struct cso_context *cso = ctx->st->cso_context;
   GLfloat x0, y0, x1, y1;
   GLsizei maxSize;

   /* 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_sampler_textures(cso);
   cso_save_fragment_shader(cso);
   cso_save_vertex_shader(cso);

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

   /* fragment shader state: TEX lookup program */
   cso_set_fragment_shader_handle(cso, stfp->driver_shader);

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


   /* 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 = 1;

      cso_single_sampler(cso, 0, &sampler);
      if (st->pixel_xfer.pixelmap_enabled) {
         cso_single_sampler(cso, 1, &sampler);
      }
      cso_single_sampler_done(cso);
   }

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

   /* texture state: */
   if (st->pixel_xfer.pixelmap_enabled) {
      struct pipe_texture *textures[2];
      textures[0] = pt;
      textures[1] = st->pixel_xfer.pixelmap_texture;
      pipe->set_sampler_textures(pipe, 2, textures);
   }
   else {
      pipe->set_sampler_textures(pipe, 1, &pt);
   }

   /* Compute window coords (y=0=bottom) with pixel zoom.
    * Recall that these coords are transformed by the current
    * vertex shader and viewport transformation.
    */
   x0 = (GLfloat) x;
   x1 = x + width * ctx->Pixel.ZoomX;
   y0 = (GLfloat) y;
   y1 = y + height * ctx->Pixel.ZoomY;

   draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);

   /* restore state */
   cso_restore_rasterizer(cso);
   cso_restore_viewport(cso);
   cso_restore_samplers(cso);
   cso_restore_sampler_textures(cso);
   cso_restore_fragment_shader(cso);
   cso_restore_vertex_shader(cso);
}