1 /************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Render unclipped vertex buffers by emitting vertices directly to 30 * dma buffers. Use strip/fan hardware acceleration where possible. 31 * 32 */ 33 #include "main/glheader.h" 34 #include "main/context.h" 35 #include "main/macros.h" 36 #include "main/imports.h" 37 #include "main/mtypes.h" 38 #include "main/enums.h" 39 40 #include "math/m_xform.h" 41 42 #include "tnl/t_context.h" 43 #include "tnl/t_vertex.h" 44 #include "tnl/t_pipeline.h" 45 46 #include "intel_screen.h" 47 #include "intel_context.h" 48 #include "intel_tris.h" 49 #include "intel_batchbuffer.h" 50 #include "intel_reg.h" 51 52 /* 53 * Render unclipped vertex buffers by emitting vertices directly to 54 * dma buffers. Use strip/fan hardware primitives where possible. 55 * Try to simulate missing primitives with indexed vertices. 56 */ 57 #define HAVE_POINTS 1 58 #define HAVE_LINES 1 59 #define HAVE_LINE_STRIPS 1 60 #define HAVE_TRIANGLES 1 61 #define HAVE_TRI_STRIPS 1 62 #define HAVE_TRI_FANS 1 63 #define HAVE_POLYGONS 1 64 65 #define HAVE_ELTS 0 66 67 static const uint32_t hw_prim[GL_POLYGON + 1] = { 68 [GL_POINTS] = PRIM3D_POINTLIST, 69 [GL_LINES ] = PRIM3D_LINELIST, 70 [GL_LINE_LOOP] = PRIM3D_LINESTRIP, 71 [GL_LINE_STRIP] = PRIM3D_LINESTRIP, 72 [GL_TRIANGLES] = PRIM3D_TRILIST, 73 [GL_TRIANGLE_STRIP] = PRIM3D_TRISTRIP, 74 [GL_TRIANGLE_FAN] = PRIM3D_TRIFAN, 75 [GL_QUADS] = 0, 76 [GL_QUAD_STRIP] = 0, 77 [GL_POLYGON] = PRIM3D_POLY, 78 }; 79 80 static const GLenum reduced_prim[GL_POLYGON + 1] = { 81 [GL_POINTS] = GL_POINTS, 82 [GL_LINES] = GL_LINES, 83 [GL_LINE_LOOP] = GL_LINES, 84 [GL_LINE_STRIP] = GL_LINES, 85 [GL_TRIANGLES] = GL_TRIANGLES, 86 [GL_TRIANGLE_STRIP] = GL_TRIANGLES, 87 [GL_TRIANGLE_FAN] = GL_TRIANGLES, 88 [GL_QUADS] = GL_TRIANGLES, 89 [GL_QUAD_STRIP] = GL_TRIANGLES, 90 [GL_POLYGON] = GL_TRIANGLES, 91 }; 92 93 static const int scale_prim[GL_POLYGON + 1] = { 94 [GL_POINTS] = 1, 95 [GL_LINES] = 1, 96 [GL_LINE_LOOP] = 2, 97 [GL_LINE_STRIP] = 2, 98 [GL_TRIANGLES] = 1, 99 [GL_TRIANGLE_STRIP] = 3, 100 [GL_TRIANGLE_FAN] = 3, 101 [GL_QUADS] = 0, /* fallback case */ 102 [GL_QUAD_STRIP] = 0, /* fallback case */ 103 [GL_POLYGON] = 3, 104 }; 105 106 107 static void 108 intelDmaPrimitive(struct intel_context *intel, GLenum prim) 109 { 110 if (0) 111 fprintf(stderr, "%s %s\n", __func__, _mesa_enum_to_string(prim)); 112 INTEL_FIREVERTICES(intel); 113 intel->vtbl.reduced_primitive_state(intel, reduced_prim[prim]); 114 intel_set_prim(intel, hw_prim[prim]); 115 } 116 117 #define INTEL_NO_VBO_STATE_RESERVED 1500 118 119 static inline GLuint intel_get_vb_max(struct intel_context *intel) 120 { 121 GLuint ret; 122 123 if (intel->intelScreen->no_vbo) { 124 ret = intel->batch.bo->size - INTEL_NO_VBO_STATE_RESERVED; 125 } else 126 ret = INTEL_VB_SIZE; 127 ret /= (intel->vertex_size * 4); 128 return ret; 129 } 130 131 static inline GLuint intel_get_current_max(struct intel_context *intel) 132 { 133 GLuint ret; 134 135 if (intel->intelScreen->no_vbo) { 136 ret = intel_batchbuffer_space(intel); 137 ret = ret <= INTEL_NO_VBO_STATE_RESERVED ? 0 : ret - INTEL_NO_VBO_STATE_RESERVED; 138 } else 139 ret = (INTEL_VB_SIZE - intel->prim.current_offset); 140 141 return ret / (intel->vertex_size * 4); 142 } 143 144 #define LOCAL_VARS struct intel_context *intel = intel_context(ctx) 145 #define INIT( prim ) \ 146 do { \ 147 intelDmaPrimitive( intel, prim ); \ 148 } while (0) 149 150 #define FLUSH() INTEL_FIREVERTICES(intel) 151 152 #define GET_SUBSEQUENT_VB_MAX_VERTS() intel_get_vb_max(intel) 153 #define GET_CURRENT_VB_MAX_VERTS() intel_get_current_max(intel) 154 155 #define ALLOC_VERTS(nr) intel_get_prim_space(intel, nr) 156 157 #define EMIT_VERTS( ctx, j, nr, buf ) \ 158 _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf ) 159 160 #define TAG(x) intel_##x 161 #include "tnl_dd/t_dd_dmatmp.h" 162 163 164 /**********************************************************************/ 165 /* Render pipeline stage */ 166 /**********************************************************************/ 167 168 /* Heuristic to choose between the two render paths: 169 */ 170 static bool 171 choose_render(struct intel_context *intel, struct vertex_buffer *VB) 172 { 173 int vertsz = intel->vertex_size; 174 int cost_render = 0; 175 int cost_fallback = 0; 176 int nr_prims = 0; 177 int nr_rprims = 0; 178 int nr_rverts = 0; 179 int rprim = intel->reduced_primitive; 180 int i = 0; 181 182 for (i = 0; i < VB->PrimitiveCount; i++) { 183 GLuint prim = VB->Primitive[i].mode; 184 GLuint length = VB->Primitive[i].count; 185 186 if (!length) 187 continue; 188 189 nr_prims++; 190 nr_rverts += length * scale_prim[prim & PRIM_MODE_MASK]; 191 192 if (reduced_prim[prim & PRIM_MODE_MASK] != rprim) { 193 nr_rprims++; 194 rprim = reduced_prim[prim & PRIM_MODE_MASK]; 195 } 196 } 197 198 /* One point for each generated primitive: 199 */ 200 cost_render = nr_prims; 201 cost_fallback = nr_rprims; 202 203 /* One point for every 1024 dwords (4k) of dma: 204 */ 205 cost_render += (vertsz * i) / 1024; 206 cost_fallback += (vertsz * nr_rverts) / 1024; 207 208 if (0) 209 fprintf(stderr, "cost render: %d fallback: %d\n", 210 cost_render, cost_fallback); 211 212 if (cost_render > cost_fallback) 213 return false; 214 215 return true; 216 } 217 218 219 static GLboolean 220 intel_run_render(struct gl_context * ctx, struct tnl_pipeline_stage *stage) 221 { 222 struct intel_context *intel = intel_context(ctx); 223 TNLcontext *tnl = TNL_CONTEXT(ctx); 224 struct vertex_buffer *VB = &tnl->vb; 225 GLuint i; 226 227 intel->vtbl.render_prevalidate( intel ); 228 229 /* Don't handle clipping or indexed vertices. 230 */ 231 if (intel->RenderIndex != 0 || 232 !intel_validate_render(ctx, VB) || !choose_render(intel, VB)) { 233 return true; 234 } 235 236 tnl->clipspace.new_inputs |= VERT_BIT_POS; 237 238 tnl->Driver.Render.Start(ctx); 239 240 for (i = 0; i < VB->PrimitiveCount; i++) { 241 GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); 242 GLuint start = VB->Primitive[i].start; 243 GLuint length = VB->Primitive[i].count; 244 245 if (!length) 246 continue; 247 248 intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start, 249 length, prim); 250 } 251 252 tnl->Driver.Render.Finish(ctx); 253 254 INTEL_FIREVERTICES(intel); 255 256 return false; /* finished the pipe */ 257 } 258 259 static const struct tnl_pipeline_stage _intel_render_stage = { 260 "intel render", 261 NULL, 262 NULL, 263 NULL, 264 NULL, 265 intel_run_render /* run */ 266 }; 267 268 const struct tnl_pipeline_stage *intel_pipeline[] = { 269 &_tnl_vertex_transform_stage, 270 &_tnl_normal_transform_stage, 271 &_tnl_lighting_stage, 272 &_tnl_fog_coordinate_stage, 273 &_tnl_texgen_stage, 274 &_tnl_texture_transform_stage, 275 &_tnl_point_attenuation_stage, 276 &_tnl_vertex_program_stage, 277 #if 1 278 &_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */ 279 #endif 280 &_tnl_render_stage, 281 0, 282 }; 283