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"
41 #include "framebuffer.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"
66 #define need_GL_ARB_multisample
67 #define need_GL_ARB_texture_compression
68 #define need_GL_ARB_vertex_buffer_object
69 #include "extension_helper.h"
75 PUBLIC
const char __driConfigOptions
[] = { 0 };
76 const GLuint __driNConfigOptions
= 0;
78 #define DRIVER_DATE "20050821"
80 static const GLubyte
*i810GetString( GLcontext
*ctx
, GLenum name
)
82 static char buffer
[128];
86 return (GLubyte
*)"Keith Whitwell";
88 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
91 switch (imesa
->i810Screen
->deviceID
) {
92 case PCI_CHIP_I810
: chipset
= "i810"; break;
93 case PCI_CHIP_I810_DC100
: chipset
= "i810 DC-100"; break;
94 case PCI_CHIP_I810_E
: chipset
= "i810E"; break;
95 case PCI_CHIP_I815
: chipset
= "i815"; break;
96 default: chipset
= "Unknown i810-class Chipset"; break;
99 (void) driGetRendererString( buffer
, chipset
, DRIVER_DATE
, 0 );
100 return (GLubyte
*) buffer
;
107 static void i810BufferSize(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
109 GET_CURRENT_CONTEXT(ctx
);
110 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
112 /* Need to lock to make sure the driDrawable is uptodate. This
113 * information is used to resize Mesa's software buffers, so it has
116 LOCK_HARDWARE(imesa
);
117 *width
= imesa
->driDrawable
->w
;
118 *height
= imesa
->driDrawable
->h
;
119 UNLOCK_HARDWARE(imesa
);
122 /* Extension strings exported by the i810 driver.
124 const struct dri_extension card_extensions
[] =
126 { "GL_ARB_multisample", GL_ARB_multisample_functions
},
127 { "GL_ARB_multitexture", NULL
},
128 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions
},
129 { "GL_ARB_texture_env_add", NULL
},
130 { "GL_ARB_texture_env_combine", NULL
},
131 { "GL_ARB_texture_env_crossbar", NULL
},
132 { "GL_ARB_texture_mirrored_repeat", NULL
},
133 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions
},
134 { "GL_EXT_stencil_wrap", NULL
},
135 { "GL_EXT_texture_edge_clamp", NULL
},
136 { "GL_EXT_texture_env_combine", NULL
},
137 { "GL_EXT_texture_lod_bias", NULL
},
138 { "GL_EXT_texture_rectangle", NULL
},
139 { "GL_MESA_ycbcr_texture", NULL
},
140 { "GL_NV_blend_square", NULL
},
141 { "GL_SGIS_generate_mipmap", NULL
},
145 extern const struct tnl_pipeline_stage _i810_render_stage
;
147 static const struct tnl_pipeline_stage
*i810_pipeline
[] = {
148 &_tnl_vertex_transform_stage
,
149 &_tnl_normal_transform_stage
,
150 &_tnl_lighting_stage
,
151 &_tnl_fog_coordinate_stage
,
153 &_tnl_texture_transform_stage
,
154 /* REMOVE: point attenuation stage */
156 &_i810_render_stage
, /* ADD: unclipped rastersetup-to-dma */
162 static const struct dri_debug_control debug_control
[] =
164 { "fall", DEBUG_FALLBACKS
},
165 { "tex", DEBUG_TEXTURE
},
166 { "ioctl", DEBUG_IOCTL
},
167 { "prim", DEBUG_PRIMS
},
168 { "vert", DEBUG_VERTS
},
169 { "state", DEBUG_STATE
},
170 { "verb", DEBUG_VERBOSE
},
171 { "dri", DEBUG_DRI
},
172 { "dma", DEBUG_DMA
},
173 { "san", DEBUG_SANITY
},
174 { "sync", DEBUG_SYNC
},
175 { "sleep", DEBUG_SLEEP
},
180 i810CreateContext( const __GLcontextModes
*mesaVis
,
181 __DRIcontextPrivate
*driContextPriv
,
182 void *sharedContextPrivate
)
184 GLcontext
*ctx
, *shareCtx
;
185 i810ContextPtr imesa
;
186 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
187 i810ScreenPrivate
*i810Screen
= (i810ScreenPrivate
*)sPriv
->private;
188 I810SAREAPtr saPriv
= (I810SAREAPtr
)
189 (((GLubyte
*)sPriv
->pSAREA
) + i810Screen
->sarea_priv_offset
);
190 struct dd_function_table functions
;
192 /* Allocate i810 context */
193 imesa
= (i810ContextPtr
) CALLOC_STRUCT(i810_context_t
);
198 driContextPriv
->driverPrivate
= imesa
;
200 imesa
->i810Screen
= i810Screen
;
201 imesa
->driScreen
= sPriv
;
202 imesa
->sarea
= saPriv
;
203 imesa
->glBuffer
= NULL
;
205 /* Init default driver functions then plug in our I810-specific functions
206 * (the texture functions are especially important)
208 _mesa_init_driver_functions( &functions
);
209 i810InitIoctlFuncs( &functions
);
210 i810InitTextureFuncs( &functions
);
213 /* Allocate the Mesa context */
214 if (sharedContextPrivate
)
215 shareCtx
= ((i810ContextPtr
) sharedContextPrivate
)->glCtx
;
218 imesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
219 &functions
, (void*) imesa
);
225 (void) memset( imesa
->texture_heaps
, 0, sizeof( imesa
->texture_heaps
) );
226 make_empty_list( & imesa
->swapped
);
229 imesa
->texture_heaps
[0] = driCreateTextureHeap( 0, imesa
,
230 i810Screen
->textureSize
,
233 imesa
->sarea
->texList
,
234 (unsigned *) & imesa
->sarea
->texAge
, /* XXX we shouldn't cast! */
236 sizeof( struct i810_texture_object_t
),
237 (destroy_texture_object_t
*) i810DestroyTexObj
);
241 /* Set the maximum texture size small enough that we can guarentee
242 * that both texture units can bind a maximal texture and have them
249 ctx
->Const
.MaxTextureUnits
= 2;
250 ctx
->Const
.MaxTextureImageUnits
= 2;
251 ctx
->Const
.MaxTextureCoordUnits
= 2;
254 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
255 * FIXME: packed, but they're not in Intel graphics hardware.
257 driCalculateMaxTextureLevels( imesa
->texture_heaps
,
261 11, /* max 2D texture size is 2048x2048 */
262 0, /* 3D textures unsupported */
263 0, /* cube textures unsupported. */
264 0, /* texture rectangles unsupported. */
269 ctx
->Const
.MinLineWidth
= 1.0;
270 ctx
->Const
.MinLineWidthAA
= 1.0;
271 ctx
->Const
.MaxLineWidth
= 3.0;
272 ctx
->Const
.MaxLineWidthAA
= 3.0;
273 ctx
->Const
.LineWidthGranularity
= 1.0;
275 ctx
->Const
.MinPointSize
= 1.0;
276 ctx
->Const
.MinPointSizeAA
= 1.0;
277 ctx
->Const
.MaxPointSize
= 3.0;
278 ctx
->Const
.MaxPointSizeAA
= 3.0;
279 ctx
->Const
.PointSizeGranularity
= 1.0;
281 ctx
->Driver
.GetBufferSize
= i810BufferSize
;
282 ctx
->Driver
.GetString
= i810GetString
;
286 ctx
->DriverCtx
= (void *) imesa
;
289 /* Initialize the software rasterizer and helper modules.
291 _swrast_CreateContext( ctx
);
292 _vbo_CreateContext( ctx
);
293 _tnl_CreateContext( ctx
);
294 _swsetup_CreateContext( ctx
);
296 /* Install the customized pipeline:
298 _tnl_destroy_pipeline( ctx
);
299 _tnl_install_pipeline( ctx
, i810_pipeline
);
301 /* Configure swrast and T&L to match hardware characteristics:
303 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
304 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
305 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
306 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
310 imesa
->hHWContext
= driContextPriv
->hHWContext
;
311 imesa
->driFd
= sPriv
->fd
;
312 imesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
314 imesa
->stipple_in_hw
= 1;
315 imesa
->RenderIndex
= ~0;
316 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
317 imesa
->upload_cliprects
= GL_TRUE
;
319 imesa
->CurrentTexObj
[0] = 0;
320 imesa
->CurrentTexObj
[1] = 0;
322 _math_matrix_ctr( &imesa
->ViewportMatrix
);
324 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
325 /* XXX these should really go right after _mesa_init_driver_functions() */
326 i810InitStateFuncs( ctx
);
327 i810InitTriFuncs( ctx
);
328 i810InitSpanFuncs( ctx
);
330 i810InitState( ctx
);
333 I810_DEBUG
= driParseDebugString( getenv( "I810_DEBUG" ),
335 I810_DEBUG
|= driParseDebugString( getenv( "INTEL_DEBUG" ),
343 i810DestroyContext(__DRIcontextPrivate
*driContextPriv
)
345 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
347 assert(imesa
); /* should never be null */
349 GLboolean release_texture_heaps
;
352 release_texture_heaps
= (imesa
->glCtx
->Shared
->RefCount
== 1);
353 _swsetup_DestroyContext( imesa
->glCtx
);
354 _tnl_DestroyContext( imesa
->glCtx
);
355 _vbo_DestroyContext( imesa
->glCtx
);
356 _swrast_DestroyContext( imesa
->glCtx
);
358 i810FreeVB( imesa
->glCtx
);
360 /* free the Mesa context */
361 imesa
->glCtx
->DriverCtx
= NULL
;
362 _mesa_destroy_context(imesa
->glCtx
);
363 if ( release_texture_heaps
) {
364 /* This share group is about to go away, free our private
365 * texture object data.
369 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
370 driDestroyTextureHeap( imesa
->texture_heaps
[ i
] );
371 imesa
->texture_heaps
[ i
] = NULL
;
374 assert( is_empty_list( & imesa
->swapped
) );
382 void i810XMesaSetFrontClipRects( i810ContextPtr imesa
)
384 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
386 imesa
->numClipRects
= dPriv
->numClipRects
;
387 imesa
->pClipRects
= dPriv
->pClipRects
;
388 imesa
->drawX
= dPriv
->x
;
389 imesa
->drawY
= dPriv
->y
;
391 i810EmitDrawingRectangle( imesa
);
392 imesa
->upload_cliprects
= GL_TRUE
;
396 void i810XMesaSetBackClipRects( i810ContextPtr imesa
)
398 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
400 if (imesa
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0)
402 imesa
->numClipRects
= dPriv
->numClipRects
;
403 imesa
->pClipRects
= dPriv
->pClipRects
;
404 imesa
->drawX
= dPriv
->x
;
405 imesa
->drawY
= dPriv
->y
;
407 imesa
->numClipRects
= dPriv
->numBackClipRects
;
408 imesa
->pClipRects
= dPriv
->pBackClipRects
;
409 imesa
->drawX
= dPriv
->backX
;
410 imesa
->drawY
= dPriv
->backY
;
413 i810EmitDrawingRectangle( imesa
);
414 imesa
->upload_cliprects
= GL_TRUE
;
418 static void i810XMesaWindowMoved( i810ContextPtr imesa
)
420 /* Determine current color drawing buffer */
421 switch (imesa
->glCtx
->DrawBuffer
->_ColorDrawBufferMask
[0]) {
422 case BUFFER_BIT_FRONT_LEFT
:
423 i810XMesaSetFrontClipRects( imesa
);
425 case BUFFER_BIT_BACK_LEFT
:
426 i810XMesaSetBackClipRects( imesa
);
429 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
430 i810XMesaSetFrontClipRects( imesa
);
436 i810UnbindContext(__DRIcontextPrivate
*driContextPriv
)
438 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
440 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
441 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
442 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
450 i810MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
451 __DRIdrawablePrivate
*driDrawPriv
,
452 __DRIdrawablePrivate
*driReadPriv
)
454 if (driContextPriv
) {
455 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
457 /* Shouldn't the readbuffer be stored also?
459 imesa
->driDrawable
= driDrawPriv
;
461 _mesa_make_current(imesa
->glCtx
,
462 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
463 (GLframebuffer
*) driReadPriv
->driverPrivate
);
465 /* Are these necessary?
467 i810XMesaWindowMoved( imesa
);
470 _mesa_make_current(NULL
, NULL
, NULL
);
477 i810UpdatePageFlipping( i810ContextPtr imesa
)
479 GLcontext
*ctx
= imesa
->glCtx
;
482 /* Determine current color drawing buffer */
483 switch (ctx
->DrawBuffer
->_ColorDrawBufferMask
[0]) {
484 case BUFFER_BIT_FRONT_LEFT
:
487 case BUFFER_BIT_BACK_LEFT
:
494 if ( imesa
->sarea
->pf_current_page
== 1 )
497 driFlipRenderbuffers(ctx
->WinSysDrawBuffer
, front
);
500 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->fbOffset
| imesa
->i810Screen
->backPitchBits
;
502 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->backOffset
| imesa
->i810Screen
->backPitchBits
;
505 imesa
->dirty
|= I810_UPLOAD_BUFFERS
;
508 void i810GetLock( i810ContextPtr imesa
, GLuint flags
)
510 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
511 __DRIscreenPrivate
*sPriv
= imesa
->driScreen
;
512 I810SAREAPtr sarea
= imesa
->sarea
;
513 int me
= imesa
->hHWContext
;
516 drmGetLock(imesa
->driFd
, imesa
->hHWContext
, flags
);
518 /* If the window moved, may need to set a new cliprect now.
520 * NOTE: This releases and regains the hw lock, so all state
521 * checking must be done *after* this call:
523 DRI_VALIDATE_DRAWABLE_INFO(sPriv
, dPriv
);
526 /* If we lost context, need to dump all registers to hardware.
527 * Note that we don't care about 2d contexts, even if they perform
528 * accelerated commands, so the DRI locking in the X server is even
529 * more broken than usual.
531 if (sarea
->ctxOwner
!= me
) {
532 driUpdateFramebufferSize(imesa
->glCtx
, dPriv
);
533 imesa
->upload_cliprects
= GL_TRUE
;
534 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
535 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
536 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
537 sarea
->ctxOwner
= me
;
540 /* Shared texture managment - if another client has played with
541 * texture space, figure out which if any of our textures have been
542 * ejected, and update our global LRU.
544 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
545 DRI_AGE_TEXTURES( imesa
->texture_heaps
[ i
] );
548 if (imesa
->lastStamp
!= dPriv
->lastStamp
) {
549 i810UpdatePageFlipping( imesa
);
550 i810XMesaWindowMoved( imesa
);
551 imesa
->lastStamp
= dPriv
->lastStamp
;
557 i810SwapBuffers( __DRIdrawablePrivate
*dPriv
)
559 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
560 i810ContextPtr imesa
;
562 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
564 if (ctx
->Visual
.doubleBufferMode
) {
565 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
566 if ( imesa
->sarea
->pf_active
) {
567 i810PageFlip( dPriv
);
569 i810CopyBuffer( dPriv
);
574 /* XXX this shouldn't be an error but we can't handle it for now */
575 _mesa_problem(NULL
, "i810SwapBuffers: drawable has no context!\n");