Esempio n. 1
0
static void update_array(struct st_context *st)
{
   struct gl_context *ctx = st->ctx;
   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
   const struct st_vertex_program *vp;
   const struct st_vp_variant *vpv;
   struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
   unsigned num_vbuffers, num_velements;

   st->vertex_array_out_of_memory = FALSE;

   /* No drawing has been done yet, so do nothing. */
   if (!arrays)
      return;

   /* vertex program validation must be done before this */
   vp = st->vp;
   vpv = st->vp_variant;

   memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);

   /*
    * Setup the vbuffer[] and velements[] arrays.
    */
   if (is_interleaved_arrays(vp, vpv, arrays)) {
      if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) {
         st->vertex_array_out_of_memory = TRUE;
         return;
      }

      num_vbuffers = 1;
      num_velements = vpv->num_inputs;
      if (num_velements == 0)
         num_vbuffers = 0;
   }
   else {
      if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
                                         velements)) {
         st->vertex_array_out_of_memory = TRUE;
         return;
      }

      num_vbuffers = vpv->num_inputs;
      num_velements = vpv->num_inputs;
   }

   cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
   if (st->last_num_vbuffers > num_vbuffers) {
      /* Unbind remaining buffers, if any. */
      cso_set_vertex_buffers(st->cso_context, num_vbuffers,
                             st->last_num_vbuffers - num_vbuffers, NULL);
   }
   st->last_num_vbuffers = num_vbuffers;
   cso_set_vertex_elements(st->cso_context, num_velements, velements);
}
Esempio n. 2
0
/**
 * Draw a simple vertex buffer / primitive.
 * Limited to float[4] vertex attribs, tightly packed.
 */
void 
util_draw_vertex_buffer(struct pipe_context *pipe,
                        struct cso_context *cso,
                        struct pipe_resource *vbuf,
                        uint offset,
                        uint prim_type,
                        uint num_verts,
                        uint num_attribs)
{
   struct pipe_vertex_buffer vbuffer;

   assert(num_attribs <= PIPE_MAX_ATTRIBS);

   /* tell pipe about the vertex buffer */
   memset(&vbuffer, 0, sizeof(vbuffer));
   vbuffer.buffer = vbuf;
   vbuffer.stride = num_attribs * 4 * sizeof(float);  /* vertex size */
   vbuffer.buffer_offset = offset;

   /* note: vertex elements already set by caller */

   if (cso) {
      cso_set_vertex_buffers(cso, 1, &vbuffer);
      cso_draw_arrays(cso, prim_type, 0, num_verts);
   } else {
      pipe->set_vertex_buffers(pipe, 1, &vbuffer);
      util_draw_arrays(pipe, prim_type, 0, num_verts);
   }
}
Esempio n. 3
0
/**
 * Render a polygon silhouette to stencil buffer.
 */
void renderer_polygon_stencil(struct renderer *renderer,
                              struct pipe_vertex_buffer *vbuf,
                              VGuint mode, VGuint start, VGuint count)
{
   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);

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

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

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

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

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

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

      cso_set_rasterizer(renderer->cso, &raster);
      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
      cso_draw_arrays(renderer->cso, mode, start, count);
   }
}
Esempio n. 4
0
static void
set_vertex_attribs(struct st_context *st,
                   struct pipe_vertex_buffer *vbuffers,
                   unsigned num_vbuffers,
                   struct pipe_vertex_element *velements,
                   unsigned num_velements)
{
   struct cso_context *cso = st->cso_context;

   cso_set_vertex_buffers(cso, 0, num_vbuffers, vbuffers);
   if (st->last_num_vbuffers > num_vbuffers) {
      /* Unbind remaining buffers, if any. */
      cso_set_vertex_buffers(cso, num_vbuffers,
                             st->last_num_vbuffers - num_vbuffers, NULL);
   }
   st->last_num_vbuffers = num_vbuffers;
   cso_set_vertex_elements(cso, num_velements, velements);
}
/**
 * Draw a screen-aligned quadrilateral.
 * Coords are clip coords with y=0=bottom.
 */
static void
draw_quad(struct st_context *st,
          float x0, float y0, float x1, float y1, GLfloat z,
          unsigned num_instances,
          const union pipe_color_union *color)
{
   struct cso_context *cso = st->cso_context;
   struct pipe_vertex_buffer vb = {0};
   GLuint i;
   float (*vertices)[2][4];  /**< vertex pos + color */

   vb.stride = 8 * sizeof(float);

   if (u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]),
                      &vb.buffer_offset, &vb.buffer,
                      (void **) &vertices) != PIPE_OK) {
      return;
   }

   /* Convert Z from [0,1] to [-1,1] range */
   z = z * 2.0f - 1.0f;

   /* positions */
   vertices[0][0][0] = x0;
   vertices[0][0][1] = y0;

   vertices[1][0][0] = x1;
   vertices[1][0][1] = y0;

   vertices[2][0][0] = x1;
   vertices[2][0][1] = y1;

   vertices[3][0][0] = x0;
   vertices[3][0][1] = y1;

   /* same for all verts: */
   for (i = 0; i < 4; i++) {
      vertices[i][0][2] = z;
      vertices[i][0][3] = 1.0;
      vertices[i][1][0] = color->f[0];
      vertices[i][1][1] = color->f[1];
      vertices[i][1][2] = color->f[2];
      vertices[i][1][3] = color->f[3];
   }

   u_upload_unmap(st->uploader);

   /* draw */
   cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, &vb);
   cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_FAN, 0, 4,
                             0, num_instances);
   pipe_resource_reference(&vb.buffer, NULL);
}
Esempio n. 6
0
void cso_restore_aux_vertex_buffer_slot(struct cso_context *ctx)
{
   struct u_vbuf *vbuf = ctx->vbuf;

   if (vbuf) {
      u_vbuf_restore_aux_vertex_buffer_slot(vbuf);
      return;
   }

   cso_set_vertex_buffers(ctx, ctx->aux_vertex_buffer_index, 1,
                          &ctx->aux_vertex_buffer_saved);
   pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer, NULL);
}
Esempio n. 7
0
/**
 * Draw a simple vertex buffer / primitive.
 * Limited to float[4] vertex attribs, tightly packed.
 */
void
util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
                             uint prim_type, uint num_verts, uint num_attribs)
{
   struct pipe_vertex_buffer vbuffer = {0};

   assert(num_attribs <= PIPE_MAX_ATTRIBS);

   vbuffer.user_buffer = buffer;
   vbuffer.stride = num_attribs * 4 * sizeof(float);  /* vertex size */

   /* note: vertex elements already set by caller */

   cso_set_vertex_buffers(cso, 1, &vbuffer);
   cso_draw_arrays(cso, prim_type, 0, num_verts);
}
Esempio n. 8
0
/**
 * Setup vertex arrays and buffers prior to drawing.
 * \return GL_TRUE for success, GL_FALSE otherwise (probably out of memory)
 */
static GLboolean
st_validate_varrays(struct gl_context *ctx,
                    const struct gl_client_array **arrays)
{
   struct st_context *st = st_context(ctx);
   const struct st_vertex_program *vp;
   const struct st_vp_variant *vpv;
   struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
   unsigned num_vbuffers, num_velements;

   /* must get these after state validation! */
   vp = st->vp;
   vpv = st->vp_variant;

   memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);

   /*
    * Setup the vbuffer[] and velements[] arrays.
    */
   if (is_interleaved_arrays(vp, vpv, arrays)) {
      if (!setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer,
                                     velements)) {
         return GL_FALSE;
      }

      num_vbuffers = 1;
      num_velements = vpv->num_inputs;
      if (num_velements == 0)
         num_vbuffers = 0;
   }
   else {
      if (!setup_non_interleaved_attribs(ctx, vp, vpv, arrays,
                                         vbuffer, velements)) {
         return GL_FALSE;
      }

      num_vbuffers = vpv->num_inputs;
      num_velements = vpv->num_inputs;
   }

   cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer);
   cso_set_vertex_elements(st->cso_context, num_velements, velements);

   return GL_TRUE;
}
Esempio n. 9
0
/**
 * Called via ctx->Driver.DrawAtlasBitmap()
 */
static void
st_DrawAtlasBitmaps(struct gl_context *ctx,
                    const struct gl_bitmap_atlas *atlas,
                    GLuint count, const GLubyte *ids)
{
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
    struct st_texture_object *stObj = st_texture_object(atlas->texObj);
    struct pipe_sampler_view *sv;
    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
    const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f;
    const float *color = ctx->Current.RasterColor;
    const float clip_x_scale = 2.0f / st->state.framebuffer.width;
    const float clip_y_scale = 2.0f / st->state.framebuffer.height;
    const unsigned num_verts = count * 4;
    const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex);
    struct st_util_vertex *verts;
    struct pipe_vertex_buffer vb = {0};
    unsigned i;

    if (!st->bitmap.cache) {
        init_bitmap_state(st);
    }

    st_flush_bitmap_cache(st);

    st_validate_state(st, ST_PIPELINE_RENDER);
    st_invalidate_readpix_cache(st);

    sv = st_create_texture_sampler_view(pipe, stObj->pt);
    if (!sv) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)");
        return;
    }

    setup_render_state(ctx, sv, color, true);

    vb.stride = sizeof(struct st_util_vertex);

    u_upload_alloc(st->uploader, 0, num_vert_bytes, 4,
                   &vb.buffer_offset, &vb.buffer, (void **) &verts);

    /* build quads vertex data */
    for (i = 0; i < count; i++) {
        const GLfloat epsilon = 0.0001F;
        const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]];
        const float xmove = g->xmove, ymove = g->ymove;
        const float xorig = g->xorig, yorig = g->yorig;
        const float s0 = g->x, t0 = g->y;
        const float s1 = s0 + g->w, t1 = t0 + g->h;
        const float x0 = IFLOOR(ctx->Current.RasterPos[0] - xorig + epsilon);
        const float y0 = IFLOOR(ctx->Current.RasterPos[1] - yorig + epsilon);
        const float x1 = x0 + g->w, y1 = y0 + g->h;
        const float clip_x0 = x0 * clip_x_scale - 1.0f;
        const float clip_y0 = y0 * clip_y_scale - 1.0f;
        const float clip_x1 = x1 * clip_x_scale - 1.0f;
        const float clip_y1 = y1 * clip_y_scale - 1.0f;

        /* lower-left corner */
        verts->x = clip_x0;
        verts->y = clip_y0;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s0;
        verts->t = t0;
        verts++;

        /* lower-right corner */
        verts->x = clip_x1;
        verts->y = clip_y0;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s1;
        verts->t = t0;
        verts++;

        /* upper-right corner */
        verts->x = clip_x1;
        verts->y = clip_y1;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s1;
        verts->t = t1;
        verts++;

        /* upper-left corner */
        verts->x = clip_x0;
        verts->y = clip_y1;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s0;
        verts->t = t1;
        verts++;

        /* Update the raster position */
        ctx->Current.RasterPos[0] += xmove;
        ctx->Current.RasterPos[1] += ymove;
    }

    u_upload_unmap(st->uploader);

    cso_set_vertex_buffers(st->cso_context,
                           cso_get_aux_vertex_buffer_slot(st->cso_context),
                           1, &vb);

    cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts);

    restore_render_state(ctx);

    pipe_resource_reference(&vb.buffer, NULL);

    pipe_sampler_view_reference(&sv, NULL);

    /* We uploaded modified constants, need to invalidate them. */
    st->dirty |= ST_NEW_FS_CONSTANTS;
}
Esempio n. 10
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;
}
Esempio n. 11
0
/**
 * Draw a quad with given position, texcoords and color.
 */
bool
st_draw_quad(struct st_context *st,
             float x0, float y0, float x1, float y1, float z,
             float s0, float t0, float s1, float t1,
             const float *color,
             unsigned num_instances)
{
   struct pipe_vertex_buffer vb = {0};
   struct st_util_vertex *verts;

   vb.stride = sizeof(struct st_util_vertex);

   u_upload_alloc(st->uploader, 0, 4 * sizeof(struct st_util_vertex), 4,
                  &vb.buffer_offset, &vb.buffer, (void **) &verts);
   if (!vb.buffer) {
      return false;
   }

   /* lower-left */
   verts[0].x = x0;
   verts[0].y = y1;
   verts[0].z = z;
   verts[0].r = color[0];
   verts[0].g = color[1];
   verts[0].b = color[2];
   verts[0].a = color[3];
   verts[0].s = s0;
   verts[0].t = t0;

   /* lower-right */
   verts[1].x = x1;
   verts[1].y = y1;
   verts[1].z = z;
   verts[1].r = color[0];
   verts[1].g = color[1];
   verts[1].b = color[2];
   verts[1].a = color[3];
   verts[1].s = s1;
   verts[1].t = t0;

   /* upper-right */
   verts[2].x = x1;
   verts[2].y = y0;
   verts[2].z = z;
   verts[2].r = color[0];
   verts[2].g = color[1];
   verts[2].b = color[2];
   verts[2].a = color[3];
   verts[2].s = s1;
   verts[2].t = t1;

   /* upper-left */
   verts[3].x = x0;
   verts[3].y = y0;
   verts[3].z = z;
   verts[3].r = color[0];
   verts[3].g = color[1];
   verts[3].b = color[2];
   verts[3].a = color[3];
   verts[3].s = s0;
   verts[3].t = t1;

   u_upload_unmap(st->uploader);

   /* At the time of writing, cso_get_aux_vertex_buffer_slot() always returns
    * zero.  If that ever changes we need to audit the calls to that function
    * and make sure the slot number is used consistently everywhere.
    */
   assert(cso_get_aux_vertex_buffer_slot(st->cso_context) == 0);

   cso_set_vertex_buffers(st->cso_context,
                          cso_get_aux_vertex_buffer_slot(st->cso_context),
                          1, &vb);

   if (num_instances > 1) {
      cso_draw_arrays_instanced(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4,
                                0, num_instances);
   } else {
      cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4);
   }

   pipe_resource_reference(&vb.buffer, NULL);

   return true;
}