1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/* 29bf215546Sopenharmony_ci * This file implements the st_draw_vbo() function which is called from 30bf215546Sopenharmony_ci * Mesa's VBO module. All point/line/triangle rendering is done through 31bf215546Sopenharmony_ci * this function whether the user called glBegin/End, glDrawArrays, 32bf215546Sopenharmony_ci * glDrawElements, glEvalMesh, or glCalList, etc. 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * Authors: 35bf215546Sopenharmony_ci * Keith Whitwell <keithw@vmware.com> 36bf215546Sopenharmony_ci */ 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "main/errors.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "main/image.h" 42bf215546Sopenharmony_ci#include "main/bufferobj.h" 43bf215546Sopenharmony_ci#include "main/macros.h" 44bf215546Sopenharmony_ci#include "main/varray.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#include "compiler/glsl/ir_uniform.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#include "vbo/vbo.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#include "st_context.h" 51bf215546Sopenharmony_ci#include "st_atom.h" 52bf215546Sopenharmony_ci#include "st_cb_bitmap.h" 53bf215546Sopenharmony_ci#include "st_debug.h" 54bf215546Sopenharmony_ci#include "st_draw.h" 55bf215546Sopenharmony_ci#include "st_program.h" 56bf215546Sopenharmony_ci#include "st_util.h" 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci#include "pipe/p_context.h" 59bf215546Sopenharmony_ci#include "pipe/p_defines.h" 60bf215546Sopenharmony_ci#include "util/u_cpu_detect.h" 61bf215546Sopenharmony_ci#include "util/u_inlines.h" 62bf215546Sopenharmony_ci#include "util/format/u_format.h" 63bf215546Sopenharmony_ci#include "util/u_prim.h" 64bf215546Sopenharmony_ci#include "util/u_draw.h" 65bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 66bf215546Sopenharmony_ci#include "util/u_threaded_context.h" 67bf215546Sopenharmony_ci#include "draw/draw_context.h" 68bf215546Sopenharmony_ci#include "cso_cache/cso_context.h" 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci/** 72bf215546Sopenharmony_ci * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to 73bf215546Sopenharmony_ci * the corresponding Gallium type. 74bf215546Sopenharmony_ci */ 75bf215546Sopenharmony_cistatic unsigned 76bf215546Sopenharmony_citranslate_prim(const struct gl_context *ctx, unsigned prim) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci /* GL prims should match Gallium prims, spot-check a few */ 79bf215546Sopenharmony_ci STATIC_ASSERT(GL_POINTS == PIPE_PRIM_POINTS); 80bf215546Sopenharmony_ci STATIC_ASSERT(GL_QUADS == PIPE_PRIM_QUADS); 81bf215546Sopenharmony_ci STATIC_ASSERT(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 82bf215546Sopenharmony_ci STATIC_ASSERT(GL_PATCHES == PIPE_PRIM_PATCHES); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci return prim; 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic inline void 88bf215546Sopenharmony_ciprepare_draw(struct st_context *st, struct gl_context *ctx, uint64_t state_mask, 89bf215546Sopenharmony_ci enum st_pipeline pipeline) 90bf215546Sopenharmony_ci{ 91bf215546Sopenharmony_ci /* Mesa core state should have been validated already */ 92bf215546Sopenharmony_ci assert(ctx->NewState == 0x0); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (unlikely(!st->bitmap.cache.empty)) 95bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci st_invalidate_readpix_cache(st); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci /* Validate state. */ 100bf215546Sopenharmony_ci if ((st->dirty | ctx->NewDriverState) & st->active_states & state_mask || 101bf215546Sopenharmony_ci st->gfx_shaders_may_be_dirty) { 102bf215546Sopenharmony_ci st_validate_state(st, pipeline); 103bf215546Sopenharmony_ci } 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci /* Pin threads regularly to the same Zen CCX that the main thread is 106bf215546Sopenharmony_ci * running on. The main thread can move between CCXs. 107bf215546Sopenharmony_ci */ 108bf215546Sopenharmony_ci if (unlikely(st->pin_thread_counter != ST_L3_PINNING_DISABLED && 109bf215546Sopenharmony_ci /* no glthread */ 110bf215546Sopenharmony_ci !ctx->GLThread.enabled && 111bf215546Sopenharmony_ci /* do it occasionally */ 112bf215546Sopenharmony_ci ++st->pin_thread_counter % 512 == 0)) { 113bf215546Sopenharmony_ci st->pin_thread_counter = 0; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci int cpu = util_get_current_cpu(); 116bf215546Sopenharmony_ci if (cpu >= 0) { 117bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 118bf215546Sopenharmony_ci uint16_t L3_cache = util_get_cpu_caps()->cpu_to_L3[cpu]; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci if (L3_cache != U_CPU_INVALID_L3) { 121bf215546Sopenharmony_ci pipe->set_context_param(pipe, 122bf215546Sopenharmony_ci PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE, 123bf215546Sopenharmony_ci L3_cache); 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_cistatic bool ALWAYS_INLINE 130bf215546Sopenharmony_ciprepare_indexed_draw(/* pass both st and ctx to reduce dereferences */ 131bf215546Sopenharmony_ci struct st_context *st, 132bf215546Sopenharmony_ci struct gl_context *ctx, 133bf215546Sopenharmony_ci struct pipe_draw_info *info, 134bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 135bf215546Sopenharmony_ci unsigned num_draws) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci if (info->index_size) { 138bf215546Sopenharmony_ci /* Get index bounds for user buffers. */ 139bf215546Sopenharmony_ci if (!info->index_bounds_valid && 140bf215546Sopenharmony_ci st->draw_needs_minmax_index) { 141bf215546Sopenharmony_ci /* Return if this fails, which means all draws have count == 0. */ 142bf215546Sopenharmony_ci if (!vbo_get_minmax_indices_gallium(ctx, info, draws, num_draws)) 143bf215546Sopenharmony_ci return false; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci info->index_bounds_valid = true; 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (!info->has_user_indices) { 149bf215546Sopenharmony_ci if (st->pipe->draw_vbo == tc_draw_vbo) { 150bf215546Sopenharmony_ci /* Fast path for u_threaded_context. This eliminates the atomic 151bf215546Sopenharmony_ci * increment for the index buffer refcount when adding it into 152bf215546Sopenharmony_ci * the threaded batch buffer. 153bf215546Sopenharmony_ci */ 154bf215546Sopenharmony_ci info->index.resource = 155bf215546Sopenharmony_ci _mesa_get_bufferobj_reference(ctx, info->index.gl_bo); 156bf215546Sopenharmony_ci info->take_index_buffer_ownership = true; 157bf215546Sopenharmony_ci } else { 158bf215546Sopenharmony_ci info->index.resource = info->index.gl_bo->buffer; 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci /* Return if the bound element array buffer doesn't have any backing 162bf215546Sopenharmony_ci * storage. (nothing to do) 163bf215546Sopenharmony_ci */ 164bf215546Sopenharmony_ci if (unlikely(!info->index.resource)) 165bf215546Sopenharmony_ci return false; 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci return true; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic void 172bf215546Sopenharmony_cist_draw_gallium(struct gl_context *ctx, 173bf215546Sopenharmony_ci struct pipe_draw_info *info, 174bf215546Sopenharmony_ci unsigned drawid_offset, 175bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 176bf215546Sopenharmony_ci unsigned num_draws) 177bf215546Sopenharmony_ci{ 178bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) 183bf215546Sopenharmony_ci return; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci cso_multi_draw(st->cso_context, info, drawid_offset, draws, num_draws); 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_cistatic void 189bf215546Sopenharmony_cist_draw_gallium_multimode(struct gl_context *ctx, 190bf215546Sopenharmony_ci struct pipe_draw_info *info, 191bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 192bf215546Sopenharmony_ci const unsigned char *mode, 193bf215546Sopenharmony_ci unsigned num_draws) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) 200bf215546Sopenharmony_ci return; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci unsigned i, first; 203bf215546Sopenharmony_ci struct cso_context *cso = st->cso_context; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci /* Find consecutive draws where mode doesn't vary. */ 206bf215546Sopenharmony_ci for (i = 0, first = 0; i <= num_draws; i++) { 207bf215546Sopenharmony_ci if (i == num_draws || mode[i] != mode[first]) { 208bf215546Sopenharmony_ci info->mode = mode[first]; 209bf215546Sopenharmony_ci cso_multi_draw(cso, info, 0, &draws[first], i - first); 210bf215546Sopenharmony_ci first = i; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci /* We can pass the reference only once. st_buffer_object keeps 213bf215546Sopenharmony_ci * the reference alive for later draws. 214bf215546Sopenharmony_ci */ 215bf215546Sopenharmony_ci info->take_index_buffer_ownership = false; 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci} 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_cistatic void 221bf215546Sopenharmony_cirewrite_partial_stride_indirect(struct st_context *st, 222bf215546Sopenharmony_ci const struct pipe_draw_info *info, 223bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 224bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias draw) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci unsigned draw_count = 0; 227bf215546Sopenharmony_ci struct u_indirect_params *new_draws = util_draw_indirect_read(st->pipe, info, indirect, &draw_count); 228bf215546Sopenharmony_ci if (!new_draws) 229bf215546Sopenharmony_ci return; 230bf215546Sopenharmony_ci for (unsigned i = 0; i < draw_count; i++) 231bf215546Sopenharmony_ci cso_draw_vbo(st->cso_context, &new_draws[i].info, i, NULL, new_draws[i].draw); 232bf215546Sopenharmony_ci free(new_draws); 233bf215546Sopenharmony_ci} 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_civoid 236bf215546Sopenharmony_cist_indirect_draw_vbo(struct gl_context *ctx, 237bf215546Sopenharmony_ci GLuint mode, 238bf215546Sopenharmony_ci struct gl_buffer_object *indirect_data, 239bf215546Sopenharmony_ci GLsizeiptr indirect_offset, 240bf215546Sopenharmony_ci unsigned draw_count, 241bf215546Sopenharmony_ci unsigned stride, 242bf215546Sopenharmony_ci struct gl_buffer_object *indirect_draw_count, 243bf215546Sopenharmony_ci GLsizeiptr indirect_draw_count_offset, 244bf215546Sopenharmony_ci const struct _mesa_index_buffer *ib, 245bf215546Sopenharmony_ci bool primitive_restart, 246bf215546Sopenharmony_ci unsigned restart_index) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 249bf215546Sopenharmony_ci struct pipe_draw_info info; 250bf215546Sopenharmony_ci struct pipe_draw_indirect_info indirect; 251bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw = {0}; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci assert(stride); 254bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci memset(&indirect, 0, sizeof(indirect)); 257bf215546Sopenharmony_ci util_draw_init_info(&info); 258bf215546Sopenharmony_ci info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci if (ib) { 261bf215546Sopenharmony_ci struct gl_buffer_object *bufobj = ib->obj; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci /* indices are always in a real VBO */ 264bf215546Sopenharmony_ci assert(bufobj); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci info.index_size = 1 << ib->index_size_shift; 267bf215546Sopenharmony_ci info.index.resource = bufobj->buffer; 268bf215546Sopenharmony_ci draw.start = pointer_to_offset(ib->ptr) >> ib->index_size_shift; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci info.restart_index = restart_index; 271bf215546Sopenharmony_ci info.primitive_restart = primitive_restart; 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci info.mode = translate_prim(ctx, mode); 275bf215546Sopenharmony_ci indirect.buffer = indirect_data->buffer; 276bf215546Sopenharmony_ci indirect.offset = indirect_offset; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci /* Viewperf2020/Maya draws with a buffer that has no storage. */ 279bf215546Sopenharmony_ci if (!indirect.buffer) 280bf215546Sopenharmony_ci return; 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci if (!st->has_multi_draw_indirect) { 283bf215546Sopenharmony_ci int i; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci assert(!indirect_draw_count); 286bf215546Sopenharmony_ci indirect.draw_count = 1; 287bf215546Sopenharmony_ci for (i = 0; i < draw_count; i++) { 288bf215546Sopenharmony_ci cso_draw_vbo(st->cso_context, &info, i, &indirect, draw); 289bf215546Sopenharmony_ci indirect.offset += stride; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci } else { 292bf215546Sopenharmony_ci indirect.draw_count = draw_count; 293bf215546Sopenharmony_ci indirect.stride = stride; 294bf215546Sopenharmony_ci if (!st->has_indirect_partial_stride && stride && 295bf215546Sopenharmony_ci (draw_count > 1 || indirect_draw_count)) { 296bf215546Sopenharmony_ci /* DrawElementsIndirectCommand or DrawArraysIndirectCommand */ 297bf215546Sopenharmony_ci const size_t struct_size = info.index_size ? sizeof(uint32_t) * 5 : sizeof(uint32_t) * 4; 298bf215546Sopenharmony_ci if (indirect.stride && indirect.stride < struct_size) { 299bf215546Sopenharmony_ci rewrite_partial_stride_indirect(st, &info, &indirect, draw); 300bf215546Sopenharmony_ci return; 301bf215546Sopenharmony_ci } 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci if (indirect_draw_count) { 304bf215546Sopenharmony_ci indirect.indirect_draw_count = 305bf215546Sopenharmony_ci indirect_draw_count->buffer; 306bf215546Sopenharmony_ci indirect.indirect_draw_count_offset = indirect_draw_count_offset; 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci cso_draw_vbo(st->cso_context, &info, 0, &indirect, draw); 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci} 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_civoid 313bf215546Sopenharmony_cist_draw_transform_feedback(struct gl_context *ctx, GLenum mode, 314bf215546Sopenharmony_ci unsigned num_instances, unsigned stream, 315bf215546Sopenharmony_ci struct gl_transform_feedback_object *tfb_vertcount) 316bf215546Sopenharmony_ci{ 317bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 318bf215546Sopenharmony_ci struct pipe_draw_info info; 319bf215546Sopenharmony_ci struct pipe_draw_indirect_info indirect; 320bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw = {0}; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci memset(&indirect, 0, sizeof(indirect)); 325bf215546Sopenharmony_ci util_draw_init_info(&info); 326bf215546Sopenharmony_ci info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ 327bf215546Sopenharmony_ci info.mode = translate_prim(ctx, mode); 328bf215546Sopenharmony_ci info.instance_count = num_instances; 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci /* Transform feedback drawing is always non-indexed. */ 331bf215546Sopenharmony_ci /* Set info.count_from_stream_output. */ 332bf215546Sopenharmony_ci indirect.count_from_stream_output = tfb_vertcount->draw_count[stream]; 333bf215546Sopenharmony_ci if (indirect.count_from_stream_output == NULL) 334bf215546Sopenharmony_ci return; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci cso_draw_vbo(st->cso_context, &info, 0, &indirect, draw); 337bf215546Sopenharmony_ci} 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_cistatic void 340bf215546Sopenharmony_cist_draw_gallium_vertex_state(struct gl_context *ctx, 341bf215546Sopenharmony_ci struct pipe_vertex_state *state, 342bf215546Sopenharmony_ci struct pipe_draw_vertex_state_info info, 343bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 344bf215546Sopenharmony_ci const uint8_t *mode, 345bf215546Sopenharmony_ci unsigned num_draws, 346bf215546Sopenharmony_ci bool per_vertex_edgeflags) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 349bf215546Sopenharmony_ci bool old_vertdata_edgeflags = st->vertdata_edgeflags; 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci /* We don't flag any other states to make st_validate state update edge 352bf215546Sopenharmony_ci * flags, so we need to update them here. 353bf215546Sopenharmony_ci */ 354bf215546Sopenharmony_ci st_update_edgeflags(st, per_vertex_edgeflags); 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK_NO_VARRAYS, 357bf215546Sopenharmony_ci ST_PIPELINE_RENDER_NO_VARRAYS); 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 360bf215546Sopenharmony_ci uint32_t velem_mask = ctx->VertexProgram._Current->info.inputs_read; 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci if (!mode) { 363bf215546Sopenharmony_ci pipe->draw_vertex_state(pipe, state, velem_mask, info, draws, num_draws); 364bf215546Sopenharmony_ci } else { 365bf215546Sopenharmony_ci /* Find consecutive draws where mode doesn't vary. */ 366bf215546Sopenharmony_ci for (unsigned i = 0, first = 0; i <= num_draws; i++) { 367bf215546Sopenharmony_ci if (i == num_draws || mode[i] != mode[first]) { 368bf215546Sopenharmony_ci unsigned current_num_draws = i - first; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci /* Increase refcount to be able to use take_vertex_state_ownership 371bf215546Sopenharmony_ci * with all draws. 372bf215546Sopenharmony_ci */ 373bf215546Sopenharmony_ci if (i != num_draws && info.take_vertex_state_ownership) 374bf215546Sopenharmony_ci p_atomic_inc(&state->reference.count); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci info.mode = mode[first]; 377bf215546Sopenharmony_ci pipe->draw_vertex_state(pipe, state, velem_mask, info, &draws[first], 378bf215546Sopenharmony_ci current_num_draws); 379bf215546Sopenharmony_ci first = i; 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci } 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci /* If per-vertex edge flags are different than the non-display-list state, 385bf215546Sopenharmony_ci * just flag ST_NEW_VERTEX_ARRAY, which will also completely revalidate 386bf215546Sopenharmony_ci * edge flags in st_validate_state. 387bf215546Sopenharmony_ci */ 388bf215546Sopenharmony_ci if (st->vertdata_edgeflags != old_vertdata_edgeflags) { 389bf215546Sopenharmony_ci ctx->Array.NewVertexElements = true; 390bf215546Sopenharmony_ci st->dirty |= ST_NEW_VERTEX_ARRAYS; 391bf215546Sopenharmony_ci } 392bf215546Sopenharmony_ci} 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_civoid 395bf215546Sopenharmony_cist_init_draw_functions(struct pipe_screen *screen, 396bf215546Sopenharmony_ci struct dd_function_table *functions) 397bf215546Sopenharmony_ci{ 398bf215546Sopenharmony_ci functions->DrawGallium = st_draw_gallium; 399bf215546Sopenharmony_ci functions->DrawGalliumMultiMode = st_draw_gallium_multimode; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci if (screen->get_param(screen, PIPE_CAP_DRAW_VERTEX_STATE)) { 402bf215546Sopenharmony_ci functions->DrawGalliumVertexState = st_draw_gallium_vertex_state; 403bf215546Sopenharmony_ci functions->CreateGalliumVertexState = st_create_gallium_vertex_state; 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci} 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_civoid 409bf215546Sopenharmony_cist_destroy_draw(struct st_context *st) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci draw_destroy(st->draw); 412bf215546Sopenharmony_ci} 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci/** 415bf215546Sopenharmony_ci * Getter for the draw_context, so that initialization of it can happen only 416bf215546Sopenharmony_ci * when needed (the TGSI exec machines take up quite a bit of memory). 417bf215546Sopenharmony_ci */ 418bf215546Sopenharmony_cistruct draw_context * 419bf215546Sopenharmony_cist_get_draw_context(struct st_context *st) 420bf215546Sopenharmony_ci{ 421bf215546Sopenharmony_ci if (!st->draw) { 422bf215546Sopenharmony_ci st->draw = draw_create(st->pipe); 423bf215546Sopenharmony_ci if (!st->draw) { 424bf215546Sopenharmony_ci _mesa_error(st->ctx, GL_OUT_OF_MEMORY, "feedback fallback allocation"); 425bf215546Sopenharmony_ci return NULL; 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci /* Disable draw options that might convert points/lines to tris, etc. 430bf215546Sopenharmony_ci * as that would foul-up feedback/selection mode. 431bf215546Sopenharmony_ci */ 432bf215546Sopenharmony_ci draw_wide_line_threshold(st->draw, 1000.0f); 433bf215546Sopenharmony_ci draw_wide_point_threshold(st->draw, 1000.0f); 434bf215546Sopenharmony_ci draw_enable_line_stipple(st->draw, FALSE); 435bf215546Sopenharmony_ci draw_enable_point_sprites(st->draw, FALSE); 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci return st->draw; 438bf215546Sopenharmony_ci} 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci/** 441bf215546Sopenharmony_ci * Draw a quad with given position, texcoords and color. 442bf215546Sopenharmony_ci */ 443bf215546Sopenharmony_cibool 444bf215546Sopenharmony_cist_draw_quad(struct st_context *st, 445bf215546Sopenharmony_ci float x0, float y0, float x1, float y1, float z, 446bf215546Sopenharmony_ci float s0, float t0, float s1, float t1, 447bf215546Sopenharmony_ci const float *color, 448bf215546Sopenharmony_ci unsigned num_instances) 449bf215546Sopenharmony_ci{ 450bf215546Sopenharmony_ci struct pipe_vertex_buffer vb = {0}; 451bf215546Sopenharmony_ci struct st_util_vertex *verts; 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci vb.stride = sizeof(struct st_util_vertex); 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci u_upload_alloc(st->pipe->stream_uploader, 0, 456bf215546Sopenharmony_ci 4 * sizeof(struct st_util_vertex), 4, 457bf215546Sopenharmony_ci &vb.buffer_offset, &vb.buffer.resource, (void **) &verts); 458bf215546Sopenharmony_ci if (!vb.buffer.resource) { 459bf215546Sopenharmony_ci return false; 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci /* lower-left */ 463bf215546Sopenharmony_ci verts[0].x = x0; 464bf215546Sopenharmony_ci verts[0].y = y1; 465bf215546Sopenharmony_ci verts[0].z = z; 466bf215546Sopenharmony_ci verts[0].r = color[0]; 467bf215546Sopenharmony_ci verts[0].g = color[1]; 468bf215546Sopenharmony_ci verts[0].b = color[2]; 469bf215546Sopenharmony_ci verts[0].a = color[3]; 470bf215546Sopenharmony_ci verts[0].s = s0; 471bf215546Sopenharmony_ci verts[0].t = t0; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci /* lower-right */ 474bf215546Sopenharmony_ci verts[1].x = x1; 475bf215546Sopenharmony_ci verts[1].y = y1; 476bf215546Sopenharmony_ci verts[1].z = z; 477bf215546Sopenharmony_ci verts[1].r = color[0]; 478bf215546Sopenharmony_ci verts[1].g = color[1]; 479bf215546Sopenharmony_ci verts[1].b = color[2]; 480bf215546Sopenharmony_ci verts[1].a = color[3]; 481bf215546Sopenharmony_ci verts[1].s = s1; 482bf215546Sopenharmony_ci verts[1].t = t0; 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci /* upper-right */ 485bf215546Sopenharmony_ci verts[2].x = x1; 486bf215546Sopenharmony_ci verts[2].y = y0; 487bf215546Sopenharmony_ci verts[2].z = z; 488bf215546Sopenharmony_ci verts[2].r = color[0]; 489bf215546Sopenharmony_ci verts[2].g = color[1]; 490bf215546Sopenharmony_ci verts[2].b = color[2]; 491bf215546Sopenharmony_ci verts[2].a = color[3]; 492bf215546Sopenharmony_ci verts[2].s = s1; 493bf215546Sopenharmony_ci verts[2].t = t1; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci /* upper-left */ 496bf215546Sopenharmony_ci verts[3].x = x0; 497bf215546Sopenharmony_ci verts[3].y = y0; 498bf215546Sopenharmony_ci verts[3].z = z; 499bf215546Sopenharmony_ci verts[3].r = color[0]; 500bf215546Sopenharmony_ci verts[3].g = color[1]; 501bf215546Sopenharmony_ci verts[3].b = color[2]; 502bf215546Sopenharmony_ci verts[3].a = color[3]; 503bf215546Sopenharmony_ci verts[3].s = s0; 504bf215546Sopenharmony_ci verts[3].t = t1; 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci u_upload_unmap(st->pipe->stream_uploader); 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci cso_set_vertex_buffers(st->cso_context, 0, 1, 0, false, &vb); 509bf215546Sopenharmony_ci st->last_num_vbuffers = MAX2(st->last_num_vbuffers, 1); 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci if (num_instances > 1) { 512bf215546Sopenharmony_ci cso_draw_arrays_instanced(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4, 513bf215546Sopenharmony_ci 0, num_instances); 514bf215546Sopenharmony_ci } else { 515bf215546Sopenharmony_ci cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4); 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci pipe_resource_reference(&vb.buffer.resource, NULL); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci return true; 521bf215546Sopenharmony_ci} 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_cistatic void 524bf215546Sopenharmony_cist_hw_select_draw_gallium(struct gl_context *ctx, 525bf215546Sopenharmony_ci struct pipe_draw_info *info, 526bf215546Sopenharmony_ci unsigned drawid_offset, 527bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 528bf215546Sopenharmony_ci unsigned num_draws) 529bf215546Sopenharmony_ci{ 530bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) 535bf215546Sopenharmony_ci return; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci if (!st_draw_hw_select_prepare_common(ctx) || 538bf215546Sopenharmony_ci !st_draw_hw_select_prepare_mode(ctx, info)) 539bf215546Sopenharmony_ci return; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci cso_multi_draw(st->cso_context, info, drawid_offset, draws, num_draws); 542bf215546Sopenharmony_ci} 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_cistatic void 545bf215546Sopenharmony_cist_hw_select_draw_gallium_multimode(struct gl_context *ctx, 546bf215546Sopenharmony_ci struct pipe_draw_info *info, 547bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 548bf215546Sopenharmony_ci const unsigned char *mode, 549bf215546Sopenharmony_ci unsigned num_draws) 550bf215546Sopenharmony_ci{ 551bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) 556bf215546Sopenharmony_ci return; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci if (!st_draw_hw_select_prepare_common(ctx)) 559bf215546Sopenharmony_ci return; 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci unsigned i, first; 562bf215546Sopenharmony_ci struct cso_context *cso = st->cso_context; 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci /* Find consecutive draws where mode doesn't vary. */ 565bf215546Sopenharmony_ci for (i = 0, first = 0; i <= num_draws; i++) { 566bf215546Sopenharmony_ci if (i == num_draws || mode[i] != mode[first]) { 567bf215546Sopenharmony_ci info->mode = mode[first]; 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci if (st_draw_hw_select_prepare_mode(ctx, info)) 570bf215546Sopenharmony_ci cso_multi_draw(cso, info, 0, &draws[first], i - first); 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci first = i; 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci /* We can pass the reference only once. st_buffer_object keeps 575bf215546Sopenharmony_ci * the reference alive for later draws. 576bf215546Sopenharmony_ci */ 577bf215546Sopenharmony_ci info->take_index_buffer_ownership = false; 578bf215546Sopenharmony_ci } 579bf215546Sopenharmony_ci } 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_civoid 583bf215546Sopenharmony_cist_init_hw_select_draw_functions(struct pipe_screen *screen, 584bf215546Sopenharmony_ci struct dd_function_table *functions) 585bf215546Sopenharmony_ci{ 586bf215546Sopenharmony_ci functions->DrawGallium = st_hw_select_draw_gallium; 587bf215546Sopenharmony_ci functions->DrawGalliumMultiMode = st_hw_select_draw_gallium_multimode; 588bf215546Sopenharmony_ci} 589