1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2007 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg/* 29848b8605Smrg * This file implements the st_draw_vbo() function which is called from 30848b8605Smrg * Mesa's VBO module. All point/line/triangle rendering is done through 31848b8605Smrg * this function whether the user called glBegin/End, glDrawArrays, 32848b8605Smrg * glDrawElements, glEvalMesh, or glCalList, etc. 33848b8605Smrg * 34848b8605Smrg * Authors: 35848b8605Smrg * Keith Whitwell <keithw@vmware.com> 36848b8605Smrg */ 37848b8605Smrg 38848b8605Smrg 39b8e80941Smrg#include "main/errors.h" 40848b8605Smrg#include "main/imports.h" 41848b8605Smrg#include "main/image.h" 42848b8605Smrg#include "main/bufferobj.h" 43848b8605Smrg#include "main/macros.h" 44b8e80941Smrg#include "main/varray.h" 45b8e80941Smrg 46b8e80941Smrg#include "compiler/glsl/ir_uniform.h" 47848b8605Smrg 48848b8605Smrg#include "vbo/vbo.h" 49848b8605Smrg 50848b8605Smrg#include "st_context.h" 51848b8605Smrg#include "st_atom.h" 52b8e80941Smrg#include "st_cb_bitmap.h" 53848b8605Smrg#include "st_cb_bufferobjects.h" 54848b8605Smrg#include "st_cb_xformfb.h" 55848b8605Smrg#include "st_debug.h" 56848b8605Smrg#include "st_draw.h" 57848b8605Smrg#include "st_program.h" 58b8e80941Smrg#include "st_util.h" 59848b8605Smrg 60848b8605Smrg#include "pipe/p_context.h" 61848b8605Smrg#include "pipe/p_defines.h" 62b8e80941Smrg#include "util/u_cpu_detect.h" 63848b8605Smrg#include "util/u_inlines.h" 64848b8605Smrg#include "util/u_format.h" 65848b8605Smrg#include "util/u_prim.h" 66b8e80941Smrg#include "util/u_draw.h" 67848b8605Smrg#include "util/u_upload_mgr.h" 68848b8605Smrg#include "draw/draw_context.h" 69848b8605Smrg#include "cso_cache/cso_context.h" 70848b8605Smrg 71b8e80941Smrg#if defined(PIPE_OS_LINUX) && !defined(ANDROID) 72b8e80941Smrg#include <sched.h> 73b8e80941Smrg#define HAVE_SCHED_GETCPU 1 74b8e80941Smrg#else 75b8e80941Smrg#define sched_getcpu() 0 76b8e80941Smrg#define HAVE_SCHED_GETCPU 0 77b8e80941Smrg#endif 78848b8605Smrg 79848b8605Smrg/** 80b8e80941Smrg * Set the restart index. 81848b8605Smrg */ 82b8e80941Smrgstatic void 83b8e80941Smrgsetup_primitive_restart(struct gl_context *ctx, struct pipe_draw_info *info) 84848b8605Smrg{ 85b8e80941Smrg if (ctx->Array._PrimitiveRestart) { 86b8e80941Smrg unsigned index_size = info->index_size; 87848b8605Smrg 88b8e80941Smrg info->restart_index = 89b8e80941Smrg _mesa_primitive_restart_index(ctx, index_size); 90848b8605Smrg 91b8e80941Smrg /* Enable primitive restart only when the restart index can have an 92b8e80941Smrg * effect. This is required for correctness in radeonsi VI support. 93b8e80941Smrg * Other hardware may also benefit from taking a faster, non-restart path 94b8e80941Smrg * when possible. 95b8e80941Smrg */ 96b8e80941Smrg if (index_size == 4 || info->restart_index < (1 << (index_size * 8))) 97b8e80941Smrg info->primitive_restart = true; 98848b8605Smrg } 99848b8605Smrg} 100848b8605Smrg 101848b8605Smrg 102848b8605Smrg/** 103848b8605Smrg * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to 104848b8605Smrg * the corresponding Gallium type. 105848b8605Smrg */ 106848b8605Smrgstatic unsigned 107848b8605Smrgtranslate_prim(const struct gl_context *ctx, unsigned prim) 108848b8605Smrg{ 109848b8605Smrg /* GL prims should match Gallium prims, spot-check a few */ 110848b8605Smrg STATIC_ASSERT(GL_POINTS == PIPE_PRIM_POINTS); 111848b8605Smrg STATIC_ASSERT(GL_QUADS == PIPE_PRIM_QUADS); 112848b8605Smrg STATIC_ASSERT(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 113b8e80941Smrg STATIC_ASSERT(GL_PATCHES == PIPE_PRIM_PATCHES); 114848b8605Smrg 115848b8605Smrg return prim; 116848b8605Smrg} 117848b8605Smrg 118b8e80941Smrgstatic inline void 119b8e80941Smrgprepare_draw(struct st_context *st, struct gl_context *ctx) 120b8e80941Smrg{ 121b8e80941Smrg /* Mesa core state should have been validated already */ 122b8e80941Smrg assert(ctx->NewState == 0x0); 123b8e80941Smrg 124b8e80941Smrg if (unlikely(!st->bitmap.cache.empty)) 125b8e80941Smrg st_flush_bitmap_cache(st); 126b8e80941Smrg 127b8e80941Smrg st_invalidate_readpix_cache(st); 128b8e80941Smrg 129b8e80941Smrg /* Validate state. */ 130b8e80941Smrg if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK || 131b8e80941Smrg st->gfx_shaders_may_be_dirty) { 132b8e80941Smrg st_validate_state(st, ST_PIPELINE_RENDER); 133b8e80941Smrg } 134b8e80941Smrg 135b8e80941Smrg struct pipe_context *pipe = st->pipe; 136b8e80941Smrg 137b8e80941Smrg /* Pin threads regularly to the same Zen CCX that the main thread is 138b8e80941Smrg * running on. The main thread can move between CCXs. 139b8e80941Smrg */ 140b8e80941Smrg if (unlikely(HAVE_SCHED_GETCPU && /* Linux */ 141b8e80941Smrg /* AMD Zen */ 142b8e80941Smrg util_cpu_caps.nr_cpus != util_cpu_caps.cores_per_L3 && 143b8e80941Smrg /* no glthread */ 144b8e80941Smrg ctx->CurrentClientDispatch != ctx->MarshalExec && 145b8e80941Smrg /* driver support */ 146b8e80941Smrg pipe->set_context_param && 147b8e80941Smrg /* do it occasionally */ 148b8e80941Smrg ++st->pin_thread_counter % 512 == 0)) { 149b8e80941Smrg int cpu = sched_getcpu(); 150b8e80941Smrg if (cpu >= 0) { 151b8e80941Smrg unsigned L3_cache = cpu / util_cpu_caps.cores_per_L3; 152b8e80941Smrg 153b8e80941Smrg pipe->set_context_param(pipe, 154b8e80941Smrg PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE, 155b8e80941Smrg L3_cache); 156b8e80941Smrg } 157b8e80941Smrg } 158b8e80941Smrg} 159848b8605Smrg 160848b8605Smrg/** 161848b8605Smrg * This function gets plugged into the VBO module and is called when 162848b8605Smrg * we have something to render. 163848b8605Smrg * Basically, translate the information into the format expected by gallium. 164b8e80941Smrg * 165b8e80941Smrg * Try to keep this logic in sync with st_feedback_draw_vbo. 166848b8605Smrg */ 167b8e80941Smrgstatic void 168848b8605Smrgst_draw_vbo(struct gl_context *ctx, 169848b8605Smrg const struct _mesa_prim *prims, 170848b8605Smrg GLuint nr_prims, 171848b8605Smrg const struct _mesa_index_buffer *ib, 172848b8605Smrg GLboolean index_bounds_valid, 173848b8605Smrg GLuint min_index, 174848b8605Smrg GLuint max_index, 175848b8605Smrg struct gl_transform_feedback_object *tfb_vertcount, 176b8e80941Smrg unsigned stream, 177848b8605Smrg struct gl_buffer_object *indirect) 178848b8605Smrg{ 179848b8605Smrg struct st_context *st = st_context(ctx); 180848b8605Smrg struct pipe_draw_info info; 181848b8605Smrg unsigned i; 182b8e80941Smrg unsigned start = 0; 183848b8605Smrg 184b8e80941Smrg prepare_draw(st, ctx); 185848b8605Smrg 186b8e80941Smrg /* Initialize pipe_draw_info. */ 187b8e80941Smrg info.primitive_restart = false; 188b8e80941Smrg info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices; 189b8e80941Smrg info.indirect = NULL; 190b8e80941Smrg info.count_from_stream_output = NULL; 191b8e80941Smrg info.restart_index = 0; 192848b8605Smrg 193848b8605Smrg if (ib) { 194b8e80941Smrg struct gl_buffer_object *bufobj = ib->obj; 195b8e80941Smrg 196848b8605Smrg /* Get index bounds for user buffers. */ 197b8e80941Smrg if (!index_bounds_valid && st->draw_needs_minmax_index) { 198b8e80941Smrg vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, 199b8e80941Smrg nr_prims); 200848b8605Smrg } 201848b8605Smrg 202b8e80941Smrg info.index_size = ib->index_size; 203b8e80941Smrg info.min_index = min_index; 204b8e80941Smrg info.max_index = max_index; 205b8e80941Smrg 206b8e80941Smrg if (_mesa_is_bufferobj(bufobj)) { 207b8e80941Smrg /* indices are in a real VBO */ 208b8e80941Smrg info.has_user_indices = false; 209b8e80941Smrg info.index.resource = st_buffer_object(bufobj)->buffer; 210b8e80941Smrg 211b8e80941Smrg /* Return if the bound element array buffer doesn't have any backing 212b8e80941Smrg * storage. (nothing to do) 213b8e80941Smrg */ 214b8e80941Smrg if (!info.index.resource) 215b8e80941Smrg return; 216b8e80941Smrg 217b8e80941Smrg start = pointer_to_offset(ib->ptr) / info.index_size; 218b8e80941Smrg } else { 219b8e80941Smrg /* indices are in user space memory */ 220b8e80941Smrg info.has_user_indices = true; 221b8e80941Smrg info.index.user = ib->ptr; 222848b8605Smrg } 223848b8605Smrg 224b8e80941Smrg setup_primitive_restart(ctx, &info); 225848b8605Smrg } 226848b8605Smrg else { 227b8e80941Smrg info.index_size = 0; 228b8e80941Smrg info.has_user_indices = false; 229b8e80941Smrg 230848b8605Smrg /* Transform feedback drawing is always non-indexed. */ 231848b8605Smrg /* Set info.count_from_stream_output. */ 232848b8605Smrg if (tfb_vertcount) { 233b8e80941Smrg if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &info)) 234b8e80941Smrg return; 235848b8605Smrg } 236848b8605Smrg } 237848b8605Smrg 238b8e80941Smrg assert(!indirect); 239848b8605Smrg 240848b8605Smrg /* do actual drawing */ 241848b8605Smrg for (i = 0; i < nr_prims; i++) { 242848b8605Smrg info.count = prims[i].count; 243b8e80941Smrg 244b8e80941Smrg /* Skip no-op draw calls. */ 245b8e80941Smrg if (!info.count && !tfb_vertcount) 246b8e80941Smrg continue; 247b8e80941Smrg 248b8e80941Smrg info.mode = translate_prim(ctx, prims[i].mode); 249b8e80941Smrg info.start = start + prims[i].start; 250848b8605Smrg info.start_instance = prims[i].base_instance; 251848b8605Smrg info.instance_count = prims[i].num_instances; 252848b8605Smrg info.index_bias = prims[i].basevertex; 253b8e80941Smrg info.drawid = prims[i].draw_id; 254848b8605Smrg if (!ib) { 255848b8605Smrg info.min_index = info.start; 256848b8605Smrg info.max_index = info.start + info.count - 1; 257848b8605Smrg } 258848b8605Smrg 259848b8605Smrg if (ST_DEBUG & DEBUG_DRAW) { 260b8e80941Smrg debug_printf("st/draw: mode %s start %u count %u index_size %d\n", 261848b8605Smrg u_prim_name(info.mode), 262848b8605Smrg info.start, 263848b8605Smrg info.count, 264b8e80941Smrg info.index_size); 265848b8605Smrg } 266848b8605Smrg 267b8e80941Smrg /* Don't call u_trim_pipe_prim. Drivers should do it if they need it. */ 268b8e80941Smrg cso_draw_vbo(st->cso_context, &info); 269b8e80941Smrg } 270b8e80941Smrg} 271b8e80941Smrg 272b8e80941Smrgstatic void 273b8e80941Smrgst_indirect_draw_vbo(struct gl_context *ctx, 274b8e80941Smrg GLuint mode, 275b8e80941Smrg struct gl_buffer_object *indirect_data, 276b8e80941Smrg GLsizeiptr indirect_offset, 277b8e80941Smrg unsigned draw_count, 278b8e80941Smrg unsigned stride, 279b8e80941Smrg struct gl_buffer_object *indirect_draw_count, 280b8e80941Smrg GLsizeiptr indirect_draw_count_offset, 281b8e80941Smrg const struct _mesa_index_buffer *ib) 282b8e80941Smrg{ 283b8e80941Smrg struct st_context *st = st_context(ctx); 284b8e80941Smrg struct pipe_draw_info info; 285b8e80941Smrg struct pipe_draw_indirect_info indirect; 286b8e80941Smrg 287b8e80941Smrg assert(stride); 288b8e80941Smrg prepare_draw(st, ctx); 289b8e80941Smrg 290b8e80941Smrg memset(&indirect, 0, sizeof(indirect)); 291b8e80941Smrg util_draw_init_info(&info); 292b8e80941Smrg info.start = 0; /* index offset / index size */ 293b8e80941Smrg info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ 294b8e80941Smrg 295b8e80941Smrg if (ib) { 296b8e80941Smrg struct gl_buffer_object *bufobj = ib->obj; 297b8e80941Smrg 298b8e80941Smrg /* indices are always in a real VBO */ 299b8e80941Smrg assert(_mesa_is_bufferobj(bufobj)); 300b8e80941Smrg 301b8e80941Smrg info.index_size = ib->index_size; 302b8e80941Smrg info.index.resource = st_buffer_object(bufobj)->buffer; 303b8e80941Smrg info.start = pointer_to_offset(ib->ptr) / info.index_size; 304b8e80941Smrg 305b8e80941Smrg /* Primitive restart is not handled by the VBO module in this case. */ 306b8e80941Smrg setup_primitive_restart(ctx, &info); 307b8e80941Smrg } 308b8e80941Smrg 309b8e80941Smrg info.mode = translate_prim(ctx, mode); 310b8e80941Smrg info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices; 311b8e80941Smrg info.indirect = &indirect; 312b8e80941Smrg indirect.buffer = st_buffer_object(indirect_data)->buffer; 313b8e80941Smrg indirect.offset = indirect_offset; 314b8e80941Smrg 315b8e80941Smrg if (ST_DEBUG & DEBUG_DRAW) { 316b8e80941Smrg debug_printf("st/draw indirect: mode %s drawcount %d index_size %d\n", 317b8e80941Smrg u_prim_name(info.mode), 318b8e80941Smrg draw_count, 319b8e80941Smrg info.index_size); 320b8e80941Smrg } 321b8e80941Smrg 322b8e80941Smrg if (!st->has_multi_draw_indirect) { 323b8e80941Smrg int i; 324b8e80941Smrg 325b8e80941Smrg assert(!indirect_draw_count); 326b8e80941Smrg indirect.draw_count = 1; 327b8e80941Smrg for (i = 0; i < draw_count; i++) { 328b8e80941Smrg info.drawid = i; 329848b8605Smrg cso_draw_vbo(st->cso_context, &info); 330b8e80941Smrg indirect.offset += stride; 331848b8605Smrg } 332b8e80941Smrg } else { 333b8e80941Smrg indirect.draw_count = draw_count; 334b8e80941Smrg indirect.stride = stride; 335b8e80941Smrg if (indirect_draw_count) { 336b8e80941Smrg indirect.indirect_draw_count = 337b8e80941Smrg st_buffer_object(indirect_draw_count)->buffer; 338b8e80941Smrg indirect.indirect_draw_count_offset = indirect_draw_count_offset; 339848b8605Smrg } 340b8e80941Smrg cso_draw_vbo(st->cso_context, &info); 341848b8605Smrg } 342848b8605Smrg} 343848b8605Smrg 344848b8605Smrg 345848b8605Smrgvoid 346b8e80941Smrgst_init_draw_functions(struct dd_function_table *functions) 347848b8605Smrg{ 348b8e80941Smrg functions->Draw = st_draw_vbo; 349b8e80941Smrg functions->DrawIndirect = st_indirect_draw_vbo; 350b8e80941Smrg} 351848b8605Smrg 352848b8605Smrg 353b8e80941Smrgvoid 354b8e80941Smrgst_destroy_draw(struct st_context *st) 355b8e80941Smrg{ 356b8e80941Smrg draw_destroy(st->draw); 357b8e80941Smrg} 358b8e80941Smrg 359b8e80941Smrg/** 360b8e80941Smrg * Getter for the draw_context, so that initialization of it can happen only 361b8e80941Smrg * when needed (the TGSI exec machines take up quite a bit of memory). 362b8e80941Smrg */ 363b8e80941Smrgstruct draw_context * 364b8e80941Smrgst_get_draw_context(struct st_context *st) 365b8e80941Smrg{ 366b8e80941Smrg if (!st->draw) { 367b8e80941Smrg st->draw = draw_create(st->pipe); 368b8e80941Smrg if (!st->draw) { 369b8e80941Smrg _mesa_error(st->ctx, GL_OUT_OF_MEMORY, "feedback fallback allocation"); 370b8e80941Smrg return NULL; 371b8e80941Smrg } 372b8e80941Smrg } 373848b8605Smrg 374848b8605Smrg /* Disable draw options that might convert points/lines to tris, etc. 375848b8605Smrg * as that would foul-up feedback/selection mode. 376848b8605Smrg */ 377848b8605Smrg draw_wide_line_threshold(st->draw, 1000.0f); 378848b8605Smrg draw_wide_point_threshold(st->draw, 1000.0f); 379848b8605Smrg draw_enable_line_stipple(st->draw, FALSE); 380848b8605Smrg draw_enable_point_sprites(st->draw, FALSE); 381848b8605Smrg 382b8e80941Smrg return st->draw; 383b8e80941Smrg} 384848b8605Smrg 385b8e80941Smrg/** 386b8e80941Smrg * Draw a quad with given position, texcoords and color. 387b8e80941Smrg */ 388b8e80941Smrgbool 389b8e80941Smrgst_draw_quad(struct st_context *st, 390b8e80941Smrg float x0, float y0, float x1, float y1, float z, 391b8e80941Smrg float s0, float t0, float s1, float t1, 392b8e80941Smrg const float *color, 393b8e80941Smrg unsigned num_instances) 394848b8605Smrg{ 395b8e80941Smrg struct pipe_vertex_buffer vb = {0}; 396b8e80941Smrg struct st_util_vertex *verts; 397b8e80941Smrg 398b8e80941Smrg vb.stride = sizeof(struct st_util_vertex); 399b8e80941Smrg 400b8e80941Smrg u_upload_alloc(st->pipe->stream_uploader, 0, 401b8e80941Smrg 4 * sizeof(struct st_util_vertex), 4, 402b8e80941Smrg &vb.buffer_offset, &vb.buffer.resource, (void **) &verts); 403b8e80941Smrg if (!vb.buffer.resource) { 404b8e80941Smrg return false; 405b8e80941Smrg } 406b8e80941Smrg 407b8e80941Smrg /* lower-left */ 408b8e80941Smrg verts[0].x = x0; 409b8e80941Smrg verts[0].y = y1; 410b8e80941Smrg verts[0].z = z; 411b8e80941Smrg verts[0].r = color[0]; 412b8e80941Smrg verts[0].g = color[1]; 413b8e80941Smrg verts[0].b = color[2]; 414b8e80941Smrg verts[0].a = color[3]; 415b8e80941Smrg verts[0].s = s0; 416b8e80941Smrg verts[0].t = t0; 417b8e80941Smrg 418b8e80941Smrg /* lower-right */ 419b8e80941Smrg verts[1].x = x1; 420b8e80941Smrg verts[1].y = y1; 421b8e80941Smrg verts[1].z = z; 422b8e80941Smrg verts[1].r = color[0]; 423b8e80941Smrg verts[1].g = color[1]; 424b8e80941Smrg verts[1].b = color[2]; 425b8e80941Smrg verts[1].a = color[3]; 426b8e80941Smrg verts[1].s = s1; 427b8e80941Smrg verts[1].t = t0; 428b8e80941Smrg 429b8e80941Smrg /* upper-right */ 430b8e80941Smrg verts[2].x = x1; 431b8e80941Smrg verts[2].y = y0; 432b8e80941Smrg verts[2].z = z; 433b8e80941Smrg verts[2].r = color[0]; 434b8e80941Smrg verts[2].g = color[1]; 435b8e80941Smrg verts[2].b = color[2]; 436b8e80941Smrg verts[2].a = color[3]; 437b8e80941Smrg verts[2].s = s1; 438b8e80941Smrg verts[2].t = t1; 439b8e80941Smrg 440b8e80941Smrg /* upper-left */ 441b8e80941Smrg verts[3].x = x0; 442b8e80941Smrg verts[3].y = y0; 443b8e80941Smrg verts[3].z = z; 444b8e80941Smrg verts[3].r = color[0]; 445b8e80941Smrg verts[3].g = color[1]; 446b8e80941Smrg verts[3].b = color[2]; 447b8e80941Smrg verts[3].a = color[3]; 448b8e80941Smrg verts[3].s = s0; 449b8e80941Smrg verts[3].t = t1; 450b8e80941Smrg 451b8e80941Smrg u_upload_unmap(st->pipe->stream_uploader); 452b8e80941Smrg 453b8e80941Smrg cso_set_vertex_buffers(st->cso_context, 0, 1, &vb); 454b8e80941Smrg 455b8e80941Smrg if (num_instances > 1) { 456b8e80941Smrg cso_draw_arrays_instanced(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4, 457b8e80941Smrg 0, num_instances); 458b8e80941Smrg } else { 459b8e80941Smrg cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_FAN, 0, 4); 460b8e80941Smrg } 461b8e80941Smrg 462b8e80941Smrg pipe_resource_reference(&vb.buffer.resource, NULL); 463b8e80941Smrg 464b8e80941Smrg return true; 465848b8605Smrg} 466