1 /**************************************************************************
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
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:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
27 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810context.c,v 1.3 2002/10/30 12:51:33 alanh Exp $ */
31 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "simple_list.h"
40 #include "extensions.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
46 #include "array_cache/acache.h"
48 #include "tnl/t_pipeline.h"
50 #include "drivers/common/driverfuncs.h"
52 #include "i810screen.h"
55 #include "i810state.h"
60 #include "i810ioctl.h"
67 const char __driConfigOptions
[] = { 0 };
68 const GLuint __driNConfigOptions
= 0;
70 static const GLubyte
*i810GetString( GLcontext
*ctx
, GLenum name
)
74 return (GLubyte
*)"Keith Whitwell";
76 return (GLubyte
*)"Mesa DRI I810 20021125";
82 static void i810BufferSize(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
84 GET_CURRENT_CONTEXT(ctx
);
85 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
87 /* Need to lock to make sure the driDrawable is uptodate. This
88 * information is used to resize Mesa's software buffers, so it has
92 *width
= imesa
->driDrawable
->w
;
93 *height
= imesa
->driDrawable
->h
;
94 UNLOCK_HARDWARE(imesa
);
97 /* Extension strings exported by the i810 driver.
99 static const char * const card_extensions
[] =
101 "GL_ARB_multitexture",
102 "GL_ARB_texture_env_add",
103 "GL_ARB_texture_mirrored_repeat",
104 "GL_EXT_stencil_wrap",
105 "GL_EXT_texture_edge_clamp",
106 "GL_EXT_texture_lod_bias",
107 "GL_MESA_ycbcr_texture",
108 "GL_SGIS_generate_mipmap",
112 extern const struct tnl_pipeline_stage _i810_render_stage
;
114 static const struct tnl_pipeline_stage
*i810_pipeline
[] = {
115 &_tnl_vertex_transform_stage
,
116 &_tnl_normal_transform_stage
,
117 &_tnl_lighting_stage
,
118 &_tnl_fog_coordinate_stage
,
120 &_tnl_texture_transform_stage
,
121 /* REMOVE: point attenuation stage */
123 &_i810_render_stage
, /* ADD: unclipped rastersetup-to-dma */
129 static const struct dri_debug_control debug_control
[] =
131 { "fall", DEBUG_FALLBACKS
},
132 { "tex", DEBUG_TEXTURE
},
133 { "ioctl", DEBUG_IOCTL
},
134 { "prim", DEBUG_PRIMS
},
135 { "vert", DEBUG_VERTS
},
136 { "state", DEBUG_STATE
},
137 { "verb", DEBUG_VERBOSE
},
138 { "dri", DEBUG_DRI
},
139 { "dma", DEBUG_DMA
},
140 { "san", DEBUG_SANITY
},
141 { "sync", DEBUG_SYNC
},
142 { "sleep", DEBUG_SLEEP
},
147 i810CreateContext( const __GLcontextModes
*mesaVis
,
148 __DRIcontextPrivate
*driContextPriv
,
149 void *sharedContextPrivate
)
151 GLcontext
*ctx
, *shareCtx
;
152 i810ContextPtr imesa
;
153 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
154 i810ScreenPrivate
*i810Screen
= (i810ScreenPrivate
*)sPriv
->private;
155 I810SAREAPtr saPriv
= (I810SAREAPtr
)
156 (((GLubyte
*)sPriv
->pSAREA
) + i810Screen
->sarea_priv_offset
);
157 struct dd_function_table functions
;
159 /* Allocate i810 context */
160 imesa
= (i810ContextPtr
) CALLOC_STRUCT(i810_context_t
);
165 driContextPriv
->driverPrivate
= imesa
;
167 imesa
->i810Screen
= i810Screen
;
168 imesa
->driScreen
= sPriv
;
169 imesa
->sarea
= saPriv
;
170 imesa
->glBuffer
= NULL
;
172 /* Init default driver functions then plug in our I810-specific functions
173 * (the texture functions are especially important)
175 _mesa_init_driver_functions( &functions
);
176 i810InitIoctlFuncs( &functions
);
177 i810InitTextureFuncs( &functions
);
180 /* Allocate the Mesa context */
181 if (sharedContextPrivate
)
182 shareCtx
= ((i810ContextPtr
) sharedContextPrivate
)->glCtx
;
185 imesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
186 &functions
, (void*) imesa
);
192 (void) memset( imesa
->texture_heaps
, 0, sizeof( imesa
->texture_heaps
) );
193 make_empty_list( & imesa
->swapped
);
196 imesa
->texture_heaps
[0] = driCreateTextureHeap( 0, imesa
,
197 i810Screen
->textureSize
,
200 imesa
->sarea
->texList
,
201 (unsigned *) & imesa
->sarea
->texAge
, /* XXX we shouldn't cast! */
203 sizeof( struct i810_texture_object_t
),
204 (destroy_texture_object_t
*) i810DestroyTexObj
);
208 /* Set the maximum texture size small enough that we can guarentee
209 * that both texture units can bind a maximal texture and have them
216 ctx
->Const
.MaxTextureUnits
= 2;
217 ctx
->Const
.MaxTextureImageUnits
= 2;
218 ctx
->Const
.MaxTextureCoordUnits
= 2;
221 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
222 * FIXME: packed, but they're not in Intel graphics hardware.
224 driCalculateMaxTextureLevels( imesa
->texture_heaps
,
228 11, /* max 2D texture size is 2048x2048 */
229 0, /* 3D textures unsupported */
230 0, /* cube textures unsupported. */
231 0, /* texture rectangles unsupported. */
235 ctx
->Const
.MinLineWidth
= 1.0;
236 ctx
->Const
.MinLineWidthAA
= 1.0;
237 ctx
->Const
.MaxLineWidth
= 3.0;
238 ctx
->Const
.MaxLineWidthAA
= 3.0;
239 ctx
->Const
.LineWidthGranularity
= 1.0;
241 ctx
->Const
.MinPointSize
= 1.0;
242 ctx
->Const
.MinPointSizeAA
= 1.0;
243 ctx
->Const
.MaxPointSize
= 3.0;
244 ctx
->Const
.MaxPointSizeAA
= 3.0;
245 ctx
->Const
.PointSizeGranularity
= 1.0;
247 ctx
->Driver
.GetBufferSize
= i810BufferSize
;
248 ctx
->Driver
.ResizeBuffers
= _swrast_alloc_buffers
;
249 ctx
->Driver
.GetString
= i810GetString
;
253 ctx
->DriverCtx
= (void *) imesa
;
256 /* Initialize the software rasterizer and helper modules.
258 _swrast_CreateContext( ctx
);
259 _ac_CreateContext( ctx
);
260 _tnl_CreateContext( ctx
);
261 _swsetup_CreateContext( ctx
);
263 /* Install the customized pipeline:
265 _tnl_destroy_pipeline( ctx
);
266 _tnl_install_pipeline( ctx
, i810_pipeline
);
268 /* Configure swrast and T&L to match hardware characteristics:
270 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
271 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
272 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
273 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
277 imesa
->hHWContext
= driContextPriv
->hHWContext
;
278 imesa
->driFd
= sPriv
->fd
;
279 imesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
281 imesa
->stipple_in_hw
= 1;
282 imesa
->RenderIndex
= ~0;
283 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
284 imesa
->upload_cliprects
= GL_TRUE
;
286 imesa
->CurrentTexObj
[0] = 0;
287 imesa
->CurrentTexObj
[1] = 0;
289 _math_matrix_ctr( &imesa
->ViewportMatrix
);
291 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
292 /* XXX these should really go right after _mesa_init_driver_functions() */
293 i810InitStateFuncs( ctx
);
294 i810InitTriFuncs( ctx
);
295 i810InitSpanFuncs( ctx
);
297 i810InitState( ctx
);
300 I810_DEBUG
= driParseDebugString( getenv( "I810_DEBUG" ),
302 I810_DEBUG
|= driParseDebugString( getenv( "INTEL_DEBUG" ),
310 i810DestroyContext(__DRIcontextPrivate
*driContextPriv
)
312 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
314 assert(imesa
); /* should never be null */
316 GLboolean release_texture_heaps
;
319 release_texture_heaps
= (imesa
->glCtx
->Shared
->RefCount
== 1);
320 _swsetup_DestroyContext( imesa
->glCtx
);
321 _tnl_DestroyContext( imesa
->glCtx
);
322 _ac_DestroyContext( imesa
->glCtx
);
323 _swrast_DestroyContext( imesa
->glCtx
);
325 i810FreeVB( imesa
->glCtx
);
327 /* free the Mesa context */
328 imesa
->glCtx
->DriverCtx
= NULL
;
329 _mesa_destroy_context(imesa
->glCtx
);
330 if ( release_texture_heaps
) {
331 /* This share group is about to go away, free our private
332 * texture object data.
336 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
337 driDestroyTextureHeap( imesa
->texture_heaps
[ i
] );
338 imesa
->texture_heaps
[ i
] = NULL
;
341 assert( is_empty_list( & imesa
->swapped
) );
349 void i810XMesaSetFrontClipRects( i810ContextPtr imesa
)
351 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
353 imesa
->numClipRects
= dPriv
->numClipRects
;
354 imesa
->pClipRects
= dPriv
->pClipRects
;
355 imesa
->drawX
= dPriv
->x
;
356 imesa
->drawY
= dPriv
->y
;
358 i810EmitDrawingRectangle( imesa
);
359 imesa
->upload_cliprects
= GL_TRUE
;
363 void i810XMesaSetBackClipRects( i810ContextPtr imesa
)
365 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
367 if (imesa
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0)
369 imesa
->numClipRects
= dPriv
->numClipRects
;
370 imesa
->pClipRects
= dPriv
->pClipRects
;
371 imesa
->drawX
= dPriv
->x
;
372 imesa
->drawY
= dPriv
->y
;
374 imesa
->numClipRects
= dPriv
->numBackClipRects
;
375 imesa
->pClipRects
= dPriv
->pBackClipRects
;
376 imesa
->drawX
= dPriv
->backX
;
377 imesa
->drawY
= dPriv
->backY
;
380 i810EmitDrawingRectangle( imesa
);
381 imesa
->upload_cliprects
= GL_TRUE
;
385 static void i810XMesaWindowMoved( i810ContextPtr imesa
)
387 switch (imesa
->glCtx
->Color
._DrawDestMask
[0]) {
388 case DD_FRONT_LEFT_BIT
:
389 i810XMesaSetFrontClipRects( imesa
);
391 case DD_BACK_LEFT_BIT
:
392 i810XMesaSetBackClipRects( imesa
);
395 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
396 i810XMesaSetFrontClipRects( imesa
);
402 i810UnbindContext(__DRIcontextPrivate
*driContextPriv
)
404 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
406 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
407 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
408 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
416 i810MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
417 __DRIdrawablePrivate
*driDrawPriv
,
418 __DRIdrawablePrivate
*driReadPriv
)
420 if (driContextPriv
) {
421 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
423 /* Shouldn't the readbuffer be stored also?
425 imesa
->driDrawable
= driDrawPriv
;
427 _mesa_make_current2(imesa
->glCtx
,
428 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
429 (GLframebuffer
*) driReadPriv
->driverPrivate
);
431 /* Are these necessary?
433 i810XMesaWindowMoved( imesa
);
434 if (!imesa
->glCtx
->Viewport
.Width
)
435 _mesa_set_viewport(imesa
->glCtx
, 0, 0,
436 driDrawPriv
->w
, driDrawPriv
->h
);
439 _mesa_make_current(0,0);
446 i810UpdatePageFlipping( i810ContextPtr imesa
)
448 GLcontext
*ctx
= imesa
->glCtx
;
451 switch (ctx
->Color
._DrawDestMask
[0]) {
452 case DD_FRONT_LEFT_BIT
:
455 case DD_BACK_LEFT_BIT
:
462 if ( imesa
->sarea
->pf_current_page
== 1 )
466 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->fbOffset
| imesa
->i810Screen
->backPitchBits
;
467 imesa
->drawMap
= (char *)imesa
->driScreen
->pFB
;
468 imesa
->readMap
= (char *)imesa
->driScreen
->pFB
;
470 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->backOffset
| imesa
->i810Screen
->backPitchBits
;
471 imesa
->drawMap
= imesa
->i810Screen
->back
.map
;
472 imesa
->readMap
= imesa
->i810Screen
->back
.map
;
475 imesa
->dirty
|= I810_UPLOAD_BUFFERS
;
478 void i810GetLock( i810ContextPtr imesa
, GLuint flags
)
480 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
481 __DRIscreenPrivate
*sPriv
= imesa
->driScreen
;
482 I810SAREAPtr sarea
= imesa
->sarea
;
483 int me
= imesa
->hHWContext
;
486 drmGetLock(imesa
->driFd
, imesa
->hHWContext
, flags
);
488 /* If the window moved, may need to set a new cliprect now.
490 * NOTE: This releases and regains the hw lock, so all state
491 * checking must be done *after* this call:
493 DRI_VALIDATE_DRAWABLE_INFO(sPriv
, dPriv
);
496 /* If we lost context, need to dump all registers to hardware.
497 * Note that we don't care about 2d contexts, even if they perform
498 * accelerated commands, so the DRI locking in the X server is even
499 * more broken than usual.
501 if (sarea
->ctxOwner
!= me
) {
502 imesa
->upload_cliprects
= GL_TRUE
;
503 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
504 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
505 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
506 sarea
->ctxOwner
= me
;
509 /* Shared texture managment - if another client has played with
510 * texture space, figure out which if any of our textures have been
511 * ejected, and update our global LRU.
513 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
514 DRI_AGE_TEXTURES( imesa
->texture_heaps
[ i
] );
517 if (imesa
->lastStamp
!= dPriv
->lastStamp
) {
518 i810UpdatePageFlipping( imesa
);
519 i810XMesaWindowMoved( imesa
);
520 imesa
->lastStamp
= dPriv
->lastStamp
;
526 i810SwapBuffers( __DRIdrawablePrivate
*dPriv
)
528 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
529 i810ContextPtr imesa
;
531 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
533 if (ctx
->Visual
.doubleBufferMode
) {
534 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
535 if ( imesa
->sarea
->pf_active
) {
536 i810PageFlip( dPriv
);
538 i810CopyBuffer( dPriv
);
543 /* XXX this shouldn't be an error but we can't handle it for now */
544 _mesa_problem(NULL
, "i810SwapBuffers: drawable has no context!\n");