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