/** * Setup vertex data for the textured quad we'll draw. * Note: y=0=top * * FIXME: We should call util_map_texcoords2d_onto_cubemap * for cubemaps. */ static unsigned setup_vertex_data_tex(struct blit_state *ctx, enum pipe_texture_target src_target, unsigned src_face, float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1, float z) { unsigned offset; ctx->vertices[0][0][0] = x0; ctx->vertices[0][0][1] = y0; ctx->vertices[0][0][2] = z; ctx->vertices[0][1][0] = s0; /*s*/ ctx->vertices[0][1][1] = t0; /*t*/ ctx->vertices[0][1][2] = 0; /*r*/ ctx->vertices[1][0][0] = x1; ctx->vertices[1][0][1] = y0; ctx->vertices[1][0][2] = z; ctx->vertices[1][1][0] = s1; /*s*/ ctx->vertices[1][1][1] = t0; /*t*/ ctx->vertices[1][1][2] = 0; /*r*/ ctx->vertices[2][0][0] = x1; ctx->vertices[2][0][1] = y1; ctx->vertices[2][0][2] = z; ctx->vertices[2][1][0] = s1; ctx->vertices[2][1][1] = t1; ctx->vertices[3][1][2] = 0; ctx->vertices[3][0][0] = x0; ctx->vertices[3][0][1] = y1; ctx->vertices[3][0][2] = z; ctx->vertices[3][1][0] = s0; ctx->vertices[3][1][1] = t1; ctx->vertices[3][1][2] = 0; if (src_target == PIPE_TEXTURE_CUBE || src_target == PIPE_TEXTURE_CUBE_ARRAY) { /* Map cubemap texture coordinates inplace. */ const unsigned stride = sizeof ctx->vertices[0] / sizeof ctx->vertices[0][0][0]; util_map_texcoords2d_onto_cubemap(src_face, &ctx->vertices[0][1][0], stride, &ctx->vertices[0][1][0], stride, TRUE); } offset = get_next_slot(ctx); if (ctx->vbuf) { pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, offset, sizeof(ctx->vertices), ctx->vertices); } return offset; }
/** * Setup vertex data for the textured quad we'll draw. * Note: y=0=top */ static unsigned setup_vertex_data_tex(struct blit_state *ctx, float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1, float z) { unsigned offset; ctx->vertices[0][0][0] = x0; ctx->vertices[0][0][1] = y0; ctx->vertices[0][0][2] = z; ctx->vertices[0][1][0] = s0; /*s*/ ctx->vertices[0][1][1] = t0; /*t*/ ctx->vertices[1][0][0] = x1; ctx->vertices[1][0][1] = y0; ctx->vertices[1][0][2] = z; ctx->vertices[1][1][0] = s1; /*s*/ ctx->vertices[1][1][1] = t0; /*t*/ ctx->vertices[2][0][0] = x1; ctx->vertices[2][0][1] = y1; ctx->vertices[2][0][2] = z; ctx->vertices[2][1][0] = s1; ctx->vertices[2][1][1] = t1; ctx->vertices[3][0][0] = x0; ctx->vertices[3][0][1] = y1; ctx->vertices[3][0][2] = z; ctx->vertices[3][1][0] = s0; ctx->vertices[3][1][1] = t1; offset = get_next_slot( ctx ); if (ctx->vbuf) { pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, offset, sizeof(ctx->vertices), ctx->vertices); } return offset; }
void si_begin_new_cs(struct si_context *ctx) { if (ctx->is_debug) { uint32_t zero = 0; /* Create a buffer used for writing trace IDs and initialize it to 0. */ assert(!ctx->trace_buf); ctx->trace_buf = (struct r600_resource*) pipe_buffer_create(ctx->b.b.screen, PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, 4); if (ctx->trace_buf) pipe_buffer_write_nooverlap(&ctx->b.b, &ctx->trace_buf->b.b, 0, sizeof(zero), &zero); ctx->trace_id = 0; } if (ctx->trace_buf) si_trace_emit(ctx); /* Flush read caches at the beginning of CS. */ ctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER | SI_CONTEXT_INV_VMEM_L1 | SI_CONTEXT_INV_GLOBAL_L2 | SI_CONTEXT_INV_SMEM_L1 | SI_CONTEXT_INV_ICACHE; /* set all valid group as dirty so they get reemited on * next draw command */ si_pm4_reset_emitted(ctx); /* The CS initialization should be emitted before everything else. */ si_pm4_emit(ctx, ctx->init_config); if (ctx->init_config_gs_rings) si_pm4_emit(ctx, ctx->init_config_gs_rings); ctx->framebuffer.dirty_cbufs = (1 << 8) - 1; ctx->framebuffer.dirty_zsbuf = true; si_mark_atom_dirty(ctx, &ctx->framebuffer.atom); si_mark_atom_dirty(ctx, &ctx->clip_regs); si_mark_atom_dirty(ctx, &ctx->clip_state.atom); si_mark_atom_dirty(ctx, &ctx->msaa_sample_locs); si_mark_atom_dirty(ctx, &ctx->msaa_config); si_mark_atom_dirty(ctx, &ctx->sample_mask.atom); si_mark_atom_dirty(ctx, &ctx->cb_render_state); si_mark_atom_dirty(ctx, &ctx->blend_color.atom); si_mark_atom_dirty(ctx, &ctx->db_render_state); si_mark_atom_dirty(ctx, &ctx->stencil_ref.atom); si_mark_atom_dirty(ctx, &ctx->spi_map); si_mark_atom_dirty(ctx, &ctx->b.streamout.enable_atom); si_mark_atom_dirty(ctx, &ctx->b.render_cond_atom); si_all_descriptors_begin_new_cs(ctx); ctx->scissors.dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1; ctx->viewports.dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1; si_mark_atom_dirty(ctx, &ctx->scissors.atom); si_mark_atom_dirty(ctx, &ctx->viewports.atom); r600_postflush_resume_features(&ctx->b); ctx->b.initial_gfx_cs_size = ctx->b.gfx.cs->cdw; /* Invalidate various draw states so that they are emitted before * the first draw call. */ si_invalidate_draw_sh_constants(ctx); ctx->last_primitive_restart_en = -1; ctx->last_restart_index = SI_RESTART_INDEX_UNKNOWN; ctx->last_gs_out_prim = -1; ctx->last_prim = -1; ctx->last_multi_vgt_param = -1; ctx->last_ls_hs_config = -1; ctx->last_rast_prim = -1; ctx->last_sc_line_stipple = ~0; ctx->emit_scratch_reloc = true; ctx->last_ls = NULL; ctx->last_tcs = NULL; ctx->last_tes_sh_base = -1; ctx->last_num_tcs_input_cp = -1; }
static void svga_vbuf_render_draw_elements( struct vbuf_render *render, const ushort *indices, uint nr_indices) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; struct pipe_screen *screen = svga->pipe.screen; int bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size; boolean ret; size_t size = 2 * nr_indices; assert(( svga_render->vbuf_offset - svga_render->vdecl_offset) % svga_render->vertex_size == 0); if (svga_render->ibuf_size < svga_render->ibuf_offset + size) pipe_resource_reference(&svga_render->ibuf, NULL); if (!svga_render->ibuf) { svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size); svga_render->ibuf = pipe_buffer_create(screen, PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM, svga_render->ibuf_size); svga_render->ibuf_offset = 0; } pipe_buffer_write_nooverlap(&svga->pipe, svga_render->ibuf, svga_render->ibuf_offset, 2 * nr_indices, indices); /* off to hardware */ svga_vbuf_submit_state(svga_render); /* Need to call update_state() again as the draw module may have * altered some of our state behind our backs. Testcase: * redbook/polys.c */ svga_update_state_retry( svga, SVGA_STATE_HW_DRAW ); ret = svga_hwtnl_draw_range_elements(svga->hwtnl, svga_render->ibuf, 2, bias, svga_render->min_index, svga_render->max_index, svga_render->prim, svga_render->ibuf_offset / 2, nr_indices); if(ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_hwtnl_draw_range_elements(svga->hwtnl, svga_render->ibuf, 2, bias, svga_render->min_index, svga_render->max_index, svga_render->prim, svga_render->ibuf_offset / 2, nr_indices); svga->swtnl.new_vbuf = TRUE; assert(ret == PIPE_OK); } svga_render->ibuf_offset += size; }
/** * 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, const GLfloat color[4]) { struct pipe_context *pipe = st->pipe; /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as * no_flush) updates to buffers where we know there is no conflict * with previous data. Currently using max_slots > 1 will cause * synchronous rendering if the driver flushes its command buffers * between one bitmap and the next. Our flush hook below isn't * sufficient to catch this as the driver doesn't tell us when it * flushes its own command buffers. Until this gets fixed, pay the * price of allocating a new buffer for each bitmap cache-flush to * avoid synchronous rendering. */ const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */ GLuint i; if (st->clear.vbuf_slot >= max_slots) { pipe_resource_reference(&st->clear.vbuf, NULL); st->clear.vbuf_slot = 0; } if (!st->clear.vbuf) { st->clear.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, max_slots * sizeof(st->clear.vertices)); } /* positions */ st->clear.vertices[0][0][0] = x0; st->clear.vertices[0][0][1] = y0; st->clear.vertices[1][0][0] = x1; st->clear.vertices[1][0][1] = y0; st->clear.vertices[2][0][0] = x1; st->clear.vertices[2][0][1] = y1; st->clear.vertices[3][0][0] = x0; st->clear.vertices[3][0][1] = y1; /* same for all verts: */ for (i = 0; i < 4; i++) { st->clear.vertices[i][0][2] = z; st->clear.vertices[i][0][3] = 1.0; st->clear.vertices[i][1][0] = color[0]; st->clear.vertices[i][1][1] = color[1]; st->clear.vertices[i][1][2] = color[2]; st->clear.vertices[i][1][3] = color[3]; } /* put vertex data into vbuf */ pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), sizeof(st->clear.vertices), st->clear.vertices); /* draw */ util_draw_vertex_buffer(pipe, st->cso_context, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ /* Increment slot */ st->clear.vbuf_slot++; }
static GLuint setup_bitmap_vertex_data(struct st_context *st, bool normalized, int x, int y, int width, int height, float z, const float color[4]) { struct pipe_context *pipe = st->pipe; const struct gl_framebuffer *fb = st->ctx->DrawBuffer; const GLfloat fb_width = (GLfloat)fb->Width; const GLfloat fb_height = (GLfloat)fb->Height; const GLfloat x0 = (GLfloat)x; const GLfloat x1 = (GLfloat)(x + width); const GLfloat y0 = (GLfloat)y; const GLfloat y1 = (GLfloat)(y + height); GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0; GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop; 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); const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */ GLuint i; if(!normalized) { sRight = width; tBot = height; } /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as * no_flush) updates to buffers where we know there is no conflict * with previous data. Currently using max_slots > 1 will cause * synchronous rendering if the driver flushes its command buffers * between one bitmap and the next. Our flush hook below isn't * sufficient to catch this as the driver doesn't tell us when it * flushes its own command buffers. Until this gets fixed, pay the * price of allocating a new buffer for each bitmap cache-flush to * avoid synchronous rendering. */ if (st->bitmap.vbuf_slot >= max_slots) { pipe_resource_reference(&st->bitmap.vbuf, NULL); st->bitmap.vbuf_slot = 0; } if (!st->bitmap.vbuf) { st->bitmap.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, max_slots * sizeof(st->bitmap.vertices)); } /* Positions are in clip coords since we need to do clipping in case * the bitmap quad goes beyond the window bounds. */ st->bitmap.vertices[0][0][0] = clip_x0; st->bitmap.vertices[0][0][1] = clip_y0; st->bitmap.vertices[0][2][0] = sLeft; st->bitmap.vertices[0][2][1] = tTop; st->bitmap.vertices[1][0][0] = clip_x1; st->bitmap.vertices[1][0][1] = clip_y0; st->bitmap.vertices[1][2][0] = sRight; st->bitmap.vertices[1][2][1] = tTop; st->bitmap.vertices[2][0][0] = clip_x1; st->bitmap.vertices[2][0][1] = clip_y1; st->bitmap.vertices[2][2][0] = sRight; st->bitmap.vertices[2][2][1] = tBot; st->bitmap.vertices[3][0][0] = clip_x0; st->bitmap.vertices[3][0][1] = clip_y1; st->bitmap.vertices[3][2][0] = sLeft; st->bitmap.vertices[3][2][1] = tBot; /* same for all verts: */ for (i = 0; i < 4; i++) { st->bitmap.vertices[i][0][2] = z; st->bitmap.vertices[i][0][3] = 1.0; st->bitmap.vertices[i][1][0] = color[0]; st->bitmap.vertices[i][1][1] = color[1]; st->bitmap.vertices[i][1][2] = color[2]; st->bitmap.vertices[i][1][3] = color[3]; st->bitmap.vertices[i][2][2] = 0.0; /*R*/ st->bitmap.vertices[i][2][3] = 1.0; /*Q*/ } /* put vertex data into vbuf */ pipe_buffer_write_nooverlap(st->pipe, st->bitmap.vbuf, st->bitmap.vbuf_slot * sizeof(st->bitmap.vertices), sizeof st->bitmap.vertices, st->bitmap.vertices); return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices; }
void r600_begin_new_cs(struct r600_context *ctx) { unsigned shader; if (ctx->is_debug) { uint32_t zero = 0; /* Create a buffer used for writing trace IDs and initialize it to 0. */ assert(!ctx->trace_buf); ctx->trace_buf = (struct r600_resource*) pipe_buffer_create(ctx->b.b.screen, 0, PIPE_USAGE_STAGING, 4); if (ctx->trace_buf) pipe_buffer_write_nooverlap(&ctx->b.b, &ctx->trace_buf->b.b, 0, sizeof(zero), &zero); ctx->trace_id = 0; } if (ctx->trace_buf) eg_trace_emit(ctx); ctx->b.flags = 0; ctx->b.gtt = 0; ctx->b.vram = 0; /* Begin a new CS. */ r600_emit_command_buffer(ctx->b.gfx.cs, &ctx->start_cs_cmd); /* Re-emit states. */ r600_mark_atom_dirty(ctx, &ctx->alphatest_state.atom); r600_mark_atom_dirty(ctx, &ctx->blend_color.atom); r600_mark_atom_dirty(ctx, &ctx->cb_misc_state.atom); r600_mark_atom_dirty(ctx, &ctx->clip_misc_state.atom); r600_mark_atom_dirty(ctx, &ctx->clip_state.atom); r600_mark_atom_dirty(ctx, &ctx->db_misc_state.atom); r600_mark_atom_dirty(ctx, &ctx->db_state.atom); r600_mark_atom_dirty(ctx, &ctx->framebuffer.atom); if (ctx->b.chip_class >= EVERGREEN) { r600_mark_atom_dirty(ctx, &ctx->fragment_images.atom); r600_mark_atom_dirty(ctx, &ctx->fragment_buffers.atom); r600_mark_atom_dirty(ctx, &ctx->compute_images.atom); r600_mark_atom_dirty(ctx, &ctx->compute_buffers.atom); } r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_PS].atom); r600_mark_atom_dirty(ctx, &ctx->poly_offset_state.atom); r600_mark_atom_dirty(ctx, &ctx->vgt_state.atom); r600_mark_atom_dirty(ctx, &ctx->sample_mask.atom); ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; r600_mark_atom_dirty(ctx, &ctx->b.scissors.atom); ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; ctx->b.viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; r600_mark_atom_dirty(ctx, &ctx->b.viewports.atom); if (ctx->b.chip_class <= EVERGREEN) { r600_mark_atom_dirty(ctx, &ctx->config_state.atom); } r600_mark_atom_dirty(ctx, &ctx->stencil_ref.atom); r600_mark_atom_dirty(ctx, &ctx->vertex_fetch_shader.atom); r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_ES].atom); r600_mark_atom_dirty(ctx, &ctx->shader_stages.atom); if (ctx->gs_shader) { r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_GS].atom); r600_mark_atom_dirty(ctx, &ctx->gs_rings.atom); } if (ctx->tes_shader) { r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[EG_HW_STAGE_HS].atom); r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[EG_HW_STAGE_LS].atom); } r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_VS].atom); r600_mark_atom_dirty(ctx, &ctx->b.streamout.enable_atom); r600_mark_atom_dirty(ctx, &ctx->b.render_cond_atom); if (ctx->blend_state.cso) r600_mark_atom_dirty(ctx, &ctx->blend_state.atom); if (ctx->dsa_state.cso) r600_mark_atom_dirty(ctx, &ctx->dsa_state.atom); if (ctx->rasterizer_state.cso) r600_mark_atom_dirty(ctx, &ctx->rasterizer_state.atom); if (ctx->b.chip_class <= R700) { r600_mark_atom_dirty(ctx, &ctx->seamless_cube_map.atom); } ctx->vertex_buffer_state.dirty_mask = ctx->vertex_buffer_state.enabled_mask; r600_vertex_buffers_dirty(ctx); /* Re-emit shader resources. */ for (shader = 0; shader < PIPE_SHADER_TYPES; shader++) { struct r600_constbuf_state *constbuf = &ctx->constbuf_state[shader]; struct r600_textures_info *samplers = &ctx->samplers[shader]; constbuf->dirty_mask = constbuf->enabled_mask; samplers->views.dirty_mask = samplers->views.enabled_mask; samplers->states.dirty_mask = samplers->states.enabled_mask; r600_constant_buffers_dirty(ctx, constbuf); r600_sampler_views_dirty(ctx, &samplers->views); r600_sampler_states_dirty(ctx, &samplers->states); } for (shader = 0; shader < ARRAY_SIZE(ctx->scratch_buffers); shader++) { ctx->scratch_buffers[shader].dirty = true; } r600_postflush_resume_features(&ctx->b); /* Re-emit the draw state. */ ctx->last_primitive_type = -1; ctx->last_start_instance = -1; ctx->last_rast_prim = -1; ctx->current_rast_prim = -1; assert(!ctx->b.gfx.cs->prev_dw); ctx->b.initial_gfx_cs_size = ctx->b.gfx.cs->current.cdw; }
static unsigned set_vertex_data(struct gen_mipmap_state *ctx, enum pipe_texture_target tex_target, uint face, float r) { unsigned offset; /* vert[0].position */ ctx->vertices[0][0][0] = -1.0f; /*x*/ ctx->vertices[0][0][1] = -1.0f; /*y*/ /* vert[1].position */ ctx->vertices[1][0][0] = 1.0f; ctx->vertices[1][0][1] = -1.0f; /* vert[2].position */ ctx->vertices[2][0][0] = 1.0f; ctx->vertices[2][0][1] = 1.0f; /* vert[3].position */ ctx->vertices[3][0][0] = -1.0f; ctx->vertices[3][0][1] = 1.0f; /* Setup vertex texcoords. This is a little tricky for cube maps. */ if (tex_target == PIPE_TEXTURE_CUBE || tex_target == PIPE_TEXTURE_CUBE_ARRAY) { static const float st[4][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} }; util_map_texcoords2d_onto_cubemap(face, &st[0][0], 2, &ctx->vertices[0][1][0], 8, FALSE); /* set the layer for cube arrays */ ctx->vertices[0][1][3] = r; ctx->vertices[1][1][3] = r; ctx->vertices[2][1][3] = r; ctx->vertices[3][1][3] = r; } else if (tex_target == PIPE_TEXTURE_1D_ARRAY) { /* 1D texture array */ ctx->vertices[0][1][0] = 0.0f; /*s*/ ctx->vertices[0][1][1] = r; /*t*/ ctx->vertices[0][1][2] = 0.0f; /*r*/ ctx->vertices[1][1][0] = 1.0f; ctx->vertices[1][1][1] = r; ctx->vertices[1][1][2] = 0.0f; ctx->vertices[2][1][0] = 1.0f; ctx->vertices[2][1][1] = r; ctx->vertices[2][1][2] = 0.0f; ctx->vertices[3][1][0] = 0.0f; ctx->vertices[3][1][1] = r; ctx->vertices[3][1][2] = 0.0f; } else { /* 1D/2D/3D/2D array */ ctx->vertices[0][1][0] = 0.0f; /*s*/ ctx->vertices[0][1][1] = 0.0f; /*t*/ ctx->vertices[0][1][2] = r; /*r*/ ctx->vertices[1][1][0] = 1.0f; ctx->vertices[1][1][1] = 0.0f; ctx->vertices[1][1][2] = r; ctx->vertices[2][1][0] = 1.0f; ctx->vertices[2][1][1] = 1.0f; ctx->vertices[2][1][2] = r; ctx->vertices[3][1][0] = 0.0f; ctx->vertices[3][1][1] = 1.0f; ctx->vertices[3][1][2] = r; } offset = get_next_slot( ctx ); pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, offset, sizeof(ctx->vertices), ctx->vertices); return offset; }