Modified Files:
[mesa.git] / src / mesa / tnl / t_context.c
1 #include "mtypes.h"
2 #include "mem.h"
3 #include "dlist.h"
4 #include "vtxfmt.h"
5
6 #include "t_context.h"
7 #include "t_clip.h"
8 #include "t_cva.h"
9 #include "t_dlist.h"
10 #include "t_eval.h"
11 #include "t_pipeline.h"
12 #include "t_shade.h"
13 #include "t_light.h"
14 #include "t_texture.h"
15 #include "t_stages.h"
16 #include "t_varray.h"
17 #include "t_vb.h"
18 #include "t_vbrender.h"
19 #include "t_vbxform.h"
20 #include "t_vtxfmt.h"
21 #include "tnl.h"
22
23 #if !defined(THREADS)
24 struct immediate *_tnl_CurrentInput = NULL;
25 #endif
26
27
28 GLboolean
29 _tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags )
30 {
31 TNLcontext *tnl = TNL_CONTEXT(ctx);
32 struct immediate *IM = TNL_CURRENT_IM(ctx);
33
34 if ((IM->Flag[IM->Count] & (VERT_BEGIN|VERT_END)) != VERT_END ||
35 (flush_flags & (FLUSH_STORED_VERTICES|FLUSH_UPDATE_CURRENT)))
36 {
37 if (IM->Flag[IM->Start])
38 _tnl_maybe_transform_vb( IM );
39
40 /* Although this code updates the ctx->Current values, that bit
41 * is left set as there is no easy mechanism to set it
42 * elsewhere. This means that each time core wants to examine
43 * ctx->Current, this function will be called. After the first
44 * time, however, it will be a no-op.
45 */
46 ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES |
47 FLUSH_INSIDE_BEGIN_END);
48
49 return (tnl->_CurrentPrimitive == GL_POLYGON+1);
50 }
51 else
52 return GL_TRUE;
53 }
54
55
56
57 void
58 _tnl_MakeCurrent( GLcontext *ctx,
59 GLframebuffer *drawBuffer,
60 GLframebuffer *readBuffer )
61 {
62 #ifndef THREADS
63 SET_IMMEDIATE( ctx, TNL_VB(ctx)->IM );
64 #endif
65 }
66
67
68 /* Update all state that references _NeedEyeCoords
69 */
70 void
71 _tnl_LightingSpaceChange( GLcontext *ctx )
72 {
73 _tnl_update_normal_transform( ctx );
74 }
75
76
77 static void
78 install_driver_callbacks( GLcontext *ctx )
79 {
80 ctx->Driver.RenderVBCulledTab = _tnl_render_tab_cull;
81 ctx->Driver.RenderVBClippedTab = _tnl_render_tab_clipped;
82 ctx->Driver.RenderVBRawTab = _tnl_render_tab_raw;
83 ctx->Driver.NewList = _tnl_NewList;
84 ctx->Driver.EndList = _tnl_EndList;
85 ctx->Driver.FlushVertices = _tnl_flush_vertices;
86 ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
87 ctx->Driver.LightingSpaceChange = _tnl_LightingSpaceChange;
88 ctx->Driver.MakeCurrent = _tnl_MakeCurrent;
89 ctx->Driver.VertexPointer = _tnl_VertexPointer;
90 ctx->Driver.NormalPointer = _tnl_NormalPointer;
91 ctx->Driver.ColorPointer = _tnl_ColorPointer;
92 ctx->Driver.FogCoordPointer = _tnl_FogCoordPointer;
93 ctx->Driver.IndexPointer = _tnl_IndexPointer;
94 ctx->Driver.SecondaryColorPointer = _tnl_SecondaryColorPointer;
95 ctx->Driver.TexCoordPointer = _tnl_TexCoordPointer;
96 ctx->Driver.EdgeFlagPointer = _tnl_EdgeFlagPointer;
97 ctx->Driver.LockArraysEXT = _tnl_LockArraysEXT;
98 ctx->Driver.UnlockArraysEXT = _tnl_UnlockArraysEXT;
99 }
100
101
102
103 GLboolean
104 _tnl_CreateContext( GLcontext *ctx )
105 {
106 TNLcontext *tnl;
107 static int firsttime = 1;
108
109 /* Onetime initializations. Doesn't really matter if this gets
110 * done twice: no need for mutexes.
111 */
112 if (firsttime) {
113 firsttime = 0;
114 _tnl_clip_init();
115 _tnl_eval_init();
116 _tnl_shade_init();
117 _tnl_texture_init();
118 _tnl_trans_elt_init();
119 _tnl_vbrender_init();
120 _tnl_stages_init();
121 }
122
123 /* Create the TNLcontext structure
124 */
125 ctx->swtnl_context = tnl = CALLOC( sizeof(TNLcontext) );
126 if (!tnl) {
127 return GL_FALSE;
128 }
129
130 /* Create and hook in the data structures available from ctx.
131 */
132 ctx->swtnl_vb = (void *)_tnl_vb_create_for_immediate( ctx );
133 if (!ctx->swtnl_vb) {
134 FREE(tnl);
135 ctx->swtnl_context = 0;
136 return GL_FALSE;
137 }
138
139 ctx->swtnl_im = (void *)TNL_VB(ctx)->IM;
140
141
142 /* Initialize tnl state.
143 */
144 _tnl_dlist_init( ctx );
145 _tnl_pipeline_init( ctx );
146 _tnl_vtxfmt_init( ctx );
147 _tnl_cva_init( ctx );
148
149 _tnl_reset_vb( TNL_VB(ctx) );
150 _tnl_reset_input( ctx, 0, 0 ); /* initially outside begin/end */
151
152
153 tnl->_CurrentTex3Flag = 0;
154 tnl->_CurrentTex4Flag = 0;
155 tnl->_CurrentPrimitive = GL_POLYGON+1;
156
157 /* Hook our functions into exec and compile dispatch tables.
158 */
159 _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
160 _mesa_install_save_vtxfmt( ctx, &tnl->vtxfmt );
161 ctx->Save->EvalMesh1 = _mesa_save_EvalMesh1; /* fixme */
162 ctx->Save->EvalMesh2 = _mesa_save_EvalMesh2;
163
164 /* Set a few default values in the driver struct.
165 */
166 install_driver_callbacks(ctx);
167
168 return GL_TRUE;
169 }
170
171
172 void
173 _tnl_DestroyContext( GLcontext *ctx )
174 {
175 TNLcontext *tnl = TNL_CONTEXT(ctx);
176
177 if (TNL_CURRENT_IM(ctx) != TNL_VB(ctx)->IM)
178 _tnl_immediate_free( TNL_CURRENT_IM(ctx) );
179
180 _tnl_vb_free( TNL_VB(ctx) );
181
182 /* Free cache of immediate buffers. */
183 while (tnl->nr_im_queued-- > 0) {
184 struct immediate * next = tnl->freed_im_queue->next;
185 ALIGN_FREE( tnl->freed_im_queue );
186 tnl->freed_im_queue = next;
187 }
188 }
189
190
191
192 void
193 _tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
194 {
195 if (new_state & _NEW_LIGHT)
196 _tnl_update_lighting_function(ctx);
197
198 if (new_state & _NEW_ARRAY)
199 _tnl_update_client_state( ctx );
200
201 if (new_state & _NEW_TEXTURE)
202 if (ctx->_Enabled & ENABLE_TEXGEN_ANY)
203 _tnl_update_texgen( ctx );
204
205 if (new_state & (_NEW_LIGHT|_NEW_TEXTURE|_NEW_FOG|
206 _DD_NEW_TRI_LIGHT_TWOSIDE |
207 _DD_NEW_SEPERATE_SPECULAR |
208 _DD_NEW_TRI_UNFILLED ))
209 _tnl_update_clipmask(ctx);
210
211 if (new_state & _TNL_NEW_NORMAL_TRANSFORM)
212 _tnl_update_normal_transform( ctx );
213
214 _tnl_update_pipelines(ctx);
215 }
216
217 void
218 _tnl_wakeup_exec( GLcontext *ctx )
219 {
220 TNLcontext *tnl = TNL_CONTEXT(ctx);
221
222 #ifndef VMS
223 fprintf(stderr, "%s\n", __FUNCTION__);
224 #endif
225
226 install_driver_callbacks(ctx);
227
228 /* Hook our functions into exec and compile dispatch tables.
229 */
230 _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
231
232 /* Call all appropriate driver callbacks to revive state.
233 */
234 _tnl_MakeCurrent( ctx, ctx->DrawBuffer, ctx->ReadBuffer );
235 _tnl_UnlockArraysEXT( ctx );
236 _tnl_LockArraysEXT( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
237
238 /* Equivalent to calling all _tnl_*Pointer functions:
239 */
240 tnl->_ArrayNewState = ~0;
241
242 /* Assume we haven't been getting state updates either:
243 */
244 _tnl_InvalidateState( ctx, ~0 );
245
246 /* Special state not restored by other methods:
247 */
248 _tnl_validate_current_tex_flags( ctx, ~0 );
249
250 }
251
252 void
253 _tnl_wakeup_save_exec( GLcontext *ctx )
254 {
255 TNLcontext *tnl = TNL_CONTEXT(ctx);
256
257 #ifndef VMS
258 fprintf(stderr, "%s\n", __FUNCTION__);
259 #endif
260
261 _tnl_wakeup_exec( ctx );
262 _mesa_install_save_vtxfmt( ctx, &tnl->vtxfmt );
263 ctx->Save->EvalMesh1 = _mesa_save_EvalMesh1; /* fixme */
264 ctx->Save->EvalMesh2 = _mesa_save_EvalMesh2;
265 }
266