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 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
35 #include "main/glheader.h"
36 #include "main/context.h"
37 #include "main/matrix.h"
38 #include "main/simple_list.h"
39 #include "main/extensions.h"
40 #include "main/framebuffer.h"
41 #include "main/imports.h"
42 #include "main/points.h"
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
49 #include "tnl/t_pipeline.h"
51 #include "drivers/common/driverfuncs.h"
53 #include "i810screen.h"
56 #include "i810state.h"
61 #include "i810ioctl.h"
63 #include "drirenderbuffer.h"
70 PUBLIC
const char __driConfigOptions
[] = { 0 };
71 const GLuint __driNConfigOptions
= 0;
73 #define DRIVER_DATE "20050821"
75 static const GLubyte
*i810GetString( GLcontext
*ctx
, GLenum name
)
77 static char buffer
[128];
81 return (GLubyte
*)"Keith Whitwell";
83 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
86 switch (imesa
->i810Screen
->deviceID
) {
87 case PCI_CHIP_I810
: chipset
= "i810"; break;
88 case PCI_CHIP_I810_DC100
: chipset
= "i810 DC-100"; break;
89 case PCI_CHIP_I810_E
: chipset
= "i810E"; break;
90 case PCI_CHIP_I815
: chipset
= "i815"; break;
91 default: chipset
= "Unknown i810-class Chipset"; break;
94 (void) driGetRendererString( buffer
, chipset
, DRIVER_DATE
, 0 );
95 return (GLubyte
*) buffer
;
102 static void i810BufferSize(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
104 GET_CURRENT_CONTEXT(ctx
);
105 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
107 /* Need to lock to make sure the driDrawable is uptodate. This
108 * information is used to resize Mesa's software buffers, so it has
111 LOCK_HARDWARE(imesa
);
112 *width
= imesa
->driDrawable
->w
;
113 *height
= imesa
->driDrawable
->h
;
114 UNLOCK_HARDWARE(imesa
);
117 /* Extension strings exported by the i810 driver.
119 static const struct dri_extension card_extensions
[] =
121 { "GL_ARB_multitexture", NULL
},
122 { "GL_ARB_texture_env_add", NULL
},
123 { "GL_ARB_texture_env_combine", NULL
},
124 { "GL_ARB_texture_env_crossbar", NULL
},
125 { "GL_ARB_texture_mirrored_repeat", NULL
},
126 { "GL_EXT_stencil_wrap", NULL
},
127 { "GL_EXT_texture_edge_clamp", NULL
},
128 { "GL_EXT_texture_env_combine", NULL
},
129 { "GL_EXT_texture_lod_bias", NULL
},
130 { "GL_EXT_texture_rectangle", NULL
},
131 { "GL_MESA_ycbcr_texture", NULL
},
132 { "GL_NV_blend_square", NULL
},
133 { "GL_SGIS_generate_mipmap", NULL
},
137 extern const struct tnl_pipeline_stage _i810_render_stage
;
139 static const struct tnl_pipeline_stage
*i810_pipeline
[] = {
140 &_tnl_vertex_transform_stage
,
141 &_tnl_normal_transform_stage
,
142 &_tnl_lighting_stage
,
143 &_tnl_fog_coordinate_stage
,
145 &_tnl_texture_transform_stage
,
146 /* REMOVE: point attenuation stage */
148 &_i810_render_stage
, /* ADD: unclipped rastersetup-to-dma */
154 static const struct dri_debug_control debug_control
[] =
156 { "fall", DEBUG_FALLBACKS
},
157 { "tex", DEBUG_TEXTURE
},
158 { "ioctl", DEBUG_IOCTL
},
159 { "prim", DEBUG_PRIMS
},
160 { "vert", DEBUG_VERTS
},
161 { "state", DEBUG_STATE
},
162 { "verb", DEBUG_VERBOSE
},
163 { "dri", DEBUG_DRI
},
164 { "dma", DEBUG_DMA
},
165 { "san", DEBUG_SANITY
},
166 { "sync", DEBUG_SYNC
},
167 { "sleep", DEBUG_SLEEP
},
172 i810CreateContext( const __GLcontextModes
*mesaVis
,
173 __DRIcontextPrivate
*driContextPriv
,
174 void *sharedContextPrivate
)
176 GLcontext
*ctx
, *shareCtx
;
177 i810ContextPtr imesa
;
178 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
179 i810ScreenPrivate
*i810Screen
= (i810ScreenPrivate
*)sPriv
->private;
180 I810SAREAPtr saPriv
= (I810SAREAPtr
)
181 (((GLubyte
*)sPriv
->pSAREA
) + i810Screen
->sarea_priv_offset
);
182 struct dd_function_table functions
;
184 /* Allocate i810 context */
185 imesa
= (i810ContextPtr
) CALLOC_STRUCT(i810_context_t
);
190 driContextPriv
->driverPrivate
= imesa
;
192 imesa
->i810Screen
= i810Screen
;
193 imesa
->driScreen
= sPriv
;
194 imesa
->sarea
= saPriv
;
195 imesa
->glBuffer
= NULL
;
197 /* Init default driver functions then plug in our I810-specific functions
198 * (the texture functions are especially important)
200 _mesa_init_driver_functions( &functions
);
201 i810InitIoctlFuncs( &functions
);
202 i810InitTextureFuncs( &functions
);
205 /* Allocate the Mesa context */
206 if (sharedContextPrivate
)
207 shareCtx
= ((i810ContextPtr
) sharedContextPrivate
)->glCtx
;
210 imesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
211 &functions
, (void*) imesa
);
217 (void) memset( imesa
->texture_heaps
, 0, sizeof( imesa
->texture_heaps
) );
218 make_empty_list( & imesa
->swapped
);
221 imesa
->texture_heaps
[0] = driCreateTextureHeap( 0, imesa
,
222 i810Screen
->textureSize
,
225 imesa
->sarea
->texList
,
226 (unsigned *) & imesa
->sarea
->texAge
, /* XXX we shouldn't cast! */
228 sizeof( struct i810_texture_object_t
),
229 (destroy_texture_object_t
*) i810DestroyTexObj
);
233 /* Set the maximum texture size small enough that we can guarentee
234 * that both texture units can bind a maximal texture and have them
241 ctx
->Const
.MaxTextureUnits
= 2;
242 ctx
->Const
.MaxTextureImageUnits
= 2;
243 ctx
->Const
.MaxTextureCoordUnits
= 2;
246 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
247 * FIXME: packed, but they're not in Intel graphics hardware.
249 driCalculateMaxTextureLevels( imesa
->texture_heaps
,
253 11, /* max 2D texture size is 2048x2048 */
254 0, /* 3D textures unsupported */
255 0, /* cube textures unsupported. */
256 0, /* texture rectangles unsupported. */
261 ctx
->Const
.MinLineWidth
= 1.0;
262 ctx
->Const
.MinLineWidthAA
= 1.0;
263 ctx
->Const
.MaxLineWidth
= 3.0;
264 ctx
->Const
.MaxLineWidthAA
= 3.0;
265 ctx
->Const
.LineWidthGranularity
= 1.0;
267 ctx
->Const
.MinPointSize
= 1.0;
268 ctx
->Const
.MinPointSizeAA
= 1.0;
269 ctx
->Const
.MaxPointSize
= 3.0;
270 ctx
->Const
.MaxPointSizeAA
= 3.0;
271 ctx
->Const
.PointSizeGranularity
= 1.0;
273 /* reinitialize the context point state.
274 * It depend on constants in __GLcontextRec::Const
276 _mesa_init_point(ctx
);
278 ctx
->Driver
.GetBufferSize
= i810BufferSize
;
279 ctx
->Driver
.GetString
= i810GetString
;
283 ctx
->DriverCtx
= (void *) imesa
;
286 /* Initialize the software rasterizer and helper modules.
288 _swrast_CreateContext( ctx
);
289 _vbo_CreateContext( ctx
);
290 _tnl_CreateContext( ctx
);
291 _swsetup_CreateContext( ctx
);
293 /* Install the customized pipeline:
295 _tnl_destroy_pipeline( ctx
);
296 _tnl_install_pipeline( ctx
, i810_pipeline
);
298 /* Configure swrast and T&L to match hardware characteristics:
300 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
301 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
302 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
303 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
307 imesa
->hHWContext
= driContextPriv
->hHWContext
;
308 imesa
->driFd
= sPriv
->fd
;
309 imesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
311 imesa
->stipple_in_hw
= 1;
312 imesa
->RenderIndex
= ~0;
313 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
314 imesa
->upload_cliprects
= GL_TRUE
;
316 imesa
->CurrentTexObj
[0] = 0;
317 imesa
->CurrentTexObj
[1] = 0;
319 _math_matrix_ctr( &imesa
->ViewportMatrix
);
321 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
322 /* XXX these should really go right after _mesa_init_driver_functions() */
323 i810InitStateFuncs( ctx
);
324 i810InitTriFuncs( ctx
);
325 i810InitSpanFuncs( ctx
);
327 i810InitState( ctx
);
330 I810_DEBUG
= driParseDebugString( getenv( "I810_DEBUG" ),
332 I810_DEBUG
|= driParseDebugString( getenv( "INTEL_DEBUG" ),
340 i810DestroyContext(__DRIcontextPrivate
*driContextPriv
)
342 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
344 assert(imesa
); /* should never be null */
346 GLboolean release_texture_heaps
;
349 release_texture_heaps
= (imesa
->glCtx
->Shared
->RefCount
== 1);
350 _swsetup_DestroyContext( imesa
->glCtx
);
351 _tnl_DestroyContext( imesa
->glCtx
);
352 _vbo_DestroyContext( imesa
->glCtx
);
353 _swrast_DestroyContext( imesa
->glCtx
);
355 i810FreeVB( imesa
->glCtx
);
357 /* free the Mesa context */
358 imesa
->glCtx
->DriverCtx
= NULL
;
359 _mesa_destroy_context(imesa
->glCtx
);
360 if ( release_texture_heaps
) {
361 /* This share group is about to go away, free our private
362 * texture object data.
366 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
367 driDestroyTextureHeap( imesa
->texture_heaps
[ i
] );
368 imesa
->texture_heaps
[ i
] = NULL
;
371 assert( is_empty_list( & imesa
->swapped
) );
379 void i810XMesaSetFrontClipRects( i810ContextPtr imesa
)
381 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
383 imesa
->numClipRects
= dPriv
->numClipRects
;
384 imesa
->pClipRects
= dPriv
->pClipRects
;
385 imesa
->drawX
= dPriv
->x
;
386 imesa
->drawY
= dPriv
->y
;
388 i810EmitDrawingRectangle( imesa
);
389 imesa
->upload_cliprects
= GL_TRUE
;
393 void i810XMesaSetBackClipRects( i810ContextPtr imesa
)
395 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
397 if (imesa
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0)
399 imesa
->numClipRects
= dPriv
->numClipRects
;
400 imesa
->pClipRects
= dPriv
->pClipRects
;
401 imesa
->drawX
= dPriv
->x
;
402 imesa
->drawY
= dPriv
->y
;
404 imesa
->numClipRects
= dPriv
->numBackClipRects
;
405 imesa
->pClipRects
= dPriv
->pBackClipRects
;
406 imesa
->drawX
= dPriv
->backX
;
407 imesa
->drawY
= dPriv
->backY
;
410 i810EmitDrawingRectangle( imesa
);
411 imesa
->upload_cliprects
= GL_TRUE
;
415 static void i810XMesaWindowMoved( i810ContextPtr imesa
)
417 /* Determine current color drawing buffer */
418 switch (imesa
->glCtx
->DrawBuffer
->_ColorDrawBufferIndexes
[0]) {
419 case BUFFER_FRONT_LEFT
:
420 i810XMesaSetFrontClipRects( imesa
);
422 case BUFFER_BACK_LEFT
:
423 i810XMesaSetBackClipRects( imesa
);
426 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
427 i810XMesaSetFrontClipRects( imesa
);
433 i810UnbindContext(__DRIcontextPrivate
*driContextPriv
)
435 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
437 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
438 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
439 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
447 i810MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
448 __DRIdrawablePrivate
*driDrawPriv
,
449 __DRIdrawablePrivate
*driReadPriv
)
451 if (driContextPriv
) {
452 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
454 /* Shouldn't the readbuffer be stored also?
456 imesa
->driDrawable
= driDrawPriv
;
458 _mesa_make_current(imesa
->glCtx
,
459 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
460 (GLframebuffer
*) driReadPriv
->driverPrivate
);
462 /* Are these necessary?
464 i810XMesaWindowMoved( imesa
);
467 _mesa_make_current(NULL
, NULL
, NULL
);
474 i810UpdatePageFlipping( i810ContextPtr imesa
)
476 GLcontext
*ctx
= imesa
->glCtx
;
479 /* Determine current color drawing buffer */
480 switch (ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[0]) {
481 case BUFFER_FRONT_LEFT
:
484 case BUFFER_BACK_LEFT
:
491 if ( imesa
->sarea
->pf_current_page
== 1 )
494 driFlipRenderbuffers(ctx
->WinSysDrawBuffer
, front
);
497 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->fbOffset
| imesa
->i810Screen
->backPitchBits
;
499 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->backOffset
| imesa
->i810Screen
->backPitchBits
;
502 imesa
->dirty
|= I810_UPLOAD_BUFFERS
;
505 void i810GetLock( i810ContextPtr imesa
, GLuint flags
)
507 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
508 __DRIscreenPrivate
*sPriv
= imesa
->driScreen
;
509 I810SAREAPtr sarea
= imesa
->sarea
;
510 int me
= imesa
->hHWContext
;
513 drmGetLock(imesa
->driFd
, imesa
->hHWContext
, flags
);
515 /* If the window moved, may need to set a new cliprect now.
517 * NOTE: This releases and regains the hw lock, so all state
518 * checking must be done *after* this call:
520 DRI_VALIDATE_DRAWABLE_INFO(sPriv
, dPriv
);
523 /* If we lost context, need to dump all registers to hardware.
524 * Note that we don't care about 2d contexts, even if they perform
525 * accelerated commands, so the DRI locking in the X server is even
526 * more broken than usual.
528 if (sarea
->ctxOwner
!= me
) {
529 driUpdateFramebufferSize(imesa
->glCtx
, dPriv
);
530 imesa
->upload_cliprects
= GL_TRUE
;
531 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
532 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
533 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
534 sarea
->ctxOwner
= me
;
537 /* Shared texture managment - if another client has played with
538 * texture space, figure out which if any of our textures have been
539 * ejected, and update our global LRU.
541 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
542 DRI_AGE_TEXTURES( imesa
->texture_heaps
[ i
] );
545 if (imesa
->lastStamp
!= dPriv
->lastStamp
) {
546 i810UpdatePageFlipping( imesa
);
547 i810XMesaWindowMoved( imesa
);
548 imesa
->lastStamp
= dPriv
->lastStamp
;
554 i810SwapBuffers( __DRIdrawablePrivate
*dPriv
)
556 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
557 i810ContextPtr imesa
;
559 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
561 if (ctx
->Visual
.doubleBufferMode
) {
562 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
563 if ( imesa
->sarea
->pf_active
) {
564 i810PageFlip( dPriv
);
566 i810CopyBuffer( dPriv
);
571 /* XXX this shouldn't be an error but we can't handle it for now */
572 _mesa_problem(NULL
, "i810SwapBuffers: drawable has no context!\n");