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 $ */
31 * Jeff Hartmann <jhartmann@2d3d.com>
32 * Graeme Fisher <graeme@2d3d.co.za>
33 * Abraham vd Merwe <abraham@2d3d.co.za>
35 * Heavily Based on I810 driver written by:
36 * Keith Whitwell <keith@tungstengraphics.com>
42 #include "simple_list.h"
43 #include "extensions.h"
46 #include "swrast/swrast.h"
47 #include "swrast_setup/swrast_setup.h"
49 #include "array_cache/acache.h"
51 #include "tnl/t_pipeline.h"
53 #include "drivers/common/driverfuncs.h"
55 #include "i830_screen.h"
58 #include "i830_state.h"
60 #include "i830_span.h"
61 #include "i830_tris.h"
62 #include "i830_ioctl.h"
70 /***************************************
71 * Mesa's Driver Functions
72 ***************************************/
74 #define DRIVER_DATE "20021115"
77 const char __driConfigOptions
[] = { 0 };
78 const GLuint __driNConfigOptions
= 0;
80 static const GLubyte
*i830DDGetString( GLcontext
*ctx
, GLenum name
)
83 static char buffer
[128];
87 switch (I830_CONTEXT(ctx
)->i830Screen
->deviceID
) {
89 return (GLubyte
*)"2d3D, Inc";
92 return (GLubyte
*)"VA Linux, Inc";
94 case PCI_CHIP_I855_GM
:
97 return (GLubyte
*)"Tungsten Graphics, Inc";
102 switch (I830_CONTEXT(ctx
)->i830Screen
->deviceID
) {
104 chipset
= "Intel(R) 845G"; break;
105 case PCI_CHIP_I830_M
:
106 chipset
= "Intel(R) 830M"; break;
107 case PCI_CHIP_I855_GM
:
108 chipset
= "Intel(R) 852GM/855GM"; break;
109 case PCI_CHIP_I865_G
:
110 chipset
= "Intel(R) 865G"; break;
112 chipset
= "Unknown Intel Chipset"; break;
115 (void) driGetRendererString( buffer
, chipset
, DRIVER_DATE
, 0 );
116 return (GLubyte
*) buffer
;
123 static void i830BufferSize(GLframebuffer
*buffer
,
124 GLuint
*width
, GLuint
*height
)
126 GET_CURRENT_CONTEXT(ctx
);
127 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
128 /* Need to lock to make sure the driDrawable is uptodate. This
129 * information is used to resize Mesa's software buffers, so it has
132 LOCK_HARDWARE(imesa
);
133 *width
= imesa
->driDrawable
->w
;
134 *height
= imesa
->driDrawable
->h
;
135 UNLOCK_HARDWARE(imesa
);
139 /* Extension strings exported by the i830 driver.
141 static const char * const card_extensions
[] =
143 "GL_ARB_multisample",
144 "GL_ARB_multitexture",
145 "GL_ARB_texture_border_clamp",
146 "GL_ARB_texture_compression",
147 "GL_ARB_texture_env_add",
148 "GL_ARB_texture_env_combine",
149 "GL_ARB_texture_env_dot3",
150 "GL_ARB_texture_mirrored_repeat",
151 "GL_EXT_blend_color",
152 "GL_EXT_blend_func_separate",
153 "GL_EXT_blend_minmax",
154 "GL_EXT_blend_subtract",
156 "GL_EXT_secondary_color",
157 "GL_EXT_stencil_wrap",
158 "GL_EXT_texture_edge_clamp",
159 "GL_EXT_texture_env_combine",
160 "GL_EXT_texture_env_dot3",
161 "GL_EXT_texture_filter_anisotropic",
162 "GL_EXT_texture_lod_bias",
163 "GL_EXT_texture_rectangle",
164 "GL_MESA_ycbcr_texture",
165 "GL_SGIS_generate_mipmap",
170 extern const struct tnl_pipeline_stage _i830_render_stage
;
172 static const struct tnl_pipeline_stage
*i830_pipeline
[] = {
173 &_tnl_vertex_transform_stage
,
174 &_tnl_normal_transform_stage
,
175 &_tnl_lighting_stage
,
176 &_tnl_fog_coordinate_stage
,
178 &_tnl_texture_transform_stage
,
179 /* REMOVE: point attenuation stage */
181 &_i830_render_stage
, /* ADD: unclipped rastersetup-to-dma */
188 static const struct dri_debug_control debug_control
[] =
190 { "fall", DEBUG_FALLBACKS
},
191 { "tex", DEBUG_TEXTURE
},
192 { "ioctl", DEBUG_IOCTL
},
193 { "prim", DEBUG_PRIMS
},
194 { "vert", DEBUG_VERTS
},
195 { "state", DEBUG_STATE
},
196 { "verb", DEBUG_VERBOSE
},
197 { "dri", DEBUG_DRI
},
198 { "dma", DEBUG_DMA
},
199 { "san", DEBUG_SANITY
},
200 { "sync", DEBUG_SYNC
},
201 { "sleep", DEBUG_SLEEP
},
206 GLboolean
i830CreateContext( const __GLcontextModes
*mesaVis
,
207 __DRIcontextPrivate
*driContextPriv
,
208 void *sharedContextPrivate
)
210 GLcontext
*ctx
, *shareCtx
;
211 i830ContextPtr imesa
;
212 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
213 i830ScreenPrivate
*screen
= (i830ScreenPrivate
*)sPriv
->private;
214 I830SAREAPtr saPriv
=(I830SAREAPtr
)
215 (((GLubyte
*)sPriv
->pSAREA
)+screen
->sarea_priv_offset
);
216 struct dd_function_table functions
;
218 /* Allocate i830 context */
219 imesa
= (i830ContextPtr
) CALLOC_STRUCT(i830_context_t
);
223 /* Init default driver functions then plug in our I830-specific functions
224 * (the texture functions are especially important)
226 _mesa_init_driver_functions(&functions
);
227 i830InitIoctlFuncs(&functions
);
228 i830InitTextureFuncs(&functions
);
230 /* Allocate the Mesa context */
231 if (sharedContextPrivate
)
232 shareCtx
= ((i830ContextPtr
) sharedContextPrivate
)->glCtx
;
235 imesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
236 &functions
, (void*) imesa
);
241 driContextPriv
->driverPrivate
= imesa
;
244 imesa
->i830Screen
= screen
;
245 imesa
->driScreen
= sPriv
;
246 imesa
->sarea
= saPriv
;
247 imesa
->glBuffer
= NULL
;
250 (void) memset( imesa
->texture_heaps
, 0, sizeof( imesa
->texture_heaps
) );
251 make_empty_list( & imesa
->swapped
);
254 imesa
->texture_heaps
[0] = driCreateTextureHeap( 0, imesa
,
258 imesa
->sarea
->texList
,
259 (unsigned *) & imesa
->sarea
->texAge
, /* XXX shouldn't need cast! */
261 sizeof( struct i830_texture_object_t
),
262 (destroy_texture_object_t
*) i830DestroyTexObj
);
265 /* Set the maximum texture size small enough that we can guarantee
266 * that both texture units can bind a maximal texture and have them
271 ctx
->Const
.MaxTextureUnits
= 2;
272 ctx
->Const
.MaxTextureImageUnits
= 2;
273 ctx
->Const
.MaxTextureCoordUnits
= 2;
275 /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
276 * FIXME: packed, but they're not in Intel graphics hardware.
278 driCalculateMaxTextureLevels( imesa
->texture_heaps
,
282 11, /* max 2D texture size is 2048x2048 */
283 0, /* 3D textures unsupported */
284 0, /* cube textures unsupported. */
285 0, /* texture rectangles unsupported. */
289 ctx
->Const
.MaxTextureMaxAnisotropy
= 2.0;
291 ctx
->Const
.MinLineWidth
= 1.0;
292 ctx
->Const
.MinLineWidthAA
= 1.0;
293 ctx
->Const
.MaxLineWidth
= 3.0;
294 ctx
->Const
.MaxLineWidthAA
= 3.0;
295 ctx
->Const
.LineWidthGranularity
= 1.0;
297 ctx
->Const
.MinPointSize
= 1.0;
298 ctx
->Const
.MinPointSizeAA
= 1.0;
299 ctx
->Const
.MaxPointSize
= 255.0;
300 ctx
->Const
.MaxPointSizeAA
= 3.0;
301 ctx
->Const
.PointSizeGranularity
= 1.0;
303 ctx
->Driver
.GetBufferSize
= i830BufferSize
;
304 ctx
->Driver
.ResizeBuffers
= _swrast_alloc_buffers
;
305 ctx
->Driver
.GetString
= i830DDGetString
;
308 ctx
->DriverCtx
= (void *) imesa
;
311 /* Initialize the software rasterizer and helper modules. */
312 _swrast_CreateContext( ctx
);
313 _ac_CreateContext( ctx
);
314 _tnl_CreateContext( ctx
);
315 _swsetup_CreateContext( ctx
);
317 /* Install the customized pipeline: */
318 _tnl_destroy_pipeline( ctx
);
319 _tnl_install_pipeline( ctx
, i830_pipeline
);
321 /* Configure swrast to match hardware characteristics: */
322 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
323 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
326 imesa
->hHWContext
= driContextPriv
->hHWContext
;
327 imesa
->driFd
= sPriv
->fd
;
328 imesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
329 imesa
->hw_stencil
= mesaVis
->stencilBits
&& mesaVis
->depthBits
== 24;
331 switch(mesaVis
->depthBits
) {
333 imesa
->depth_scale
= 1.0/0xffff;
334 imesa
->depth_clear_mask
= ~0;
335 imesa
->ClearDepth
= 0xffff;
338 imesa
->depth_scale
= 1.0/0xffffff;
339 imesa
->depth_clear_mask
= 0x00ffffff;
340 imesa
->stencil_clear_mask
= 0xff000000;
341 imesa
->ClearDepth
= 0x00ffffff;
343 case 32: /* Not supported */
347 /* Completely disable stenciling for now, there are some serious issues
351 imesa
->hw_stencil
= 0;
354 imesa
->RenderIndex
= ~0;
356 imesa
->upload_cliprects
= GL_TRUE
;
358 imesa
->CurrentTexObj
[0] = 0;
359 imesa
->CurrentTexObj
[1] = 0;
361 imesa
->do_irqs
= (imesa
->i830Screen
->irq_active
&&
362 !getenv("I830_NO_IRQS"));
364 _math_matrix_ctr (&imesa
->ViewportMatrix
);
366 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
367 /* XXX these should really go right after _mesa_init_driver_functions() */
368 i830DDInitStateFuncs( ctx
);
369 i830InitTriFuncs (ctx
);
370 i830DDInitSpanFuncs( ctx
);
371 i830DDInitState (ctx
);
373 driInitTextureObjects( ctx
, & imesa
->swapped
,
374 DRI_TEXMGR_DO_TEXTURE_2D
375 | DRI_TEXMGR_DO_TEXTURE_RECT
);
378 I830_DEBUG
= driParseDebugString( getenv( "I830_DEBUG" ),
380 I830_DEBUG
|= driParseDebugString( getenv( "INTEL_DEBUG" ),
384 if (getenv("I830_NO_RAST") ||
385 getenv("INTEL_NO_RAST")) {
386 fprintf(stderr
, "disabling 3D rasterization\n");
387 FALLBACK(imesa
, I830_FALLBACK_USER
, 1);
393 void i830DestroyContext(__DRIcontextPrivate
*driContextPriv
)
395 i830ContextPtr imesa
= (i830ContextPtr
) driContextPriv
->driverPrivate
;
397 assert(imesa
); /* should never be null */
399 GLboolean release_texture_heaps
;
402 release_texture_heaps
= (imesa
->glCtx
->Shared
->RefCount
== 1);
403 _swsetup_DestroyContext (imesa
->glCtx
);
404 _tnl_DestroyContext (imesa
->glCtx
);
405 _ac_DestroyContext (imesa
->glCtx
);
406 _swrast_DestroyContext (imesa
->glCtx
);
408 /* free the Mesa context */
409 imesa
->glCtx
->DriverCtx
= NULL
;
410 _mesa_destroy_context(imesa
->glCtx
);
412 if ( release_texture_heaps
) {
413 /* This share group is about to go away, free our private
414 * texture object data.
418 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
419 driDestroyTextureHeap( imesa
->texture_heaps
[ i
] );
420 imesa
->texture_heaps
[ i
] = NULL
;
423 assert( is_empty_list( & imesa
->swapped
) );
430 void i830XMesaSetFrontClipRects( i830ContextPtr imesa
)
432 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
434 imesa
->numClipRects
= dPriv
->numClipRects
;
435 imesa
->pClipRects
= dPriv
->pClipRects
;
436 imesa
->drawX
= dPriv
->x
;
437 imesa
->drawY
= dPriv
->y
;
439 i830EmitDrawingRectangle( imesa
);
440 imesa
->upload_cliprects
= GL_TRUE
;
443 void i830XMesaSetBackClipRects( i830ContextPtr imesa
)
445 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
447 if (imesa
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0) {
448 imesa
->numClipRects
= dPriv
->numClipRects
;
449 imesa
->pClipRects
= dPriv
->pClipRects
;
450 imesa
->drawX
= dPriv
->x
;
451 imesa
->drawY
= dPriv
->y
;
453 imesa
->numClipRects
= dPriv
->numBackClipRects
;
454 imesa
->pClipRects
= dPriv
->pBackClipRects
;
455 imesa
->drawX
= dPriv
->backX
;
456 imesa
->drawY
= dPriv
->backY
;
459 i830EmitDrawingRectangle( imesa
);
460 imesa
->upload_cliprects
= GL_TRUE
;
463 static void i830XMesaWindowMoved( i830ContextPtr imesa
)
465 switch (imesa
->glCtx
->Color
._DrawDestMask
) {
467 i830XMesaSetFrontClipRects( imesa
);
470 i830XMesaSetBackClipRects( imesa
);
473 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
474 i830XMesaSetFrontClipRects( imesa
);
478 GLboolean
i830UnbindContext(__DRIcontextPrivate
*driContextPriv
)
480 i830ContextPtr imesa
= (i830ContextPtr
) driContextPriv
->driverPrivate
;
482 /* Might want to change this so texblend isn't always updated */
483 imesa
->dirty
|= (I830_UPLOAD_CTX
|
484 I830_UPLOAD_BUFFERS
|
485 I830_UPLOAD_STIPPLE
|
486 I830_UPLOAD_TEXBLEND0
|
487 I830_UPLOAD_TEXBLEND1
);
489 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I830_UPLOAD_TEX0
;
490 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I830_UPLOAD_TEX1
;
495 GLboolean
i830MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
496 __DRIdrawablePrivate
*driDrawPriv
,
497 __DRIdrawablePrivate
*driReadPriv
)
500 if (driContextPriv
) {
501 i830ContextPtr imesa
= (i830ContextPtr
) driContextPriv
->driverPrivate
;
503 if ( imesa
->driDrawable
!= driDrawPriv
) {
504 /* Shouldn't the readbuffer be stored also? */
505 imesa
->driDrawable
= driDrawPriv
;
506 i830XMesaWindowMoved( imesa
);
509 _mesa_make_current2(imesa
->glCtx
,
510 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
511 (GLframebuffer
*) driReadPriv
->driverPrivate
);
513 if (!imesa
->glCtx
->Viewport
.Width
)
514 _mesa_set_viewport(imesa
->glCtx
, 0, 0,
515 driDrawPriv
->w
, driDrawPriv
->h
);
517 _mesa_make_current(0,0);
523 void i830GetLock( i830ContextPtr imesa
, GLuint flags
)
525 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
526 __DRIscreenPrivate
*sPriv
= imesa
->driScreen
;
527 I830SAREAPtr sarea
= imesa
->sarea
;
528 int me
= imesa
->hHWContext
;
531 drmGetLock(imesa
->driFd
, imesa
->hHWContext
, flags
);
533 /* If the window moved, may need to set a new cliprect now.
535 * NOTE: This releases and regains the hw lock, so all state
536 * checking must be done *after* this call:
538 DRI_VALIDATE_DRAWABLE_INFO( sPriv
, dPriv
);
540 /* If we lost context, need to dump all registers to hardware.
541 * Note that we don't care about 2d contexts, even if they perform
542 * accelerated commands, so the DRI locking in the X server is even
543 * more broken than usual.
546 if (sarea
->ctxOwner
!= me
) {
547 imesa
->upload_cliprects
= GL_TRUE
;
548 imesa
->dirty
|= (I830_UPLOAD_CTX
|
549 I830_UPLOAD_BUFFERS
|
550 I830_UPLOAD_STIPPLE
);
552 if(imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I830_UPLOAD_TEX0
;
553 if(imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I830_UPLOAD_TEX1
;
554 if(imesa
->TexBlendWordsUsed
[0]) imesa
->dirty
|= I830_UPLOAD_TEXBLEND0
;
555 if(imesa
->TexBlendWordsUsed
[1]) imesa
->dirty
|= I830_UPLOAD_TEXBLEND1
;
557 sarea
->perf_boxes
= imesa
->perf_boxes
| I830_BOX_LOST_CONTEXT
;
558 sarea
->ctxOwner
= me
;
561 /* Shared texture managment - if another client has played with
562 * texture space, figure out which if any of our textures have been
563 * ejected, and update our global LRU.
566 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
567 DRI_AGE_TEXTURES( imesa
->texture_heaps
[ i
] );
570 if (imesa
->lastStamp
!= dPriv
->lastStamp
) {
571 i830XMesaWindowMoved( imesa
);
572 imesa
->lastStamp
= dPriv
->lastStamp
;
575 sarea
->last_quiescent
= -1; /* just kill it for now */
578 void i830SwapBuffers( __DRIdrawablePrivate
*dPriv
)
580 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
581 i830ContextPtr imesa
;
583 imesa
= (i830ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
585 if (ctx
->Visual
.doubleBufferMode
) {
586 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
587 if ( 0 /*imesa->doPageFlip*/ ) { /* doPageFlip is never set !!! */
588 i830PageFlip( dPriv
);
590 i830CopyBuffer( dPriv
);
594 /* XXX this shouldn't be an error but we can't handle it for now */
595 _mesa_problem(NULL
, "%s: drawable has no context!\n", __FUNCTION__
);