2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Keith Whitwell <keith@tungstengraphics.com>
36 #include "t_pipeline.h"
37 #include "t_save_api.h"
38 #include "t_vtx_api.h"
40 static GLint
get_size( const GLfloat
*f
)
42 if (f
[3] != 1.0) return 4;
43 if (f
[2] != 0.0) return 3;
48 /* Some nasty stuff still hanging on here.
50 * TODO - remove VB->ColorPtr, etc and just use the AttrPtr's.
52 static void _tnl_bind_vertex_list( GLcontext
*ctx
,
53 struct tnl_vertex_list
*node
)
55 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
56 struct vertex_buffer
*VB
= &tnl
->vb
;
57 struct tnl_vertex_arrays
*tmp
= &tnl
->save_inputs
;
58 GLfloat
*data
= node
->buffer
;
61 /* Setup constant data in the VB.
63 VB
->Count
= node
->count
;
64 VB
->Primitive
= node
->prim
;
65 VB
->PrimitiveCount
= node
->prim_count
;
67 VB
->NormalLengthPtr
= node
->normal_lengths
;
69 for (attr
= 0; attr
<= _TNL_ATTRIB_INDEX
; attr
++) {
70 if (node
->attrsz
[attr
]) {
71 tmp
->Attribs
[attr
].count
= node
->count
;
72 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) data
;
73 tmp
->Attribs
[attr
].start
= data
;
74 tmp
->Attribs
[attr
].size
= node
->attrsz
[attr
];
75 tmp
->Attribs
[attr
].stride
= node
->vertex_size
* sizeof(GLfloat
);
76 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
77 data
+= node
->attrsz
[attr
];
80 tmp
->Attribs
[attr
].count
= node
->count
;
81 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) tnl
->vtx
.current
[attr
];
82 tmp
->Attribs
[attr
].start
= tnl
->vtx
.current
[attr
];
83 tmp
->Attribs
[attr
].size
= get_size( tnl
->vtx
.current
[attr
] );
84 tmp
->Attribs
[attr
].stride
= 0;
85 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
90 /* Copy edgeflag to a contiguous array
92 if (ctx
->Polygon
.FrontMode
!= GL_FILL
|| ctx
->Polygon
.BackMode
!= GL_FILL
) {
93 if (node
->attrsz
[_TNL_ATTRIB_EDGEFLAG
]) {
94 VB
->EdgeFlag
= _tnl_translate_edgeflag( ctx
, data
,
100 VB
->EdgeFlag
= _tnl_import_current_edgeflag( ctx
, node
->count
);
103 /* Legacy pointers -- remove one day.
105 VB
->ObjPtr
= VB
->AttribPtr
[_TNL_ATTRIB_POS
];
106 VB
->NormalPtr
= VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
];
107 VB
->ColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
];
109 VB
->IndexPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_INDEX
];
111 VB
->SecondaryColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
];
112 VB
->SecondaryColorPtr
[1] = 0;
113 VB
->FogCoordPtr
= VB
->AttribPtr
[_TNL_ATTRIB_FOG
];
115 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
116 VB
->TexCoordPtr
[i
] = VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
];
120 static void _playback_copy_to_current( GLcontext
*ctx
,
121 struct tnl_vertex_list
*node
)
123 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
128 data
= node
->buffer
+ (node
->count
-1) * node
->vertex_size
;
132 for (i
= _TNL_ATTRIB_POS
+1 ; i
<= _TNL_ATTRIB_INDEX
; i
++) {
133 if (node
->attrsz
[i
]) {
134 ASSIGN_4V(tnl
->vtx
.current
[i
], 0, 0, 0, 1);
135 COPY_SZ_4V(tnl
->vtx
.current
[i
], node
->attrsz
[i
], data
);
136 data
+= node
->attrsz
[i
];
140 /* Edgeflag requires special treatment:
142 if (node
->attrsz
[_TNL_ATTRIB_EDGEFLAG
]) {
143 ctx
->Current
.EdgeFlag
= (data
[0] == 1.0);
146 /* Colormaterial -- this kindof sucks.
148 if (ctx
->Light
.ColorMaterialEnabled
) {
149 _mesa_update_color_material(ctx
, ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
152 if (node
->have_materials
) {
153 tnl
->Driver
.NotifyMaterialChange( ctx
);
156 /* CurrentExecPrimitive
158 if (node
->prim_count
) {
159 GLenum mode
= node
->prim
[node
->prim_count
- 1].mode
;
161 ctx
->Driver
.CurrentExecPrimitive
= PRIM_OUTSIDE_BEGIN_END
;
163 ctx
->Driver
.CurrentExecPrimitive
= (mode
& PRIM_MODE_MASK
);
169 * Execute the buffer and save copied verts.
171 void _tnl_playback_vertex_list( GLcontext
*ctx
, void *data
)
173 struct tnl_vertex_list
*node
= (struct tnl_vertex_list
*)data
;
174 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
176 FLUSH_CURRENT(ctx
, 0);
178 if (node
->prim_count
&&
181 if (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
&&
182 (node
->prim
[0].mode
& PRIM_BEGIN
)) {
184 /* Degenerate case: list is called inside begin/end pair and
185 * includes operations such as glBegin or glDrawArrays.
187 _mesa_error( ctx
, GL_INVALID_OPERATION
, "displaylist recursive begin");
188 _tnl_loopback_vertex_list( ctx
, (struct tnl_vertex_list
*) data
);
191 else if (tnl
->LoopbackDListCassettes
||
192 node
->dangling_attr_ref
) {
193 /* Degenerate case: list references current data and would
194 * require fixup. Take the easier option & loop it back.
196 _tnl_loopback_vertex_list( ctx
, (struct tnl_vertex_list
*) data
);
201 _mesa_update_state( ctx
);
203 if (tnl
->pipeline
.build_state_changes
)
204 _tnl_validate_pipeline( ctx
);
206 _tnl_bind_vertex_list( ctx
, node
);
208 /* Invalidate all stored data before and after run:
210 tnl
->pipeline
.run_input_changes
|= tnl
->pipeline
.inputs
;
211 tnl
->Driver
.RunPipeline( ctx
);
212 tnl
->pipeline
.run_input_changes
|= tnl
->pipeline
.inputs
;
217 _playback_copy_to_current( ctx
, node
);