1 /* $Id: t_imm_dlist.c,v 1.8 2001/02/15 01:33:52 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Keith Whitwell <keithw@valinux.com>
39 #include "t_context.h"
40 #include "t_imm_api.h"
41 #include "t_imm_elt.h"
42 #include "t_imm_alloc.h"
43 #include "t_imm_dlist.h"
44 #include "t_imm_debug.h"
45 #include "t_imm_exec.h"
46 #include "t_imm_fixup.h"
47 #include "t_pipeline.h"
54 GLuint SavedBeginState
;
61 GLuint MaterialOrMask
;
64 static void execute_compiled_cassette( GLcontext
*ctx
, void *data
);
67 /* Insert the active immediate struct onto the display list currently
71 _tnl_compile_cassette( GLcontext
*ctx
, struct immediate
*IM
)
73 struct immediate
*im
= TNL_CURRENT_IM(ctx
);
74 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
75 TNLvertexcassette
*node
;
76 GLuint new_beginstate
;
79 _tnl_compute_orflag( IM
);
81 IM
->CopyStart
= IM
->Start
;
83 if (IM
->OrFlag
& VERT_ELT
) {
86 GLuint start
= IM
->FlushElt
? IM
->LastPrimitive
: IM
->CopyStart
;
87 _tnl_translate_array_elts( ctx
, IM
, start
, IM
->Count
);
89 /* Need to recompute andflag.
91 if (IM
->AndFlag
& VERT_ELT
)
92 IM
->CopyAndFlag
= IM
->AndFlag
|= ctx
->Array
._Enabled
;
94 for (i
= IM
->CopyStart
; i
< IM
->Count
; i
++)
95 andflag
&= IM
->Flag
[i
];
96 IM
->CopyAndFlag
= IM
->AndFlag
= andflag
;
100 _tnl_fixup_input( ctx
, IM
);
102 /* Mark the last primitive:
104 IM
->PrimitiveLength
[IM
->LastPrimitive
] = IM
->Count
- IM
->LastPrimitive
;
105 ASSERT(IM
->Primitive
[IM
->LastPrimitive
] & PRIM_LAST
);
108 node
= (TNLvertexcassette
*)
109 _mesa_alloc_instruction(ctx
,
110 tnl
->opcode_vertex_cassette
,
111 sizeof(TNLvertexcassette
));
115 node
->IM
= im
; im
->ref_count
++;
116 node
->Start
= im
->Start
;
117 node
->Count
= im
->Count
;
118 node
->BeginState
= im
->BeginState
;
119 node
->SavedBeginState
= im
->SavedBeginState
;
120 node
->OrFlag
= im
->OrFlag
;
121 node
->TexSize
= im
->TexSize
;
122 node
->AndFlag
= im
->AndFlag
;
123 node
->LastData
= im
->LastData
;
124 node
->LastPrimitive
= im
->LastPrimitive
;
125 node
->LastMaterial
= im
->LastMaterial
;
126 node
->MaterialOrMask
= im
->MaterialOrMask
;
128 if (ctx
->ExecuteFlag
) {
129 execute_compiled_cassette( ctx
, (void *)node
);
133 /* Discard any errors raised in the last cassette.
135 new_beginstate
= node
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
);
137 /* Decide whether this immediate struct is full, or can be used for
138 * the next batch of vertices as well.
140 if (im
->Count
> IMM_MAXDATA
- 16) {
143 struct immediate
*new_im
= _tnl_alloc_immediate(ctx
);
146 im
->ref_count
--; /* remove CURRENT_IM reference */
147 ASSERT(im
->ref_count
> 0);
148 SET_IMMEDIATE( ctx
, new_im
);
149 _tnl_reset_input( ctx
, IMM_MAX_COPIED_VERTS
,
150 new_beginstate
, node
->SavedBeginState
);
152 /* Still some room in the current immediate.
154 _tnl_reset_input( ctx
, im
->Count
+1+IMM_MAX_COPIED_VERTS
,
155 new_beginstate
, node
->SavedBeginState
);
161 execute_compiled_cassette( GLcontext
*ctx
, void *data
)
163 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
164 TNLvertexcassette
*node
= (TNLvertexcassette
*)data
;
165 struct immediate
*IM
= node
->IM
;
168 gl_update_state(ctx
);
170 if (tnl
->pipeline
.build_state_changes
)
171 _tnl_validate_pipeline( ctx
);
173 IM
->Start
= node
->Start
;
174 IM
->CopyStart
= node
->Start
;
175 IM
->Count
= node
->Count
;
176 IM
->BeginState
= node
->BeginState
;
177 IM
->SavedBeginState
= node
->SavedBeginState
;
178 IM
->OrFlag
= node
->OrFlag
;
179 IM
->TexSize
= node
->TexSize
;
180 IM
->AndFlag
= node
->AndFlag
;
181 IM
->LastData
= node
->LastData
;
182 IM
->LastPrimitive
= node
->LastPrimitive
;
184 if ((MESA_VERBOSE
& VERBOSE_DISPLAY_LIST
) &&
185 (MESA_VERBOSE
& VERBOSE_IMMEDIATE
))
186 _tnl_print_cassette( IM
);
188 if (MESA_VERBOSE
& VERBOSE_DISPLAY_LIST
) {
189 fprintf(stderr
, "Run cassette %d, rows %d..%d, beginstate %x ",
191 IM
->Start
, IM
->Count
, IM
->BeginState
);
192 _tnl_print_vert_flags("orflag", IM
->OrFlag
);
195 if (IM
->Count
== IM
->Start
) {
196 _tnl_copy_to_current( ctx
, IM
, IM
->OrFlag
);
200 if (IM
->SavedBeginState
) {
201 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1)
202 tnl
->ReplayHardBeginEnd
= 1;
203 if (!tnl
->ReplayHardBeginEnd
) {
204 /* This is a user error. Whatever operation (like glRectf)
205 * decomposed to this hard begin/end pair is now being run
206 * inside a begin/end object -- illegally. Reject it and
209 gl_error(ctx
, GL_INVALID_OPERATION
, "hard replay");
214 _tnl_fixup_compiled_cassette( ctx
, IM
);
215 _tnl_get_exec_copy_verts( ctx
, IM
);
216 _tnl_run_cassette( ctx
, IM
);
217 _tnl_restore_compiled_cassette( ctx
, IM
);
219 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1)
220 tnl
->ReplayHardBeginEnd
= 0;
224 destroy_compiled_cassette( GLcontext
*ctx
, void *data
)
226 TNLvertexcassette
*node
= (TNLvertexcassette
*)data
;
228 if ( --node
->IM
->ref_count
== 0 )
229 _tnl_free_immediate( node
->IM
);
234 print_compiled_cassette( GLcontext
*ctx
, void *data
)
236 TNLvertexcassette
*node
= (TNLvertexcassette
*)data
;
237 struct immediate
*IM
= node
->IM
;
239 fprintf(stderr
, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n",
240 node
->IM
->id
, node
->Start
, node
->Count
);
242 IM
->Start
= node
->Start
;
243 IM
->Count
= node
->Count
;
244 IM
->BeginState
= node
->BeginState
;
245 IM
->OrFlag
= node
->OrFlag
;
246 IM
->TexSize
= node
->TexSize
;
247 IM
->AndFlag
= node
->AndFlag
;
248 IM
->LastData
= node
->LastData
;
249 IM
->LastPrimitive
= node
->LastPrimitive
;
250 IM
->LastMaterial
= node
->LastMaterial
;
251 IM
->MaterialOrMask
= node
->MaterialOrMask
;
253 _tnl_print_cassette( node
->IM
);
257 _tnl_BeginCallList( GLcontext
*ctx
, GLuint list
)
261 FLUSH_CURRENT(ctx
, 0);
265 /* Called at the tail of a CallList. Copy vertices out of the display
269 _tnl_EndCallList( GLcontext
*ctx
)
271 /* May have to copy vertices from a dangling begin/end inside the
272 * list to the current immediate.
274 if (ctx
->CallDepth
== 0) {
275 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
276 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
278 if (tnl
->ExecCopySource
!= IM
)
279 _tnl_copy_immediate_vertices( ctx
, IM
);
285 _tnl_EndList( GLcontext
*ctx
)
287 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
288 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
292 if (IM
== tnl
->ExecCopySource
) {
295 if ( --tnl
->ExecCopySource
->ref_count
== 0 )
296 _tnl_free_immediate( tnl
->ExecCopySource
);
299 /* If this one isn't free, get a clean one. (Otherwise we'll be
300 * using one that's already half full).
302 if (IM
->ref_count
!= 0)
303 IM
= _tnl_alloc_immediate( ctx
);
305 ASSERT(IM
->ref_count
== 0);
307 tnl
->ExecCopySource
= IM
;
310 SET_IMMEDIATE( ctx
, IM
);
313 _tnl_reset_input( ctx
, IMM_MAX_COPIED_VERTS
, 0, 0 );
315 /* outside begin/end, even in COMPILE_AND_EXEC,
316 * so no vertices to copy, right?
318 ASSERT(TNL_CONTEXT(ctx
)->ExecCopyCount
== 0);
323 _tnl_NewList( GLcontext
*ctx
, GLuint list
, GLenum mode
)
325 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
327 /* Use the installed immediate struct. No vertices in the current
328 * immediate, no copied vertices in the system.
330 ASSERT(TNL_CURRENT_IM(ctx
));
331 ASSERT(TNL_CURRENT_IM(ctx
)->Start
== IMM_MAX_COPIED_VERTS
);
332 ASSERT(TNL_CURRENT_IM(ctx
)->Start
== TNL_CURRENT_IM(ctx
)->Count
);
333 ASSERT(TNL_CONTEXT(ctx
)->ExecCopyCount
== 0);
335 /* Set current Begin/End state to unknown:
337 IM
->BeginState
= VERT_BEGIN_0
;
338 ctx
->Driver
.CurrentSavePrimitive
= PRIM_UNKNOWN
;
343 _tnl_dlist_init( GLcontext
*ctx
)
345 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
347 tnl
->opcode_vertex_cassette
=
348 _mesa_alloc_opcode( ctx
,
349 sizeof(TNLvertexcassette
),
350 execute_compiled_cassette
,
351 destroy_compiled_cassette
,
352 print_compiled_cassette
);