0,0 → 1,287 |
/************************************************************************** |
* |
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
* All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the |
* "Software"), to deal in the Software without restriction, including |
* without limitation the rights to use, copy, modify, merge, publish, |
* distribute, sub license, and/or sell copies of the Software, and to |
* permit persons to whom the Software is furnished to do so, subject to |
* the following conditions: |
* |
* The above copyright notice and this permission notice (including the |
* next paragraph) shall be included in all copies or substantial portions |
* of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR |
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
**************************************************************************/ |
|
/* |
* Render unclipped vertex buffers by emitting vertices directly to |
* dma buffers. Use strip/fan hardware acceleration where possible. |
* |
*/ |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
|
#include "math/m_xform.h" |
|
#include "tnl/t_context.h" |
#include "tnl/t_vertex.h" |
#include "tnl/t_pipeline.h" |
|
#include "intel_screen.h" |
#include "intel_context.h" |
#include "intel_tris.h" |
#include "intel_batchbuffer.h" |
#include "intel_reg.h" |
|
/* |
* Render unclipped vertex buffers by emitting vertices directly to |
* dma buffers. Use strip/fan hardware primitives where possible. |
* Try to simulate missing primitives with indexed vertices. |
*/ |
#define HAVE_POINTS 0 /* Has it, but can't use because subpixel has to |
* be adjusted for points on the INTEL/I845G |
*/ |
#define HAVE_LINES 1 |
#define HAVE_LINE_STRIPS 1 |
#define HAVE_TRIANGLES 1 |
#define HAVE_TRI_STRIPS 1 |
#define HAVE_TRI_STRIP_1 0 /* has it, template can't use it yet */ |
#define HAVE_TRI_FANS 1 |
#define HAVE_POLYGONS 1 |
#define HAVE_QUADS 0 |
#define HAVE_QUAD_STRIPS 0 |
|
#define HAVE_ELTS 0 |
|
static uint32_t hw_prim[GL_POLYGON + 1] = { |
0, |
PRIM3D_LINELIST, |
PRIM3D_LINESTRIP, |
PRIM3D_LINESTRIP, |
PRIM3D_TRILIST, |
PRIM3D_TRISTRIP, |
PRIM3D_TRIFAN, |
0, |
0, |
PRIM3D_POLY |
}; |
|
static const GLenum reduced_prim[GL_POLYGON + 1] = { |
GL_POINTS, |
GL_LINES, |
GL_LINES, |
GL_LINES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES |
}; |
|
static const int scale_prim[GL_POLYGON + 1] = { |
0, /* fallback case */ |
1, |
2, |
2, |
1, |
3, |
3, |
0, /* fallback case */ |
0, /* fallback case */ |
3 |
}; |
|
|
static void |
intelDmaPrimitive(struct intel_context *intel, GLenum prim) |
{ |
if (0) |
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); |
INTEL_FIREVERTICES(intel); |
intel->vtbl.reduced_primitive_state(intel, reduced_prim[prim]); |
intel_set_prim(intel, hw_prim[prim]); |
} |
|
#define INTEL_NO_VBO_STATE_RESERVED 1500 |
|
static INLINE GLuint intel_get_vb_max(struct intel_context *intel) |
{ |
GLuint ret; |
|
if (intel->intelScreen->no_vbo) { |
ret = intel->batch.bo->size - INTEL_NO_VBO_STATE_RESERVED; |
} else |
ret = INTEL_VB_SIZE; |
ret /= (intel->vertex_size * 4); |
return ret; |
} |
|
static INLINE GLuint intel_get_current_max(struct intel_context *intel) |
{ |
GLuint ret; |
|
if (intel->intelScreen->no_vbo) { |
ret = intel_batchbuffer_space(intel); |
ret = ret <= INTEL_NO_VBO_STATE_RESERVED ? 0 : ret - INTEL_NO_VBO_STATE_RESERVED; |
} else |
ret = (INTEL_VB_SIZE - intel->prim.current_offset); |
|
return ret / (intel->vertex_size * 4); |
} |
|
#define LOCAL_VARS struct intel_context *intel = intel_context(ctx) |
#define INIT( prim ) \ |
do { \ |
intelDmaPrimitive( intel, prim ); \ |
} while (0) |
|
#define FLUSH() INTEL_FIREVERTICES(intel) |
|
#define GET_SUBSEQUENT_VB_MAX_VERTS() intel_get_vb_max(intel) |
#define GET_CURRENT_VB_MAX_VERTS() intel_get_current_max(intel) |
|
#define ALLOC_VERTS(nr) intel_get_prim_space(intel, nr) |
|
#define EMIT_VERTS( ctx, j, nr, buf ) \ |
_tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf ) |
|
#define TAG(x) intel_##x |
#include "tnl_dd/t_dd_dmatmp.h" |
|
|
/**********************************************************************/ |
/* Render pipeline stage */ |
/**********************************************************************/ |
|
/* Heuristic to choose between the two render paths: |
*/ |
static bool |
choose_render(struct intel_context *intel, struct vertex_buffer *VB) |
{ |
int vertsz = intel->vertex_size; |
int cost_render = 0; |
int cost_fallback = 0; |
int nr_prims = 0; |
int nr_rprims = 0; |
int nr_rverts = 0; |
int rprim = intel->reduced_primitive; |
int i = 0; |
|
for (i = 0; i < VB->PrimitiveCount; i++) { |
GLuint prim = VB->Primitive[i].mode; |
GLuint length = VB->Primitive[i].count; |
|
if (!length) |
continue; |
|
nr_prims++; |
nr_rverts += length * scale_prim[prim & PRIM_MODE_MASK]; |
|
if (reduced_prim[prim & PRIM_MODE_MASK] != rprim) { |
nr_rprims++; |
rprim = reduced_prim[prim & PRIM_MODE_MASK]; |
} |
} |
|
/* One point for each generated primitive: |
*/ |
cost_render = nr_prims; |
cost_fallback = nr_rprims; |
|
/* One point for every 1024 dwords (4k) of dma: |
*/ |
cost_render += (vertsz * i) / 1024; |
cost_fallback += (vertsz * nr_rverts) / 1024; |
|
if (0) |
fprintf(stderr, "cost render: %d fallback: %d\n", |
cost_render, cost_fallback); |
|
if (cost_render > cost_fallback) |
return false; |
|
return true; |
} |
|
|
static GLboolean |
intel_run_render(struct gl_context * ctx, struct tnl_pipeline_stage *stage) |
{ |
struct intel_context *intel = intel_context(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint i; |
|
intel->vtbl.render_prevalidate( intel ); |
|
/* Don't handle clipping or indexed vertices. |
*/ |
if (intel->RenderIndex != 0 || |
!intel_validate_render(ctx, VB) || !choose_render(intel, VB)) { |
return true; |
} |
|
tnl->clipspace.new_inputs |= VERT_BIT_POS; |
|
tnl->Driver.Render.Start(ctx); |
|
for (i = 0; i < VB->PrimitiveCount; i++) { |
GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); |
GLuint start = VB->Primitive[i].start; |
GLuint length = VB->Primitive[i].count; |
|
if (!length) |
continue; |
|
intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start, |
start + length, prim); |
} |
|
tnl->Driver.Render.Finish(ctx); |
|
INTEL_FIREVERTICES(intel); |
|
return false; /* finished the pipe */ |
} |
|
static const struct tnl_pipeline_stage _intel_render_stage = { |
"intel render", |
NULL, |
NULL, |
NULL, |
NULL, |
intel_run_render /* run */ |
}; |
|
const struct tnl_pipeline_stage *intel_pipeline[] = { |
&_tnl_vertex_transform_stage, |
&_tnl_normal_transform_stage, |
&_tnl_lighting_stage, |
&_tnl_fog_coordinate_stage, |
&_tnl_texgen_stage, |
&_tnl_texture_transform_stage, |
&_tnl_point_attenuation_stage, |
&_tnl_vertex_program_stage, |
#if 1 |
&_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */ |
#endif |
&_tnl_render_stage, |
0, |
}; |