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/i830/i830_context.c,v 1.9 2003/02/06 04:18:00 dawes Exp $ */
30 * \file i830_context.c
32 * Heavily Based on I810 driver written by Keith Whitwell.
34 * \author Jeff Hartmann <jhartmann@2d3d.com>
35 * \author Graeme Fisher <graeme@2d3d.co.za>
36 * \author Abraham vd Merwe <abraham@2d3d.co.za>
37 * \author Keith Whitwell <keith@tungstengraphics.com>
43 #include "simple_list.h"
44 #include "extensions.h"
47 #include "swrast/swrast.h"
48 #include "swrast_setup/swrast_setup.h"
50 #include "array_cache/acache.h"
52 #include "tnl/t_pipeline.h"
54 #include "drivers/common/driverfuncs.h"
56 #include "i830_screen.h"
59 #include "i830_state.h"
61 #include "i830_span.h"
62 #include "i830_tris.h"
63 #include "i830_ioctl.h"
67 #include "xmlpool.h" /* for symbolic values of enum-type options */
72 /***************************************
73 * Mesa's Driver Functions
74 ***************************************/
76 #define DRIVER_DATE "20041007"
79 static const GLubyte
*i830DDGetString( GLcontext
*ctx
, GLenum name
)
82 static char buffer
[128];
86 switch (I830_CONTEXT(ctx
)->i830Screen
->deviceID
) {
88 return (GLubyte
*)"2d3D, Inc";
91 return (GLubyte
*)"VA Linux, Inc";
93 case PCI_CHIP_I855_GM
:
96 return (GLubyte
*)"Tungsten Graphics, Inc";
101 switch (I830_CONTEXT(ctx
)->i830Screen
->deviceID
) {
103 chipset
= "Intel(R) 845G"; break;
104 case PCI_CHIP_I830_M
:
105 chipset
= "Intel(R) 830M"; break;
106 case PCI_CHIP_I855_GM
:
107 chipset
= "Intel(R) 852GM/855GM"; break;
108 case PCI_CHIP_I865_G
:
109 chipset
= "Intel(R) 865G"; break;
111 chipset
= "Unknown Intel Chipset"; break;
114 (void) driGetRendererString( buffer
, chipset
, DRIVER_DATE
, 0 );
115 return (GLubyte
*) buffer
;
122 static void i830BufferSize(GLframebuffer
*buffer
,
123 GLuint
*width
, GLuint
*height
)
125 GET_CURRENT_CONTEXT(ctx
);
126 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
127 /* Need to lock to make sure the driDrawable is uptodate. This
128 * information is used to resize Mesa's software buffers, so it has
131 LOCK_HARDWARE(imesa
);
132 *width
= imesa
->driDrawable
->w
;
133 *height
= imesa
->driDrawable
->h
;
134 UNLOCK_HARDWARE(imesa
);
138 /* Extension strings exported by the i830 driver.
140 static const char * const card_extensions
[] =
142 "GL_ARB_multisample",
143 "GL_ARB_multitexture",
144 "GL_ARB_texture_border_clamp",
145 "GL_ARB_texture_compression",
146 "GL_ARB_texture_env_add",
147 "GL_ARB_texture_env_combine",
148 "GL_ARB_texture_env_crossbar",
149 "GL_ARB_texture_env_dot3",
150 "GL_ARB_texture_mirrored_repeat",
151 "GL_EXT_blend_color",
152 "GL_EXT_blend_equation_separate",
153 "GL_EXT_blend_func_separate",
154 "GL_EXT_blend_minmax",
155 "GL_EXT_blend_subtract",
157 "GL_EXT_secondary_color",
158 "GL_EXT_stencil_wrap",
159 "GL_EXT_texture_edge_clamp",
160 "GL_EXT_texture_env_combine",
161 "GL_EXT_texture_env_dot3",
162 "GL_EXT_texture_filter_anisotropic",
163 "GL_EXT_texture_lod_bias",
164 "GL_EXT_texture_rectangle",
165 "GL_NV_blend_square",
166 "GL_MESA_ycbcr_texture",
167 "GL_SGIS_generate_mipmap",
172 extern const struct tnl_pipeline_stage _i830_render_stage
;
174 static const struct tnl_pipeline_stage
*i830_pipeline
[] = {
175 &_tnl_vertex_transform_stage
,
176 &_tnl_normal_transform_stage
,
177 &_tnl_lighting_stage
,
178 &_tnl_fog_coordinate_stage
,
180 &_tnl_texture_transform_stage
,
181 /* REMOVE: point attenuation stage */
183 &_i830_render_stage
, /* ADD: unclipped rastersetup-to-dma */
190 static const struct dri_debug_control debug_control
[] =
192 { "fall", DEBUG_FALLBACKS
},
193 { "tex", DEBUG_TEXTURE
},
194 { "ioctl", DEBUG_IOCTL
},
195 { "prim", DEBUG_PRIMS
},
196 { "vert", DEBUG_VERTS
},
197 { "state", DEBUG_STATE
},
198 { "verb", DEBUG_VERBOSE
},
199 { "dri", DEBUG_DRI
},
200 { "dma", DEBUG_DMA
},
201 { "san", DEBUG_SANITY
},
202 { "sync", DEBUG_SYNC
},
203 { "sleep", DEBUG_SLEEP
},
208 GLboolean
i830CreateContext( const __GLcontextModes
*mesaVis
,
209 __DRIcontextPrivate
*driContextPriv
,
210 void *sharedContextPrivate
)
212 GLcontext
*ctx
, *shareCtx
;
213 i830ContextPtr imesa
;
214 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
215 i830ScreenPrivate
*screen
= (i830ScreenPrivate
*)sPriv
->private;
216 I830SAREAPtr saPriv
=(I830SAREAPtr
)
217 (((GLubyte
*)sPriv
->pSAREA
)+screen
->sarea_priv_offset
);
218 struct dd_function_table functions
;
220 /* Allocate i830 context */
221 imesa
= (i830ContextPtr
) CALLOC_STRUCT(i830_context_t
);
225 /* Init default driver functions then plug in our I830-specific functions
226 * (the texture functions are especially important)
228 _mesa_init_driver_functions(&functions
);
229 i830InitIoctlFuncs(&functions
);
230 i830InitTextureFuncs(&functions
);
232 /* Allocate the Mesa context */
233 if (sharedContextPrivate
)
234 shareCtx
= ((i830ContextPtr
) sharedContextPrivate
)->glCtx
;
237 imesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
238 &functions
, (void*) imesa
);
243 driContextPriv
->driverPrivate
= imesa
;
246 imesa
->i830Screen
= screen
;
247 imesa
->driScreen
= sPriv
;
248 imesa
->sarea
= saPriv
;
249 imesa
->glBuffer
= NULL
;
251 driParseConfigFiles (&imesa
->optionCache
, &screen
->optionCache
,
252 screen
->driScrnPriv
->myNum
, "i830");
254 (void) memset( imesa
->texture_heaps
, 0, sizeof( imesa
->texture_heaps
) );
255 make_empty_list( & imesa
->swapped
);
258 imesa
->texture_heaps
[0] = driCreateTextureHeap( 0, imesa
,
262 imesa
->sarea
->texList
,
263 (unsigned *) & imesa
->sarea
->texAge
, /* XXX shouldn't need cast! */
265 sizeof( struct i830_texture_object_t
),
266 (destroy_texture_object_t
*) i830DestroyTexObj
);
268 /* Set the maximum texture size small enough that we can guarantee
269 * that every texture unit can bind a maximal texture and have them
274 ctx
->Const
.MaxTextureUnits
= driQueryOptioni(&imesa
->optionCache
,
276 ctx
->Const
.MaxTextureImageUnits
= ctx
->Const
.MaxTextureUnits
;
277 ctx
->Const
.MaxTextureCoordUnits
= ctx
->Const
.MaxTextureUnits
;
279 /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
280 * FIXME: packed, but they're not in Intel graphics hardware.
282 driCalculateMaxTextureLevels( imesa
->texture_heaps
,
286 11, /* max 2D texture size is 2048x2048 */
287 0, /* 3D textures unsupported */
288 0, /* cube textures unsupported. */
289 0, /* texture rectangles unsupported. */
293 ctx
->Const
.MaxTextureMaxAnisotropy
= 2.0;
295 ctx
->Const
.MinLineWidth
= 1.0;
296 ctx
->Const
.MinLineWidthAA
= 1.0;
297 ctx
->Const
.MaxLineWidth
= 3.0;
298 ctx
->Const
.MaxLineWidthAA
= 3.0;
299 ctx
->Const
.LineWidthGranularity
= 1.0;
301 ctx
->Const
.MinPointSize
= 1.0;
302 ctx
->Const
.MinPointSizeAA
= 1.0;
303 ctx
->Const
.MaxPointSize
= 255.0;
304 ctx
->Const
.MaxPointSizeAA
= 3.0;
305 ctx
->Const
.PointSizeGranularity
= 1.0;
307 ctx
->Driver
.GetBufferSize
= i830BufferSize
;
308 ctx
->Driver
.ResizeBuffers
= _swrast_alloc_buffers
;
309 ctx
->Driver
.GetString
= i830DDGetString
;
312 ctx
->DriverCtx
= (void *) imesa
;
315 /* Initialize the software rasterizer and helper modules. */
316 _swrast_CreateContext( ctx
);
317 _ac_CreateContext( ctx
);
318 _tnl_CreateContext( ctx
);
319 _swsetup_CreateContext( ctx
);
321 /* Install the customized pipeline: */
322 _tnl_destroy_pipeline( ctx
);
323 _tnl_install_pipeline( ctx
, i830_pipeline
);
325 /* Configure swrast and T&L to match hardware characteristics: */
326 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
327 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
328 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
329 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
332 imesa
->hHWContext
= driContextPriv
->hHWContext
;
333 imesa
->driFd
= sPriv
->fd
;
334 /* drmLock ptr = &drm_hw_lock_t */
335 imesa
->driHwLock
= (drmLock
*) &sPriv
->pSAREA
->lock
;
336 imesa
->hw_stencil
= mesaVis
->stencilBits
&& mesaVis
->depthBits
== 24;
338 switch(mesaVis
->depthBits
) {
340 imesa
->depth_scale
= 1.0/0xffff;
341 imesa
->depth_clear_mask
= ~0;
342 imesa
->ClearDepth
= 0xffff;
345 imesa
->depth_scale
= 1.0/0xffffff;
346 imesa
->depth_clear_mask
= 0x00ffffff;
347 imesa
->stencil_clear_mask
= 0xff000000;
348 imesa
->ClearDepth
= 0x00ffffff;
350 case 32: /* Not supported */
354 /* Completely disable stenciling for now, there are some serious issues
358 imesa
->hw_stencil
= 0;
361 imesa
->RenderIndex
= ~0;
363 imesa
->upload_cliprects
= GL_TRUE
;
365 imesa
->CurrentTexObj
[0] = 0;
366 imesa
->CurrentTexObj
[1] = 0;
368 imesa
->do_irqs
= (imesa
->i830Screen
->irq_active
&&
369 !getenv("I830_NO_IRQS"));
371 _math_matrix_ctr (&imesa
->ViewportMatrix
);
373 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
375 if (imesa
->glCtx
->Mesa_DXTn
) {
376 _mesa_enable_extension( ctx
, "GL_EXT_texture_compression_s3tc" );
377 _mesa_enable_extension( ctx
, "GL_S3_s3tc" );
379 else if (driQueryOptionb (&imesa
->optionCache
, "force_s3tc_enable")) {
380 _mesa_enable_extension( ctx
, "GL_EXT_texture_compression_s3tc" );
383 _mesa_enable_extension( ctx
, "GL_3DFX_texture_compression_FXT1" );
385 /* XXX these should really go right after _mesa_init_driver_functions() */
386 i830DDInitStateFuncs( ctx
);
387 i830InitTriFuncs (ctx
);
388 i830DDInitSpanFuncs( ctx
);
389 i830DDInitState (ctx
);
392 I830_DEBUG
= driParseDebugString( getenv( "I830_DEBUG" ),
394 I830_DEBUG
|= driParseDebugString( getenv( "INTEL_DEBUG" ),
398 if (getenv("I830_NO_RAST") ||
399 getenv("INTEL_NO_RAST")) {
400 fprintf(stderr
, "disabling 3D rasterization\n");
401 FALLBACK(imesa
, I830_FALLBACK_USER
, 1);
407 void i830DestroyContext(__DRIcontextPrivate
*driContextPriv
)
409 i830ContextPtr imesa
= (i830ContextPtr
) driContextPriv
->driverPrivate
;
411 assert(imesa
); /* should never be null */
413 GLboolean release_texture_heaps
;
416 release_texture_heaps
= (imesa
->glCtx
->Shared
->RefCount
== 1);
417 _swsetup_DestroyContext (imesa
->glCtx
);
418 _tnl_DestroyContext (imesa
->glCtx
);
419 _ac_DestroyContext (imesa
->glCtx
);
420 _swrast_DestroyContext (imesa
->glCtx
);
422 /* free the Mesa context */
423 imesa
->glCtx
->DriverCtx
= NULL
;
424 _mesa_destroy_context(imesa
->glCtx
);
426 if ( release_texture_heaps
) {
427 /* This share group is about to go away, free our private
428 * texture object data.
432 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
433 driDestroyTextureHeap( imesa
->texture_heaps
[ i
] );
434 imesa
->texture_heaps
[ i
] = NULL
;
437 assert( is_empty_list( & imesa
->swapped
) );
444 void i830XMesaSetFrontClipRects( i830ContextPtr imesa
)
446 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
448 imesa
->numClipRects
= dPriv
->numClipRects
;
449 imesa
->pClipRects
= dPriv
->pClipRects
;
450 imesa
->drawX
= dPriv
->x
;
451 imesa
->drawY
= dPriv
->y
;
453 i830EmitDrawingRectangle( imesa
);
454 imesa
->upload_cliprects
= GL_TRUE
;
457 void i830XMesaSetBackClipRects( i830ContextPtr imesa
)
459 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
461 if (imesa
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0) {
462 imesa
->numClipRects
= dPriv
->numClipRects
;
463 imesa
->pClipRects
= dPriv
->pClipRects
;
464 imesa
->drawX
= dPriv
->x
;
465 imesa
->drawY
= dPriv
->y
;
467 imesa
->numClipRects
= dPriv
->numBackClipRects
;
468 imesa
->pClipRects
= dPriv
->pBackClipRects
;
469 imesa
->drawX
= dPriv
->backX
;
470 imesa
->drawY
= dPriv
->backY
;
473 i830EmitDrawingRectangle( imesa
);
474 imesa
->upload_cliprects
= GL_TRUE
;
477 static void i830XMesaWindowMoved( i830ContextPtr imesa
)
479 switch (imesa
->glCtx
->Color
._DrawDestMask
[0]) {
480 case DD_FRONT_LEFT_BIT
:
481 i830XMesaSetFrontClipRects( imesa
);
483 case DD_BACK_LEFT_BIT
:
484 i830XMesaSetBackClipRects( imesa
);
487 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
488 i830XMesaSetFrontClipRects( imesa
);
492 GLboolean
i830UnbindContext(__DRIcontextPrivate
*driContextPriv
)
494 i830ContextPtr imesa
= (i830ContextPtr
) driContextPriv
->driverPrivate
;
498 /* Might want to change this so texblend isn't always updated */
499 imesa
->dirty
|= (I830_UPLOAD_CTX
|
500 I830_UPLOAD_BUFFERS
|
501 I830_UPLOAD_STIPPLE
|
502 I830_UPLOAD_TEXBLEND0
|
503 I830_UPLOAD_TEXBLEND1
|
504 I830_UPLOAD_TEXBLEND2
|
505 I830_UPLOAD_TEXBLEND3
);
507 for ( i
= 0 ; i
< imesa
->glCtx
->Const
.MaxTextureUnits
; i
++ ) {
508 if (imesa
->CurrentTexObj
[i
]) imesa
->dirty
|= I830_UPLOAD_TEX_N( i
);
514 GLboolean
i830MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
515 __DRIdrawablePrivate
*driDrawPriv
,
516 __DRIdrawablePrivate
*driReadPriv
)
519 if (driContextPriv
) {
520 i830ContextPtr imesa
= (i830ContextPtr
) driContextPriv
->driverPrivate
;
522 if ( imesa
->driDrawable
!= driDrawPriv
) {
523 imesa
->driDrawable
= driDrawPriv
;
524 i830XMesaWindowMoved( imesa
);
525 imesa
->mesa_drawable
= driDrawPriv
;
528 imesa
->driReadable
= driReadPriv
;
530 _mesa_make_current2(imesa
->glCtx
,
531 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
532 (GLframebuffer
*) driReadPriv
->driverPrivate
);
534 _mesa_make_current(0,0);
540 void i830GetLock( i830ContextPtr imesa
, GLuint flags
)
542 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
543 __DRIscreenPrivate
*sPriv
= imesa
->driScreen
;
544 I830SAREAPtr sarea
= imesa
->sarea
;
545 int me
= imesa
->hHWContext
;
548 drmGetLock(imesa
->driFd
, imesa
->hHWContext
, flags
);
550 /* If the window moved, may need to set a new cliprect now.
552 * NOTE: This releases and regains the hw lock, so all state
553 * checking must be done *after* this call:
555 DRI_VALIDATE_DRAWABLE_INFO( sPriv
, dPriv
);
557 /* If we lost context, need to dump all registers to hardware.
558 * Note that we don't care about 2d contexts, even if they perform
559 * accelerated commands, so the DRI locking in the X server is even
560 * more broken than usual.
563 if (sarea
->ctxOwner
!= me
) {
564 imesa
->upload_cliprects
= GL_TRUE
;
565 imesa
->dirty
|= (I830_UPLOAD_CTX
|
566 I830_UPLOAD_BUFFERS
|
567 I830_UPLOAD_STIPPLE
);
569 for ( i
= 0 ; i
< imesa
->glCtx
->Const
.MaxTextureUnits
; i
++ ) {
570 if(imesa
->CurrentTexObj
[i
]) imesa
->dirty
|= I830_UPLOAD_TEX_N( i
);
571 if(imesa
->TexBlendWordsUsed
[i
]) imesa
->dirty
|= I830_UPLOAD_TEXBLEND_N( i
);
574 sarea
->perf_boxes
= imesa
->perf_boxes
| I830_BOX_LOST_CONTEXT
;
575 sarea
->ctxOwner
= me
;
578 /* Shared texture managment - if another client has played with
579 * texture space, figure out which if any of our textures have been
580 * ejected, and update our global LRU.
583 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
584 DRI_AGE_TEXTURES( imesa
->texture_heaps
[ i
] );
587 if (imesa
->lastStamp
!= dPriv
->lastStamp
) {
588 i830XMesaWindowMoved( imesa
);
589 imesa
->lastStamp
= dPriv
->lastStamp
;
592 sarea
->last_quiescent
= -1; /* just kill it for now */
595 void i830SwapBuffers( __DRIdrawablePrivate
*dPriv
)
597 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
598 i830ContextPtr imesa
;
600 imesa
= (i830ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
602 if (ctx
->Visual
.doubleBufferMode
) {
603 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
604 if ( 0 /*imesa->doPageFlip*/ ) { /* doPageFlip is never set !!! */
605 i830PageFlip( dPriv
);
607 i830CopyBuffer( dPriv
);
611 /* XXX this shouldn't be an error but we can't handle it for now */
612 _mesa_problem(NULL
, "%s: drawable has no context!\n", __FUNCTION__
);