14a49301eSmrg/************************************************************************** 2af69d88dSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 5af69d88dSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 13af69d88dSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 17af69d88dSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25af69d88dSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg/* 294a49301eSmrg * This file implements the st_draw_vbo() function which is called from 304a49301eSmrg * Mesa's VBO module. All point/line/triangle rendering is done through 314a49301eSmrg * this function whether the user called glBegin/End, glDrawArrays, 324a49301eSmrg * glDrawElements, glEvalMesh, or glCalList, etc. 334a49301eSmrg * 344a49301eSmrg * Authors: 35af69d88dSmrg * Keith Whitwell <keithw@vmware.com> 364a49301eSmrg */ 374a49301eSmrg 384a49301eSmrg 3901e04c3fSmrg#include "main/errors.h" 407ec681f3Smrg 414a49301eSmrg#include "main/image.h" 423464ebd5Sriastradh#include "main/bufferobj.h" 434a49301eSmrg#include "main/macros.h" 4401e04c3fSmrg#include "main/varray.h" 4501e04c3fSmrg 4601e04c3fSmrg#include "compiler/glsl/ir_uniform.h" 474a49301eSmrg 484a49301eSmrg#include "vbo/vbo.h" 494a49301eSmrg 504a49301eSmrg#include "st_context.h" 514a49301eSmrg#include "st_atom.h" 5201e04c3fSmrg#include "st_cb_bitmap.h" 534a49301eSmrg#include "st_cb_bufferobjects.h" 54af69d88dSmrg#include "st_cb_xformfb.h" 55af69d88dSmrg#include "st_debug.h" 564a49301eSmrg#include "st_draw.h" 574a49301eSmrg#include "st_program.h" 58b9abf16eSmaya#include "st_util.h" 594a49301eSmrg 604a49301eSmrg#include "pipe/p_context.h" 614a49301eSmrg#include "pipe/p_defines.h" 62b9abf16eSmaya#include "util/u_cpu_detect.h" 63cdc920a0Smrg#include "util/u_inlines.h" 647ec681f3Smrg#include "util/format/u_format.h" 653464ebd5Sriastradh#include "util/u_prim.h" 6601e04c3fSmrg#include "util/u_draw.h" 67af69d88dSmrg#include "util/u_upload_mgr.h" 687ec681f3Smrg#include "util/u_threaded_context.h" 693464ebd5Sriastradh#include "draw/draw_context.h" 703464ebd5Sriastradh#include "cso_cache/cso_context.h" 714a49301eSmrg 724a49301eSmrg 733464ebd5Sriastradh/** 743464ebd5Sriastradh * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to 753464ebd5Sriastradh * the corresponding Gallium type. 763464ebd5Sriastradh */ 773464ebd5Sriastradhstatic unsigned 783464ebd5Sriastradhtranslate_prim(const struct gl_context *ctx, unsigned prim) 79cdc920a0Smrg{ 803464ebd5Sriastradh /* GL prims should match Gallium prims, spot-check a few */ 81af69d88dSmrg STATIC_ASSERT(GL_POINTS == PIPE_PRIM_POINTS); 82af69d88dSmrg STATIC_ASSERT(GL_QUADS == PIPE_PRIM_QUADS); 83af69d88dSmrg STATIC_ASSERT(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 8401e04c3fSmrg STATIC_ASSERT(GL_PATCHES == PIPE_PRIM_PATCHES); 85cdc920a0Smrg 86cdc920a0Smrg return prim; 87cdc920a0Smrg} 88cdc920a0Smrg 8901e04c3fSmrgstatic inline void 907ec681f3Smrgprepare_draw(struct st_context *st, struct gl_context *ctx, uint64_t state_mask, 917ec681f3Smrg enum st_pipeline pipeline) 9201e04c3fSmrg{ 9301e04c3fSmrg /* Mesa core state should have been validated already */ 9401e04c3fSmrg assert(ctx->NewState == 0x0); 9501e04c3fSmrg 9601e04c3fSmrg if (unlikely(!st->bitmap.cache.empty)) 9701e04c3fSmrg st_flush_bitmap_cache(st); 9801e04c3fSmrg 9901e04c3fSmrg st_invalidate_readpix_cache(st); 10001e04c3fSmrg 10101e04c3fSmrg /* Validate state. */ 1027ec681f3Smrg if ((st->dirty | ctx->NewDriverState) & st->active_states & state_mask || 10301e04c3fSmrg st->gfx_shaders_may_be_dirty) { 1047ec681f3Smrg st_validate_state(st, pipeline); 10501e04c3fSmrg } 106b9abf16eSmaya 107b9abf16eSmaya /* Pin threads regularly to the same Zen CCX that the main thread is 108b9abf16eSmaya * running on. The main thread can move between CCXs. 109b9abf16eSmaya */ 1107ec681f3Smrg if (unlikely(st->pin_thread_counter != ST_L3_PINNING_DISABLED && 111b9abf16eSmaya /* no glthread */ 112b9abf16eSmaya ctx->CurrentClientDispatch != ctx->MarshalExec && 113b9abf16eSmaya /* do it occasionally */ 114b9abf16eSmaya ++st->pin_thread_counter % 512 == 0)) { 1157ec681f3Smrg st->pin_thread_counter = 0; 1167ec681f3Smrg 1177ec681f3Smrg int cpu = util_get_current_cpu(); 118b9abf16eSmaya if (cpu >= 0) { 1197ec681f3Smrg struct pipe_context *pipe = st->pipe; 1207ec681f3Smrg uint16_t L3_cache = util_get_cpu_caps()->cpu_to_L3[cpu]; 1217ec681f3Smrg 1227ec681f3Smrg if (L3_cache != U_CPU_INVALID_L3) { 1237ec681f3Smrg pipe->set_context_param(pipe, 1247ec681f3Smrg PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE, 1257ec681f3Smrg L3_cache); 1267ec681f3Smrg } 1277ec681f3Smrg } 1287ec681f3Smrg } 1297ec681f3Smrg} 1307ec681f3Smrg 1317ec681f3Smrgstatic bool ALWAYS_INLINE 1327ec681f3Smrgprepare_indexed_draw(/* pass both st and ctx to reduce dereferences */ 1337ec681f3Smrg struct st_context *st, 1347ec681f3Smrg struct gl_context *ctx, 1357ec681f3Smrg struct pipe_draw_info *info, 1367ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 1377ec681f3Smrg unsigned num_draws) 1387ec681f3Smrg{ 1397ec681f3Smrg if (info->index_size) { 1407ec681f3Smrg /* Get index bounds for user buffers. */ 1417ec681f3Smrg if (!info->index_bounds_valid && 1427ec681f3Smrg st->draw_needs_minmax_index) { 1437ec681f3Smrg /* Return if this fails, which means all draws have count == 0. */ 1447ec681f3Smrg if (!vbo_get_minmax_indices_gallium(ctx, info, draws, num_draws)) 1457ec681f3Smrg return false; 146b9abf16eSmaya 1477ec681f3Smrg info->index_bounds_valid = true; 1487ec681f3Smrg } 1497ec681f3Smrg 1507ec681f3Smrg if (!info->has_user_indices) { 1517ec681f3Smrg if (st->pipe->draw_vbo == tc_draw_vbo) { 1527ec681f3Smrg /* Fast path for u_threaded_context. This eliminates the atomic 1537ec681f3Smrg * increment for the index buffer refcount when adding it into 1547ec681f3Smrg * the threaded batch buffer. 1557ec681f3Smrg */ 1567ec681f3Smrg info->index.resource = 1577ec681f3Smrg st_get_buffer_reference(ctx, info->index.gl_bo); 1587ec681f3Smrg info->take_index_buffer_ownership = true; 1597ec681f3Smrg } else { 1607ec681f3Smrg info->index.resource = st_buffer_object(info->index.gl_bo)->buffer; 1617ec681f3Smrg } 1627ec681f3Smrg 1637ec681f3Smrg /* Return if the bound element array buffer doesn't have any backing 1647ec681f3Smrg * storage. (nothing to do) 1657ec681f3Smrg */ 1667ec681f3Smrg if (unlikely(!info->index.resource)) 1677ec681f3Smrg return false; 168b9abf16eSmaya } 169b9abf16eSmaya } 1707ec681f3Smrg return true; 17101e04c3fSmrg} 1723464ebd5Sriastradh 17301e04c3fSmrgstatic void 1747ec681f3Smrgst_draw_gallium(struct gl_context *ctx, 1757ec681f3Smrg struct pipe_draw_info *info, 1767ec681f3Smrg unsigned drawid_offset, 1777ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 1787ec681f3Smrg unsigned num_draws) 1793464ebd5Sriastradh{ 1803464ebd5Sriastradh struct st_context *st = st_context(ctx); 1813464ebd5Sriastradh 1827ec681f3Smrg prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 1834a49301eSmrg 1847ec681f3Smrg if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) 1857ec681f3Smrg return; 186af69d88dSmrg 1877ec681f3Smrg cso_multi_draw(st->cso_context, info, drawid_offset, draws, num_draws); 1887ec681f3Smrg} 18901e04c3fSmrg 1907ec681f3Smrgstatic void 1917ec681f3Smrgst_draw_gallium_multimode(struct gl_context *ctx, 1927ec681f3Smrg struct pipe_draw_info *info, 1937ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 1947ec681f3Smrg const unsigned char *mode, 1957ec681f3Smrg unsigned num_draws) 1967ec681f3Smrg{ 1977ec681f3Smrg struct st_context *st = st_context(ctx); 198af69d88dSmrg 1997ec681f3Smrg prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 20001e04c3fSmrg 2017ec681f3Smrg if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) 2027ec681f3Smrg return; 20301e04c3fSmrg 2047ec681f3Smrg unsigned i, first; 2057ec681f3Smrg struct cso_context *cso = st->cso_context; 206af69d88dSmrg 2077ec681f3Smrg /* Find consecutive draws where mode doesn't vary. */ 2087ec681f3Smrg for (i = 0, first = 0; i <= num_draws; i++) { 2097ec681f3Smrg if (i == num_draws || mode[i] != mode[first]) { 2107ec681f3Smrg info->mode = mode[first]; 2117ec681f3Smrg cso_multi_draw(cso, info, 0, &draws[first], i - first); 2127ec681f3Smrg first = i; 213af69d88dSmrg 2147ec681f3Smrg /* We can pass the reference only once. st_buffer_object keeps 2157ec681f3Smrg * the reference alive for later draws. 2167ec681f3Smrg */ 2177ec681f3Smrg info->take_index_buffer_ownership = false; 218af69d88dSmrg } 21901e04c3fSmrg } 22001e04c3fSmrg} 22101e04c3fSmrg 22201e04c3fSmrgstatic void 22301e04c3fSmrgst_indirect_draw_vbo(struct gl_context *ctx, 22401e04c3fSmrg GLuint mode, 22501e04c3fSmrg struct gl_buffer_object *indirect_data, 22601e04c3fSmrg GLsizeiptr indirect_offset, 22701e04c3fSmrg unsigned draw_count, 22801e04c3fSmrg unsigned stride, 22901e04c3fSmrg struct gl_buffer_object *indirect_draw_count, 23001e04c3fSmrg GLsizeiptr indirect_draw_count_offset, 2317ec681f3Smrg const struct _mesa_index_buffer *ib, 2327ec681f3Smrg bool primitive_restart, 2337ec681f3Smrg unsigned restart_index) 23401e04c3fSmrg{ 23501e04c3fSmrg struct st_context *st = st_context(ctx); 23601e04c3fSmrg struct pipe_draw_info info; 23701e04c3fSmrg struct pipe_draw_indirect_info indirect; 2387ec681f3Smrg struct pipe_draw_start_count_bias draw = {0}; 23901e04c3fSmrg 24001e04c3fSmrg assert(stride); 2417ec681f3Smrg prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 24201e04c3fSmrg 24301e04c3fSmrg memset(&indirect, 0, sizeof(indirect)); 24401e04c3fSmrg util_draw_init_info(&info); 24501e04c3fSmrg info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ 24601e04c3fSmrg 24701e04c3fSmrg if (ib) { 24801e04c3fSmrg struct gl_buffer_object *bufobj = ib->obj; 24901e04c3fSmrg 25001e04c3fSmrg /* indices are always in a real VBO */ 2517ec681f3Smrg assert(bufobj); 25201e04c3fSmrg 2537ec681f3Smrg info.index_size = 1 << ib->index_size_shift; 25401e04c3fSmrg info.index.resource = st_buffer_object(bufobj)->buffer; 2557ec681f3Smrg draw.start = pointer_to_offset(ib->ptr) >> ib->index_size_shift; 25601e04c3fSmrg 2577ec681f3Smrg info.restart_index = restart_index; 2587ec681f3Smrg info.primitive_restart = primitive_restart; 25901e04c3fSmrg } 26001e04c3fSmrg 26101e04c3fSmrg info.mode = translate_prim(ctx, mode); 26201e04c3fSmrg indirect.buffer = st_buffer_object(indirect_data)->buffer; 26301e04c3fSmrg indirect.offset = indirect_offset; 26401e04c3fSmrg 2657ec681f3Smrg /* Viewperf2020/Maya draws with a buffer that has no storage. */ 2667ec681f3Smrg if (!indirect.buffer) 2677ec681f3Smrg return; 26801e04c3fSmrg 26901e04c3fSmrg if (!st->has_multi_draw_indirect) { 27001e04c3fSmrg int i; 27101e04c3fSmrg 27201e04c3fSmrg assert(!indirect_draw_count); 27301e04c3fSmrg indirect.draw_count = 1; 27401e04c3fSmrg for (i = 0; i < draw_count; i++) { 2757ec681f3Smrg cso_draw_vbo(st->cso_context, &info, i, &indirect, draw); 27601e04c3fSmrg indirect.offset += stride; 277af69d88dSmrg } 27801e04c3fSmrg } else { 27901e04c3fSmrg indirect.draw_count = draw_count; 28001e04c3fSmrg indirect.stride = stride; 28101e04c3fSmrg if (indirect_draw_count) { 28201e04c3fSmrg indirect.indirect_draw_count = 28301e04c3fSmrg st_buffer_object(indirect_draw_count)->buffer; 28401e04c3fSmrg indirect.indirect_draw_count_offset = indirect_draw_count_offset; 285af69d88dSmrg } 2867ec681f3Smrg cso_draw_vbo(st->cso_context, &info, 0, &indirect, draw); 287af69d88dSmrg } 2884a49301eSmrg} 2894a49301eSmrg 2907ec681f3Smrgstatic void 2917ec681f3Smrgst_draw_transform_feedback(struct gl_context *ctx, GLenum mode, 2927ec681f3Smrg unsigned num_instances, unsigned stream, 2937ec681f3Smrg struct gl_transform_feedback_object *tfb_vertcount) 2947ec681f3Smrg{ 2957ec681f3Smrg struct st_context *st = st_context(ctx); 2967ec681f3Smrg struct pipe_draw_info info; 2977ec681f3Smrg struct pipe_draw_indirect_info indirect; 2987ec681f3Smrg struct pipe_draw_start_count_bias draw = {0}; 2997ec681f3Smrg 3007ec681f3Smrg prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK, ST_PIPELINE_RENDER); 3017ec681f3Smrg 3027ec681f3Smrg memset(&indirect, 0, sizeof(indirect)); 3037ec681f3Smrg util_draw_init_info(&info); 3047ec681f3Smrg info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ 3057ec681f3Smrg info.mode = translate_prim(ctx, mode); 3067ec681f3Smrg info.instance_count = num_instances; 3077ec681f3Smrg 3087ec681f3Smrg /* Transform feedback drawing is always non-indexed. */ 3097ec681f3Smrg /* Set info.count_from_stream_output. */ 3107ec681f3Smrg if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &indirect)) 3117ec681f3Smrg return; 3127ec681f3Smrg 3137ec681f3Smrg cso_draw_vbo(st->cso_context, &info, 0, &indirect, draw); 3147ec681f3Smrg} 3157ec681f3Smrg 3167ec681f3Smrgstatic void 3177ec681f3Smrgst_draw_gallium_vertex_state(struct gl_context *ctx, 3187ec681f3Smrg struct pipe_vertex_state *state, 3197ec681f3Smrg struct pipe_draw_vertex_state_info info, 3207ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 3217ec681f3Smrg const uint8_t *mode, 3227ec681f3Smrg unsigned num_draws, 3237ec681f3Smrg bool per_vertex_edgeflags) 3247ec681f3Smrg{ 3257ec681f3Smrg struct st_context *st = st_context(ctx); 3267ec681f3Smrg bool old_vertdata_edgeflags = st->vertdata_edgeflags; 3277ec681f3Smrg 3287ec681f3Smrg /* We don't flag any other states to make st_validate state update edge 3297ec681f3Smrg * flags, so we need to update them here. 3307ec681f3Smrg */ 3317ec681f3Smrg st_update_edgeflags(st, per_vertex_edgeflags); 3327ec681f3Smrg 3337ec681f3Smrg prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK_NO_VARRAYS, 3347ec681f3Smrg ST_PIPELINE_RENDER_NO_VARRAYS); 3357ec681f3Smrg 3367ec681f3Smrg struct pipe_context *pipe = st->pipe; 3377ec681f3Smrg uint32_t velem_mask = ctx->VertexProgram._Current->info.inputs_read; 3387ec681f3Smrg 3397ec681f3Smrg if (!mode) { 3407ec681f3Smrg pipe->draw_vertex_state(pipe, state, velem_mask, info, draws, num_draws); 3417ec681f3Smrg } else { 3427ec681f3Smrg /* Find consecutive draws where mode doesn't vary. */ 3437ec681f3Smrg for (unsigned i = 0, first = 0; i <= num_draws; i++) { 3447ec681f3Smrg if (i == num_draws || mode[i] != mode[first]) { 3457ec681f3Smrg unsigned current_num_draws = i - first; 3467ec681f3Smrg 3477ec681f3Smrg /* Increase refcount to be able to use take_vertex_state_ownership 3487ec681f3Smrg * with all draws. 3497ec681f3Smrg */ 3507ec681f3Smrg if (i != num_draws && info.take_vertex_state_ownership) 3517ec681f3Smrg p_atomic_inc(&state->reference.count); 3527ec681f3Smrg 3537ec681f3Smrg info.mode = mode[first]; 3547ec681f3Smrg pipe->draw_vertex_state(pipe, state, velem_mask, info, &draws[first], 3557ec681f3Smrg current_num_draws); 3567ec681f3Smrg first = i; 3577ec681f3Smrg } 3587ec681f3Smrg } 3597ec681f3Smrg } 3607ec681f3Smrg 3617ec681f3Smrg /* If per-vertex edge flags are different than the non-display-list state, 3627ec681f3Smrg * just flag ST_NEW_VERTEX_ARRAY, which will also completely revalidate 3637ec681f3Smrg * edge flags in st_validate_state. 3647ec681f3Smrg */ 3657ec681f3Smrg if (st->vertdata_edgeflags != old_vertdata_edgeflags) 3667ec681f3Smrg st->dirty |= ST_NEW_VERTEX_ARRAYS; 3677ec681f3Smrg} 3684a49301eSmrg 3693464ebd5Sriastradhvoid 3707ec681f3Smrgst_init_draw_functions(struct pipe_screen *screen, 3717ec681f3Smrg struct dd_function_table *functions) 3724a49301eSmrg{ 3737ec681f3Smrg functions->Draw = NULL; 3747ec681f3Smrg functions->DrawGallium = st_draw_gallium; 3757ec681f3Smrg functions->DrawGalliumMultiMode = st_draw_gallium_multimode; 37601e04c3fSmrg functions->DrawIndirect = st_indirect_draw_vbo; 3777ec681f3Smrg functions->DrawTransformFeedback = st_draw_transform_feedback; 3787ec681f3Smrg 3797ec681f3Smrg if (screen->get_param(screen, PIPE_CAP_DRAW_VERTEX_STATE)) { 3807ec681f3Smrg functions->DrawGalliumVertexState = st_draw_gallium_vertex_state; 3817ec681f3Smrg functions->CreateGalliumVertexState = st_create_gallium_vertex_state; 3827ec681f3Smrg } 38301e04c3fSmrg} 3844a49301eSmrg 3854a49301eSmrg 38601e04c3fSmrgvoid 38701e04c3fSmrgst_destroy_draw(struct st_context *st) 38801e04c3fSmrg{ 38901e04c3fSmrg draw_destroy(st->draw); 39001e04c3fSmrg} 39101e04c3fSmrg 39201e04c3fSmrg/** 39301e04c3fSmrg * Getter for the draw_context, so that initialization of it can happen only 39401e04c3fSmrg * when needed (the TGSI exec machines take up quite a bit of memory). 39501e04c3fSmrg */ 39601e04c3fSmrgstruct draw_context * 39701e04c3fSmrgst_get_draw_context(struct st_context *st) 39801e04c3fSmrg{ 39901e04c3fSmrg if (!st->draw) { 40001e04c3fSmrg st->draw = draw_create(st->pipe); 40101e04c3fSmrg if (!st->draw) { 40201e04c3fSmrg _mesa_error(st->ctx, GL_OUT_OF_MEMORY, "feedback fallback allocation"); 40301e04c3fSmrg return NULL; 40401e04c3fSmrg } 40501e04c3fSmrg } 4064a49301eSmrg 4073464ebd5Sriastradh /* Disable draw options that might convert points/lines to tris, etc. 4083464ebd5Sriastradh * as that would foul-up feedback/selection mode. 4093464ebd5Sriastradh */ 4103464ebd5Sriastradh draw_wide_line_threshold(st->draw, 1000.0f); 4113464ebd5Sriastradh draw_wide_point_threshold(st->draw, 1000.0f); 4123464ebd5Sriastradh draw_enable_line_stipple(st->draw, FALSE); 4133464ebd5Sriastradh draw_enable_point_sprites(st->draw, FALSE); 4144a49301eSmrg 41501e04c3fSmrg return st->draw; 41601e04c3fSmrg} 4174a49301eSmrg 41801e04c3fSmrg/** 41901e04c3fSmrg * Draw a quad with given position, texcoords and color. 42001e04c3fSmrg */ 42101e04c3fSmrgbool 42201e04c3fSmrgst_draw_quad(struct st_context *st, 42301e04c3fSmrg float x0, float y0, float x1, float y1, float z, 42401e04c3fSmrg float s0, float t0, float s1, float t1, 42501e04c3fSmrg const float *color, 42601e04c3fSmrg unsigned num_instances) 4273464ebd5Sriastradh{ 42801e04c3fSmrg struct pipe_vertex_buffer vb = {0}; 42901e04c3fSmrg struct st_util_vertex *verts; 43001e04c3fSmrg 43101e04c3fSmrg vb.stride = sizeof(struct st_util_vertex); 43201e04c3fSmrg 43301e04c3fSmrg u_upload_alloc(st->pipe->stream_uploader, 0, 43401e04c3fSmrg 4 * sizeof(struct st_util_vertex), 4, 43501e04c3fSmrg &vb.buffer_offset, &vb.buffer.resource, (void **) &verts); 43601e04c3fSmrg if (!vb.buffer.resource) { 43701e04c3fSmrg return false; 43801e04c3fSmrg } 43901e04c3fSmrg 44001e04c3fSmrg /* lower-left */ 44101e04c3fSmrg verts[0].x = x0; 44201e04c3fSmrg verts[0].y = y1; 44301e04c3fSmrg verts[0].z = z; 44401e04c3fSmrg verts[0].r = color[0]; 44501e04c3fSmrg verts[0].g = color[1]; 44601e04c3fSmrg verts[0].b = color[2]; 44701e04c3fSmrg verts[0].a = color[3]; 44801e04c3fSmrg verts[0].s = s0; 44901e04c3fSmrg verts[0].t = t0; 45001e04c3fSmrg 45101e04c3fSmrg /* lower-right */ 45201e04c3fSmrg verts[1].x = x1; 45301e04c3fSmrg verts[1].y = y1; 45401e04c3fSmrg verts[1].z = z; 45501e04c3fSmrg verts[1].r = color[0]; 45601e04c3fSmrg verts[1].g = color[1]; 45701e04c3fSmrg verts[1].b = color[2]; 45801e04c3fSmrg verts[1].a = color[3]; 45901e04c3fSmrg verts[1].s = s1; 46001e04c3fSmrg verts[1].t = t0; 46101e04c3fSmrg 46201e04c3fSmrg /* upper-right */ 46301e04c3fSmrg verts[2].x = x1; 46401e04c3fSmrg verts[2].y = y0; 46501e04c3fSmrg verts[2].z = z; 46601e04c3fSmrg verts[2].r = color[0]; 46701e04c3fSmrg verts[2].g = color[1]; 46801e04c3fSmrg verts[2].b = color[2]; 46901e04c3fSmrg verts[2].a = color[3]; 47001e04c3fSmrg verts[2].s = s1; 47101e04c3fSmrg verts[2].t = t1; 47201e04c3fSmrg 47301e04c3fSmrg /* upper-left */ 47401e04c3fSmrg verts[3].x = x0; 47501e04c3fSmrg verts[3].y = y0; 47601e04c3fSmrg verts[3].z = z; 47701e04c3fSmrg verts[3].r = color[0]; 47801e04c3fSmrg verts[3].g = color[1]; 47901e04c3fSmrg verts[3].b = color[2]; 48001e04c3fSmrg verts[3].a = color[3]; 48101e04c3fSmrg verts[3].s = s0; 48201e04c3fSmrg verts[3].t = t1; 48301e04c3fSmrg 48401e04c3fSmrg u_upload_unmap(st->pipe->stream_uploader); 48501e04c3fSmrg 48601e04c3fSmrg cso_set_vertex_buffers(st->cso_context, 0, 1, &vb); 4877ec681f3Smrg st->last_num_vbuffers = MAX2(st->last_num_vbuffers, 1); 48801e04c3fSmrg 48901e04c3fSmrg if (num_instances > 1) { 49001e04c3fSmrg cso_draw_arrays_instanced(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4, 49101e04c3fSmrg 0, num_instances); 49201e04c3fSmrg } else { 49301e04c3fSmrg cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4); 49401e04c3fSmrg } 49501e04c3fSmrg 49601e04c3fSmrg pipe_resource_reference(&vb.buffer.resource, NULL); 49701e04c3fSmrg 49801e04c3fSmrg return true; 4993464ebd5Sriastradh} 500