예제 #1
0
static void
update_tcp( struct st_context *st )
{
   struct st_tessctrl_program *sttcp;

   if (!st->ctx->TessCtrlProgram._Current) {
      cso_set_tessctrl_shader_handle(st->cso_context, NULL);
      st_reference_tesscprog(st, &st->tcp, NULL);
      return;
   }

   sttcp = st_tessctrl_program(st->ctx->TessCtrlProgram._Current);
   assert(sttcp->Base.Base.Target == GL_TESS_CONTROL_PROGRAM_NV);

   st->tcp_variant = st_get_basic_variant(st, PIPE_SHADER_TESS_CTRL,
                                          &sttcp->tgsi, &sttcp->variants);

   st_reference_tesscprog(st, &st->tcp, sttcp);

   cso_set_tessctrl_shader_handle(st->cso_context,
                                  st->tcp_variant->driver_shader);
}
예제 #2
0
/**
 * Setup pipeline state prior to rendering the bitmap textured quad.
 */
static void
setup_render_state(struct gl_context *ctx,
                   struct pipe_sampler_view *sv,
                   const GLfloat *color,
                   bool atlas)
{
    struct st_context *st = st_context(ctx);
    struct cso_context *cso = st->cso_context;
    struct st_fp_variant *fpv;
    struct st_fp_variant_key key;

    memset(&key, 0, sizeof(key));
    key.st = st->has_shareable_shaders ? NULL : st;
    key.bitmap = GL_TRUE;
    key.clamp_color = st->clamp_frag_color_in_shader &&
                      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, st->fp->Base.Base.Parameters,
                            PIPE_SHADER_FRAGMENT);
        COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
    }

    cso_save_state(cso, (CSO_BIT_RASTERIZER |
                         CSO_BIT_FRAGMENT_SAMPLERS |
                         CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
                         CSO_BIT_VIEWPORT |
                         CSO_BIT_STREAM_OUTPUTS |
                         CSO_BIT_VERTEX_ELEMENTS |
                         CSO_BIT_AUX_VERTEX_BUFFER_SLOT |
                         CSO_BITS_ALL_SHADERS));


    /* 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];
        }
        if (atlas)
            samplers[fpv->bitmap_sampler] = &st->bitmap.atlas_sampler;
        else
            samplers[fpv->bitmap_sampler] = &st->bitmap.sampler;
        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 */
    cso_set_viewport_dims(cso, st->state.framebuffer.width,
                          st->state.framebuffer.height,
                          st->state.fb_orientation == Y_0_TOP);

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

    cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
}
예제 #3
0
파일: u_blit.c 프로젝트: Echelon9/mesa
/**
 * 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_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, TGSI_WRITEMASK_XYZW,
                       src_sampler_view->format,
                       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);
}
예제 #4
0
static void
st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
           GLfloat width, GLfloat height)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct cso_context *cso = st->cso_context;
   struct pipe_resource *vbuffer = NULL;
   GLuint i, numTexCoords, numAttribs;
   GLboolean emitColor;
   uint semantic_names[2 + MAX_TEXTURE_UNITS];
   uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
   struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
   unsigned offset;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   st_validate_state(st, ST_PIPELINE_RENDER);

   /* determine if we need vertex color */
   if (ctx->FragmentProgram._Current->info.inputs_read & VARYING_BIT_COL0)
      emitColor = GL_TRUE;
   else
      emitColor = GL_FALSE;

   /* determine how many enabled sets of texcoords */
   numTexCoords = 0;
   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
      if (ctx->Texture.Unit[i]._Current &&
          ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
         numTexCoords++;
      }
   }

   /* total number of attributes per vertex */
   numAttribs = 1 + emitColor + numTexCoords;

   /* load vertex buffer */
   {
#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W)                              \
      do {                                                              \
         GLuint k = (((VERT) * numAttribs + (ATTR)) * 4);               \
         assert(k < 4 * 4 * numAttribs);                                \
         vbuf[k + 0] = X;                                               \
         vbuf[k + 1] = Y;                                               \
         vbuf[k + 2] = Z;                                               \
         vbuf[k + 3] = W;                                               \
      } while (0)

      const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
      GLfloat *vbuf = NULL;
      GLuint tex_attr;

      u_upload_alloc(pipe->stream_uploader, 0,
                     numAttribs * 4 * 4 * sizeof(GLfloat), 4,
                     &offset, &vbuffer, (void **) &vbuf);
      if (!vbuffer) {
         return;
      }

      z = CLAMP(z, 0.0f, 1.0f);

      /* positions (in clip coords) */
      {
         const struct gl_framebuffer *fb = ctx->DrawBuffer;
         const GLfloat fb_width = (GLfloat)_mesa_geometric_width(fb);
         const GLfloat fb_height = (GLfloat)_mesa_geometric_height(fb);

         const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
         const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
         const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
         const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);

         SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f);   /* lower left */
         SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f);   /* lower right */
         SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f);   /* upper right */
         SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f);   /* upper left */

         semantic_names[0] = TGSI_SEMANTIC_POSITION;
         semantic_indexes[0] = 0;
      }

      /* colors */
      if (emitColor) {
         const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
         SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
         semantic_names[1] = TGSI_SEMANTIC_COLOR;
         semantic_indexes[1] = 0;
         tex_attr = 2;
      }
      else {
         tex_attr = 1;
      }

      /* texcoords */
      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
         if (ctx->Texture.Unit[i]._Current &&
             ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
            struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
            const struct gl_texture_image *img = _mesa_base_tex_image(obj);
            const GLfloat wt = (GLfloat) img->Width;
            const GLfloat ht = (GLfloat) img->Height;
            const GLfloat s0 = obj->CropRect[0] / wt;
            const GLfloat t0 = obj->CropRect[1] / ht;
            const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
            const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;

            /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
            SET_ATTRIB(0, tex_attr, s0, t0, 0.0f, 1.0f);  /* lower left */
            SET_ATTRIB(1, tex_attr, s1, t0, 0.0f, 1.0f);  /* lower right */
            SET_ATTRIB(2, tex_attr, s1, t1, 0.0f, 1.0f);  /* upper right */
            SET_ATTRIB(3, tex_attr, s0, t1, 0.0f, 1.0f);  /* upper left */

            semantic_names[tex_attr] = st->needs_texcoord_semantic ?
               TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
            /* XXX: should this use semantic index i instead of 0 ? */
            semantic_indexes[tex_attr] = 0;

            tex_attr++;
         }
      }

      u_upload_unmap(pipe->stream_uploader);

#undef SET_ATTRIB
   }

   cso_save_state(cso, (CSO_BIT_VIEWPORT |
                        CSO_BIT_STREAM_OUTPUTS |
                        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));

   {
      void *vs = lookup_shader(pipe, numAttribs,
                               semantic_names, semantic_indexes);
      cso_set_vertex_shader_handle(cso, vs);
   }
   cso_set_tessctrl_shader_handle(cso, NULL);
   cso_set_tesseval_shader_handle(cso, NULL);
   cso_set_geometry_shader_handle(cso, NULL);

   for (i = 0; i < numAttribs; i++) {
      velements[i].src_offset = i * 4 * sizeof(float);
      velements[i].instance_divisor = 0;
      velements[i].vertex_buffer_index = 0;
      velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
   }
   cso_set_vertex_elements(cso, numAttribs, velements);
   cso_set_stream_outputs(cso, 0, NULL, NULL);

   /* viewport state: viewport matching window dims */
   {
      const struct gl_framebuffer *fb = ctx->DrawBuffer;
      const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
      const GLfloat width = (GLfloat)_mesa_geometric_width(fb);
      const GLfloat height = (GLfloat)_mesa_geometric_height(fb);
      struct pipe_viewport_state vp;
      vp.scale[0] =  0.5f * width;
      vp.scale[1] = height * (invert ? -0.5f : 0.5f);
      vp.scale[2] = 1.0f;
      vp.translate[0] = 0.5f * width;
      vp.translate[1] = 0.5f * height;
      vp.translate[2] = 0.0f;
      cso_set_viewport(cso, &vp);
   }

   util_draw_vertex_buffer(pipe, cso, vbuffer,
			   cso_get_aux_vertex_buffer_slot(cso),
                           offset,  /* offset */
                           PIPE_PRIM_TRIANGLE_FAN,
                           4,  /* verts */
                           numAttribs); /* attribs/vert */

   pipe_resource_reference(&vbuffer, NULL);

   /* restore state */
   cso_restore_state(cso);
}
예제 #5
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);
}
예제 #6
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 (ppq->n_filters == 0)
      return;

   assert(ppq->pp_queue);
   assert(ppq->tmp[0]);

   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;


      pp_blit(ppq->p->pipe, in, 0, 0,
              w, h, 0, ppq->tmps[0],
              0, 0, w, h);

      in = ppq->tmp[0];
   }

   /* save state (restored below) */
   cso_save_state(cso, (CSO_BIT_BLEND |
                        CSO_BIT_DEPTH_STENCIL_ALPHA |
                        CSO_BIT_FRAGMENT_SHADER |
                        CSO_BIT_FRAMEBUFFER |
                        CSO_BIT_TESSCTRL_SHADER |
                        CSO_BIT_TESSEVAL_SHADER |
                        CSO_BIT_GEOMETRY_SHADER |
                        CSO_BIT_RASTERIZER |
                        CSO_BIT_SAMPLE_MASK |
                        CSO_BIT_MIN_SAMPLES |
                        CSO_BIT_FRAGMENT_SAMPLERS |
                        CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
                        CSO_BIT_STENCIL_REF |
                        CSO_BIT_STREAM_OUTPUTS |
                        CSO_BIT_VERTEX_ELEMENTS |
                        CSO_BIT_VERTEX_SHADER |
                        CSO_BIT_VIEWPORT |
                        CSO_BIT_AUX_VERTEX_BUFFER_SLOT |
                        CSO_BIT_PAUSE_QUERIES |
                        CSO_BIT_RENDER_CONDITION));
   cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
   cso_save_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);

   /* set default state */
   cso_set_sample_mask(cso, ~0);
   cso_set_min_samples(cso, 1);
   cso_set_stream_outputs(cso, 0, NULL, NULL);
   cso_set_tessctrl_shader_handle(cso, NULL);
   cso_set_tesseval_shader_handle(cso, NULL);
   cso_set_geometry_shader_handle(cso, NULL);
   cso_set_render_condition(cso, NULL, FALSE, 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 0:
      /* Failsafe, but never reached. */
      break;
   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 */
      assert(ppq->tmp[1]);
      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_state(cso);
   cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
   cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);

   pipe_resource_reference(&ppq->depth, NULL);
   pipe_resource_reference(&refin, NULL);
   pipe_resource_reference(&refout, NULL);
}
예제 #7
0
/* Setup all vertex pipeline state, rasterizer state, and fragment shader
 * constants, and issue the draw call for PBO upload/download.
 *
 * The caller is responsible for saving and restoring state, as well as for
 * setting other fragment shader state (fragment shader, samplers), and
 * framebuffer/viewport/DSA/blend state.
 */
bool
st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr,
            unsigned surface_width, unsigned surface_height)
{
   struct cso_context *cso = st->cso_context;

   /* Setup vertex and geometry shaders */
   if (!st->pbo.vs) {
      st->pbo.vs = st_pbo_create_vs(st);
      if (!st->pbo.vs)
         return false;
   }

   if (addr->depth != 1 && st->pbo.use_gs && !st->pbo.gs) {
      st->pbo.gs = st_pbo_create_gs(st);
      if (!st->pbo.gs)
         return false;
   }

   cso_set_vertex_shader_handle(cso, st->pbo.vs);

   cso_set_geometry_shader_handle(cso, addr->depth != 1 ? st->pbo.gs : NULL);

   cso_set_tessctrl_shader_handle(cso, NULL);

   cso_set_tesseval_shader_handle(cso, NULL);

   /* Upload vertices */
   {
      struct pipe_vertex_buffer vbo = {0};
      struct pipe_vertex_element velem;

      float x0 = (float) addr->xoffset / surface_width * 2.0f - 1.0f;
      float y0 = (float) addr->yoffset / surface_height * 2.0f - 1.0f;
      float x1 = (float) (addr->xoffset + addr->width) / surface_width * 2.0f - 1.0f;
      float y1 = (float) (addr->yoffset + addr->height) / surface_height * 2.0f - 1.0f;

      float *verts = NULL;

      vbo.stride = 2 * sizeof(float);

      u_upload_alloc(st->pipe->stream_uploader, 0, 8 * sizeof(float), 4,
                     &vbo.buffer_offset, &vbo.buffer.resource, (void **) &verts);
      if (!verts)
         return false;

      verts[0] = x0;
      verts[1] = y0;
      verts[2] = x0;
      verts[3] = y1;
      verts[4] = x1;
      verts[5] = y0;
      verts[6] = x1;
      verts[7] = y1;

      u_upload_unmap(st->pipe->stream_uploader);

      velem.src_offset = 0;
      velem.instance_divisor = 0;
      velem.vertex_buffer_index = 0;
      velem.src_format = PIPE_FORMAT_R32G32_FLOAT;

      cso_set_vertex_elements(cso, 1, &velem);

      cso_set_vertex_buffers(cso, velem.vertex_buffer_index, 1, &vbo);

      pipe_resource_reference(&vbo.buffer.resource, NULL);
   }

   /* Upload constants */
   {
      struct pipe_constant_buffer cb;

      cb.buffer = NULL;
      cb.user_buffer = &addr->constants;
      cb.buffer_offset = 0;
      cb.buffer_size = sizeof(addr->constants);

      cso_set_constant_buffer(cso, PIPE_SHADER_FRAGMENT, 0, &cb);

      pipe_resource_reference(&cb.buffer, NULL);
   }

   /* Rasterizer state */
   cso_set_rasterizer(cso, &st->pbo.raster);

   /* Disable stream output */
   cso_set_stream_outputs(cso, 0, NULL, 0);

   if (addr->depth == 1) {
      cso_draw_arrays(cso, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
   } else {
      cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_STRIP,
                                0, 4, 0, addr->depth);
   }

   return true;
}
예제 #8
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);
}