Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pipe.c
4565 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/*28* Authors:29* Keith Whitwell <[email protected]>30*/3132#include "draw/draw_private.h"33#include "draw/draw_pipe.h"34#include "util/u_debug.h"35#include "util/u_math.h"36373839boolean draw_pipeline_init( struct draw_context *draw )40{41/* create pipeline stages */42draw->pipeline.wide_line = draw_wide_line_stage( draw );43draw->pipeline.wide_point = draw_wide_point_stage( draw );44draw->pipeline.stipple = draw_stipple_stage( draw );45draw->pipeline.unfilled = draw_unfilled_stage( draw );46draw->pipeline.twoside = draw_twoside_stage( draw );47draw->pipeline.offset = draw_offset_stage( draw );48draw->pipeline.clip = draw_clip_stage( draw );49draw->pipeline.flatshade = draw_flatshade_stage( draw );50draw->pipeline.cull = draw_cull_stage( draw );51draw->pipeline.user_cull = draw_user_cull_stage( draw );52draw->pipeline.validate = draw_validate_stage( draw );53draw->pipeline.first = draw->pipeline.validate;5455if (!draw->pipeline.wide_line ||56!draw->pipeline.wide_point ||57!draw->pipeline.stipple ||58!draw->pipeline.unfilled ||59!draw->pipeline.twoside ||60!draw->pipeline.offset ||61!draw->pipeline.clip ||62!draw->pipeline.flatshade ||63!draw->pipeline.cull ||64!draw->pipeline.user_cull ||65!draw->pipeline.validate)66return FALSE;6768/* these defaults are oriented toward the needs of softpipe */69draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */70draw->pipeline.wide_line_threshold = 1.0f;71draw->pipeline.wide_point_sprites = FALSE;72draw->pipeline.line_stipple = TRUE;73draw->pipeline.point_sprite = TRUE;7475return TRUE;76}777879void draw_pipeline_destroy( struct draw_context *draw )80{81if (draw->pipeline.wide_line)82draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );83if (draw->pipeline.wide_point)84draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );85if (draw->pipeline.stipple)86draw->pipeline.stipple->destroy( draw->pipeline.stipple );87if (draw->pipeline.unfilled)88draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );89if (draw->pipeline.twoside)90draw->pipeline.twoside->destroy( draw->pipeline.twoside );91if (draw->pipeline.offset)92draw->pipeline.offset->destroy( draw->pipeline.offset );93if (draw->pipeline.clip)94draw->pipeline.clip->destroy( draw->pipeline.clip );95if (draw->pipeline.flatshade)96draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );97if (draw->pipeline.cull)98draw->pipeline.cull->destroy( draw->pipeline.cull );99if (draw->pipeline.user_cull)100draw->pipeline.user_cull->destroy( draw->pipeline.user_cull );101if (draw->pipeline.validate)102draw->pipeline.validate->destroy( draw->pipeline.validate );103if (draw->pipeline.aaline)104draw->pipeline.aaline->destroy( draw->pipeline.aaline );105if (draw->pipeline.aapoint)106draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );107if (draw->pipeline.pstipple)108draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );109if (draw->pipeline.rasterize)110draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );111}112113114115/**116* Build primitive to render a point with vertex at v0.117*/118static void do_point( struct draw_context *draw,119const char *v0 )120{121struct prim_header prim;122123prim.flags = 0;124prim.pad = 0;125prim.v[0] = (struct vertex_header *)v0;126127draw->pipeline.first->point( draw->pipeline.first, &prim );128}129130131/**132* Build primitive to render a line with vertices at v0, v1.133* \param flags bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE134*/135static void do_line( struct draw_context *draw,136ushort flags,137const char *v0,138const char *v1 )139{140struct prim_header prim;141142prim.flags = flags;143prim.pad = 0;144prim.v[0] = (struct vertex_header *)v0;145prim.v[1] = (struct vertex_header *)v1;146147draw->pipeline.first->line( draw->pipeline.first, &prim );148}149150151/**152* Build primitive to render a triangle with vertices at v0, v1, v2.153* \param flags bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE154*/155static void do_triangle( struct draw_context *draw,156ushort flags,157char *v0,158char *v1,159char *v2 )160{161struct prim_header prim;162163prim.v[0] = (struct vertex_header *)v0;164prim.v[1] = (struct vertex_header *)v1;165prim.v[2] = (struct vertex_header *)v2;166prim.flags = flags;167prim.pad = 0;168169draw->pipeline.first->tri( draw->pipeline.first, &prim );170}171172173/*174* Set up macros for draw_pt_decompose.h template code.175* This code uses vertex indexes / elements.176*/177178#define TRIANGLE(flags,i0,i1,i2) \179do { \180do_triangle( draw, \181flags, \182verts + stride * (i0), \183verts + stride * (i1), \184verts + stride * (i2) ); \185} while (0)186187#define LINE(flags,i0,i1) \188do { \189do_line( draw, \190flags, \191verts + stride * (i0), \192verts + stride * (i1) ); \193} while (0)194195#define POINT(i0) \196do { \197do_point( draw, verts + stride * (i0) ); \198} while (0)199200#define GET_ELT(idx) (MIN2(elts[idx], max_index))201202#define FUNC pipe_run_elts203#define FUNC_VARS \204struct draw_context *draw, \205unsigned prim, \206unsigned prim_flags, \207struct vertex_header *vertices, \208unsigned stride, \209const ushort *elts, \210unsigned count, \211unsigned max_index212213#include "draw_pt_decompose.h"214215216217/**218* Code to run the pipeline on a fairly arbitrary collection of vertices.219* For drawing indexed primitives.220*221* Vertex headers must be pre-initialized with the222* UNDEFINED_VERTEX_ID, this code will cause that id to become223* overwritten, so it may have to be reset if there is the intention224* to reuse the vertices.225*226* This code provides a callback to reset the vertex id's which the227* draw_vbuf.c code uses when it has to perform a flush.228*/229void draw_pipeline_run( struct draw_context *draw,230const struct draw_vertex_info *vert_info,231const struct draw_prim_info *prim_info)232{233unsigned i, start;234235draw->pipeline.verts = (char *)vert_info->verts;236draw->pipeline.vertex_stride = vert_info->stride;237draw->pipeline.vertex_count = vert_info->count;238239for (start = i = 0;240i < prim_info->primitive_count;241start += prim_info->primitive_lengths[i], i++)242{243const unsigned count = prim_info->primitive_lengths[i];244245#if DEBUG246/* Warn if one of the element indexes go outside the vertex buffer */247{248unsigned max_index = 0x0, i;249/* find the largest element index */250for (i = 0; i < count; i++) {251unsigned int index = prim_info->elts[start + i];252if (index > max_index)253max_index = index;254}255if (max_index >= vert_info->count) {256debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",257__FUNCTION__,258max_index,259vert_info->count);260}261}262#endif263264pipe_run_elts(draw,265prim_info->prim,266prim_info->flags,267vert_info->verts,268vert_info->stride,269prim_info->elts + start,270count,271vert_info->count - 1);272}273274draw->pipeline.verts = NULL;275draw->pipeline.vertex_count = 0;276}277278279/*280* Set up macros for draw_pt_decompose.h template code.281* This code is for non-indexed (aka linear) rendering (no elts).282*/283284#define TRIANGLE(flags,i0,i1,i2) \285do_triangle( draw, flags, \286verts + stride * (i0), \287verts + stride * (i1), \288verts + stride * (i2) )289290#define LINE(flags,i0,i1) \291do_line( draw, flags, \292verts + stride * (i0), \293verts + stride * (i1) )294295#define POINT(i0) \296do_point( draw, verts + stride * (i0) )297298299#define GET_ELT(idx) (idx)300301#define FUNC pipe_run_linear302#define FUNC_VARS \303struct draw_context *draw, \304unsigned prim, \305unsigned prim_flags, \306struct vertex_header *vertices, \307unsigned stride, \308unsigned count309310#include "draw_pt_decompose.h"311312313/*314* For drawing non-indexed primitives.315*/316void draw_pipeline_run_linear( struct draw_context *draw,317const struct draw_vertex_info *vert_info,318const struct draw_prim_info *prim_info)319{320unsigned i, start;321322for (start = i = 0;323i < prim_info->primitive_count;324start += prim_info->primitive_lengths[i], i++)325{326unsigned count = prim_info->primitive_lengths[i];327char *verts = ((char*)vert_info->verts) +328(start * vert_info->stride);329330draw->pipeline.verts = verts;331draw->pipeline.vertex_stride = vert_info->stride;332draw->pipeline.vertex_count = count;333334assert(count <= vert_info->count);335336pipe_run_linear(draw,337prim_info->prim,338prim_info->flags,339(struct vertex_header*)verts,340vert_info->stride,341count);342}343344draw->pipeline.verts = NULL;345draw->pipeline.vertex_count = 0;346}347348349void draw_pipeline_flush( struct draw_context *draw,350unsigned flags )351{352draw->pipeline.first->flush( draw->pipeline.first, flags );353if (flags & DRAW_FLUSH_STATE_CHANGE)354draw->pipeline.first = draw->pipeline.validate;355}356357358