Major rip-up of internal function insertion interface. The old
[mesa.git] / src / mesa / drivers / dri / i810 / i810context.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
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 PRECISION INSIGHT 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 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810context.c,v 1.3 2002/10/30 12:51:33 alanh Exp $ */
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 *
33 */
34
35
36 #include "glheader.h"
37 #include "context.h"
38 #include "matrix.h"
39 #include "simple_list.h"
40 #include "extensions.h"
41 #include "framebuffer.h"
42 #include "imports.h"
43
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/tnl.h"
47 #include "array_cache/acache.h"
48
49 #include "tnl/t_pipeline.h"
50
51 #include "drivers/common/driverfuncs.h"
52
53 #include "i810screen.h"
54 #include "i810_dri.h"
55
56 #include "i810state.h"
57 #include "i810tex.h"
58 #include "i810span.h"
59 #include "i810tris.h"
60 #include "i810vb.h"
61 #include "i810ioctl.h"
62
63 #include "utils.h"
64
65 #define need_GL_ARB_multisample
66 #include "extension_helper.h"
67
68 #ifndef I810_DEBUG
69 int I810_DEBUG = (0);
70 #endif
71
72 PUBLIC const char __driConfigOptions[] = { 0 };
73 const GLuint __driNConfigOptions = 0;
74
75 static const GLubyte *i810GetString( GLcontext *ctx, GLenum name )
76 {
77 switch (name) {
78 case GL_VENDOR:
79 return (GLubyte *)"Keith Whitwell";
80 case GL_RENDERER:
81 return (GLubyte *)"Mesa DRI I810 20021125";
82 default:
83 return 0;
84 }
85 }
86
87 static void i810BufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
88 {
89 GET_CURRENT_CONTEXT(ctx);
90 i810ContextPtr imesa = I810_CONTEXT(ctx);
91
92 /* Need to lock to make sure the driDrawable is uptodate. This
93 * information is used to resize Mesa's software buffers, so it has
94 * to be correct.
95 */
96 LOCK_HARDWARE(imesa);
97 *width = imesa->driDrawable->w;
98 *height = imesa->driDrawable->h;
99 UNLOCK_HARDWARE(imesa);
100 }
101
102 /* Extension strings exported by the i810 driver.
103 */
104 static const struct dri_extension card_extensions[] =
105 {
106 { "GL_ARB_multisample", GL_ARB_multisample_functions },
107 { "GL_ARB_multitexture", NULL },
108 { "GL_ARB_texture_env_add", NULL },
109 { "GL_ARB_texture_mirrored_repeat", NULL },
110 { "GL_EXT_stencil_wrap", NULL },
111 { "GL_EXT_texture_edge_clamp", NULL },
112 { "GL_EXT_texture_lod_bias", NULL },
113 { "GL_MESA_ycbcr_texture", NULL },
114 { "GL_SGIS_generate_mipmap", NULL },
115 { NULL, NULL }
116 };
117
118 extern const struct tnl_pipeline_stage _i810_render_stage;
119
120 static const struct tnl_pipeline_stage *i810_pipeline[] = {
121 &_tnl_vertex_transform_stage,
122 &_tnl_normal_transform_stage,
123 &_tnl_lighting_stage,
124 &_tnl_fog_coordinate_stage,
125 &_tnl_texgen_stage,
126 &_tnl_texture_transform_stage,
127 /* REMOVE: point attenuation stage */
128 #if 1
129 &_i810_render_stage, /* ADD: unclipped rastersetup-to-dma */
130 #endif
131 &_tnl_render_stage,
132 0,
133 };
134
135 static const struct dri_debug_control debug_control[] =
136 {
137 { "fall", DEBUG_FALLBACKS },
138 { "tex", DEBUG_TEXTURE },
139 { "ioctl", DEBUG_IOCTL },
140 { "prim", DEBUG_PRIMS },
141 { "vert", DEBUG_VERTS },
142 { "state", DEBUG_STATE },
143 { "verb", DEBUG_VERBOSE },
144 { "dri", DEBUG_DRI },
145 { "dma", DEBUG_DMA },
146 { "san", DEBUG_SANITY },
147 { "sync", DEBUG_SYNC },
148 { "sleep", DEBUG_SLEEP },
149 { NULL, 0 }
150 };
151
152 GLboolean
153 i810CreateContext( const __GLcontextModes *mesaVis,
154 __DRIcontextPrivate *driContextPriv,
155 void *sharedContextPrivate )
156 {
157 GLcontext *ctx, *shareCtx;
158 i810ContextPtr imesa;
159 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
160 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
161 I810SAREAPtr saPriv = (I810SAREAPtr)
162 (((GLubyte *)sPriv->pSAREA) + i810Screen->sarea_priv_offset);
163 struct dd_function_table functions;
164
165 /* Allocate i810 context */
166 imesa = (i810ContextPtr) CALLOC_STRUCT(i810_context_t);
167 if (!imesa) {
168 return GL_FALSE;
169 }
170
171 driContextPriv->driverPrivate = imesa;
172
173 imesa->i810Screen = i810Screen;
174 imesa->driScreen = sPriv;
175 imesa->sarea = saPriv;
176 imesa->glBuffer = NULL;
177
178 /* Init default driver functions then plug in our I810-specific functions
179 * (the texture functions are especially important)
180 */
181 _mesa_init_driver_functions( &functions );
182 i810InitIoctlFuncs( &functions );
183 i810InitTextureFuncs( &functions );
184
185
186 /* Allocate the Mesa context */
187 if (sharedContextPrivate)
188 shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
189 else
190 shareCtx = NULL;
191 imesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
192 &functions, (void*) imesa);
193 if (!imesa->glCtx) {
194 FREE(imesa);
195 return GL_FALSE;
196 }
197
198 (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
199 make_empty_list( & imesa->swapped );
200
201 imesa->nr_heaps = 1;
202 imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa,
203 i810Screen->textureSize,
204 12,
205 I810_NR_TEX_REGIONS,
206 imesa->sarea->texList,
207 (unsigned *) & imesa->sarea->texAge, /* XXX we shouldn't cast! */
208 & imesa->swapped,
209 sizeof( struct i810_texture_object_t ),
210 (destroy_texture_object_t *) i810DestroyTexObj );
211
212
213
214 /* Set the maximum texture size small enough that we can guarentee
215 * that both texture units can bind a maximal texture and have them
216 * in memory at once.
217 */
218
219
220
221 ctx = imesa->glCtx;
222 ctx->Const.MaxTextureUnits = 2;
223 ctx->Const.MaxTextureImageUnits = 2;
224 ctx->Const.MaxTextureCoordUnits = 2;
225
226
227 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
228 * FIXME: packed, but they're not in Intel graphics hardware.
229 */
230 driCalculateMaxTextureLevels( imesa->texture_heaps,
231 imesa->nr_heaps,
232 & ctx->Const,
233 4,
234 11, /* max 2D texture size is 2048x2048 */
235 0, /* 3D textures unsupported */
236 0, /* cube textures unsupported. */
237 0, /* texture rectangles unsupported. */
238 12,
239 GL_FALSE );
240
241 ctx->Const.MinLineWidth = 1.0;
242 ctx->Const.MinLineWidthAA = 1.0;
243 ctx->Const.MaxLineWidth = 3.0;
244 ctx->Const.MaxLineWidthAA = 3.0;
245 ctx->Const.LineWidthGranularity = 1.0;
246
247 ctx->Const.MinPointSize = 1.0;
248 ctx->Const.MinPointSizeAA = 1.0;
249 ctx->Const.MaxPointSize = 3.0;
250 ctx->Const.MaxPointSizeAA = 3.0;
251 ctx->Const.PointSizeGranularity = 1.0;
252
253 ctx->Driver.GetBufferSize = i810BufferSize;
254 ctx->Driver.ResizeBuffers = _mesa_resize_framebuffer;
255 ctx->Driver.GetString = i810GetString;
256
257 /* Who owns who?
258 */
259 ctx->DriverCtx = (void *) imesa;
260 imesa->glCtx = ctx;
261
262 /* Initialize the software rasterizer and helper modules.
263 */
264 _swrast_CreateContext( ctx );
265 _ac_CreateContext( ctx );
266 _tnl_CreateContext( ctx );
267 _swsetup_CreateContext( ctx );
268
269 /* Install the customized pipeline:
270 */
271 _tnl_destroy_pipeline( ctx );
272 _tnl_install_pipeline( ctx, i810_pipeline );
273
274 /* Configure swrast and T&L to match hardware characteristics:
275 */
276 _swrast_allow_pixel_fog( ctx, GL_FALSE );
277 _swrast_allow_vertex_fog( ctx, GL_TRUE );
278 _tnl_allow_pixel_fog( ctx, GL_FALSE );
279 _tnl_allow_vertex_fog( ctx, GL_TRUE );
280
281 /* Dri stuff
282 */
283 imesa->hHWContext = driContextPriv->hHWContext;
284 imesa->driFd = sPriv->fd;
285 imesa->driHwLock = &sPriv->pSAREA->lock;
286
287 imesa->stipple_in_hw = 1;
288 imesa->RenderIndex = ~0;
289 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
290 imesa->upload_cliprects = GL_TRUE;
291
292 imesa->CurrentTexObj[0] = 0;
293 imesa->CurrentTexObj[1] = 0;
294
295 _math_matrix_ctr( &imesa->ViewportMatrix );
296
297 driInitExtensions( ctx, card_extensions, GL_TRUE );
298 /* XXX these should really go right after _mesa_init_driver_functions() */
299 i810InitStateFuncs( ctx );
300 i810InitTriFuncs( ctx );
301 i810InitSpanFuncs( ctx );
302 i810InitVB( ctx );
303 i810InitState( ctx );
304
305 #if DO_DEBUG
306 I810_DEBUG = driParseDebugString( getenv( "I810_DEBUG" ),
307 debug_control );
308 I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
309 debug_control );
310 #endif
311
312 return GL_TRUE;
313 }
314
315 void
316 i810DestroyContext(__DRIcontextPrivate *driContextPriv)
317 {
318 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
319
320 assert(imesa); /* should never be null */
321 if (imesa) {
322 GLboolean release_texture_heaps;
323
324
325 release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1);
326 _swsetup_DestroyContext( imesa->glCtx );
327 _tnl_DestroyContext( imesa->glCtx );
328 _ac_DestroyContext( imesa->glCtx );
329 _swrast_DestroyContext( imesa->glCtx );
330
331 i810FreeVB( imesa->glCtx );
332
333 /* free the Mesa context */
334 imesa->glCtx->DriverCtx = NULL;
335 _mesa_destroy_context(imesa->glCtx);
336 if ( release_texture_heaps ) {
337 /* This share group is about to go away, free our private
338 * texture object data.
339 */
340 unsigned int i;
341
342 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
343 driDestroyTextureHeap( imesa->texture_heaps[ i ] );
344 imesa->texture_heaps[ i ] = NULL;
345 }
346
347 assert( is_empty_list( & imesa->swapped ) );
348 }
349
350 FREE(imesa);
351 }
352 }
353
354
355 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
356 {
357 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
358
359 imesa->numClipRects = dPriv->numClipRects;
360 imesa->pClipRects = dPriv->pClipRects;
361 imesa->drawX = dPriv->x;
362 imesa->drawY = dPriv->y;
363
364 i810EmitDrawingRectangle( imesa );
365 imesa->upload_cliprects = GL_TRUE;
366 }
367
368
369 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
370 {
371 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
372
373 if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
374 {
375 imesa->numClipRects = dPriv->numClipRects;
376 imesa->pClipRects = dPriv->pClipRects;
377 imesa->drawX = dPriv->x;
378 imesa->drawY = dPriv->y;
379 } else {
380 imesa->numClipRects = dPriv->numBackClipRects;
381 imesa->pClipRects = dPriv->pBackClipRects;
382 imesa->drawX = dPriv->backX;
383 imesa->drawY = dPriv->backY;
384 }
385
386 i810EmitDrawingRectangle( imesa );
387 imesa->upload_cliprects = GL_TRUE;
388 }
389
390
391 static void i810XMesaWindowMoved( i810ContextPtr imesa )
392 {
393 /* Determine current color drawing buffer */
394 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
395 case BUFFER_BIT_FRONT_LEFT:
396 i810XMesaSetFrontClipRects( imesa );
397 break;
398 case BUFFER_BIT_BACK_LEFT:
399 i810XMesaSetBackClipRects( imesa );
400 break;
401 default:
402 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
403 i810XMesaSetFrontClipRects( imesa );
404 }
405 }
406
407
408 GLboolean
409 i810UnbindContext(__DRIcontextPrivate *driContextPriv)
410 {
411 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
412 if (imesa) {
413 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
414 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
415 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
416 }
417
418 return GL_TRUE;
419 }
420
421
422 GLboolean
423 i810MakeCurrent(__DRIcontextPrivate *driContextPriv,
424 __DRIdrawablePrivate *driDrawPriv,
425 __DRIdrawablePrivate *driReadPriv)
426 {
427 if (driContextPriv) {
428 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
429
430 /* Shouldn't the readbuffer be stored also?
431 */
432 imesa->driDrawable = driDrawPriv;
433
434 _mesa_make_current(imesa->glCtx,
435 (GLframebuffer *) driDrawPriv->driverPrivate,
436 (GLframebuffer *) driReadPriv->driverPrivate);
437
438 /* Are these necessary?
439 */
440 i810XMesaWindowMoved( imesa );
441 }
442 else {
443 _mesa_make_current(NULL, NULL, NULL);
444 }
445
446 return GL_TRUE;
447 }
448
449 static void
450 i810UpdatePageFlipping( i810ContextPtr imesa )
451 {
452 GLcontext *ctx = imesa->glCtx;
453 int front = 0;
454
455 /* Determine current color drawing buffer */
456 switch (ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
457 case BUFFER_BIT_FRONT_LEFT:
458 front = 1;
459 break;
460 case BUFFER_BIT_BACK_LEFT:
461 front = 0;
462 break;
463 default:
464 return;
465 }
466
467 if ( imesa->sarea->pf_current_page == 1 )
468 front ^= 1;
469
470 if (front) {
471 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
472 imesa->drawMap = (char *)imesa->driScreen->pFB;
473 imesa->readMap = (char *)imesa->driScreen->pFB;
474 } else {
475 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
476 imesa->drawMap = imesa->i810Screen->back.map;
477 imesa->readMap = imesa->i810Screen->back.map;
478 }
479
480 imesa->dirty |= I810_UPLOAD_BUFFERS;
481 }
482
483 void i810GetLock( i810ContextPtr imesa, GLuint flags )
484 {
485 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
486 __DRIscreenPrivate *sPriv = imesa->driScreen;
487 I810SAREAPtr sarea = imesa->sarea;
488 int me = imesa->hHWContext;
489 unsigned i;
490
491 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
492
493 /* If the window moved, may need to set a new cliprect now.
494 *
495 * NOTE: This releases and regains the hw lock, so all state
496 * checking must be done *after* this call:
497 */
498 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
499
500
501 /* If we lost context, need to dump all registers to hardware.
502 * Note that we don't care about 2d contexts, even if they perform
503 * accelerated commands, so the DRI locking in the X server is even
504 * more broken than usual.
505 */
506 if (sarea->ctxOwner != me) {
507 imesa->upload_cliprects = GL_TRUE;
508 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
509 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
510 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
511 sarea->ctxOwner = me;
512 }
513
514 /* Shared texture managment - if another client has played with
515 * texture space, figure out which if any of our textures have been
516 * ejected, and update our global LRU.
517 */
518 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
519 DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
520 }
521
522 if (imesa->lastStamp != dPriv->lastStamp) {
523 i810UpdatePageFlipping( imesa );
524 i810XMesaWindowMoved( imesa );
525 imesa->lastStamp = dPriv->lastStamp;
526 }
527 }
528
529
530 void
531 i810SwapBuffers( __DRIdrawablePrivate *dPriv )
532 {
533 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
534 i810ContextPtr imesa;
535 GLcontext *ctx;
536 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
537 ctx = imesa->glCtx;
538 if (ctx->Visual.doubleBufferMode) {
539 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
540 if ( imesa->sarea->pf_active ) {
541 i810PageFlip( dPriv );
542 } else {
543 i810CopyBuffer( dPriv );
544 }
545 }
546 }
547 else {
548 /* XXX this shouldn't be an error but we can't handle it for now */
549 _mesa_problem(NULL, "i810SwapBuffers: drawable has no context!\n");
550 }
551 }
552