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 #include "extension_helper.h"
74 PUBLIC
const char __driConfigOptions
[] = { 0 };
75 const GLuint __driNConfigOptions
= 0;
77 #define DRIVER_DATE "20050821"
79 static const GLubyte
*i810GetString( GLcontext
*ctx
, GLenum name
)
81 static char buffer
[128];
85 return (GLubyte
*)"Keith Whitwell";
87 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
90 switch (imesa
->i810Screen
->deviceID
) {
91 case PCI_CHIP_I810
: chipset
= "i810"; break;
92 case PCI_CHIP_I810_DC100
: chipset
= "i810 DC-100"; break;
93 case PCI_CHIP_I810_E
: chipset
= "i810E"; break;
94 case PCI_CHIP_I815
: chipset
= "i815"; break;
95 default: chipset
= "Unknown i810-class Chipset"; break;
98 (void) driGetRendererString( buffer
, chipset
, DRIVER_DATE
, 0 );
99 return (GLubyte
*) buffer
;
106 static void i810BufferSize(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
108 GET_CURRENT_CONTEXT(ctx
);
109 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
111 /* Need to lock to make sure the driDrawable is uptodate. This
112 * information is used to resize Mesa's software buffers, so it has
115 LOCK_HARDWARE(imesa
);
116 *width
= imesa
->driDrawable
->w
;
117 *height
= imesa
->driDrawable
->h
;
118 UNLOCK_HARDWARE(imesa
);
121 /* Extension strings exported by the i810 driver.
123 const struct dri_extension card_extensions
[] =
125 { "GL_ARB_multisample", GL_ARB_multisample_functions
},
126 { "GL_ARB_multitexture", NULL
},
127 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions
},
128 { "GL_ARB_texture_env_add", NULL
},
129 { "GL_ARB_texture_env_combine", NULL
},
130 { "GL_ARB_texture_env_crossbar", NULL
},
131 { "GL_ARB_texture_mirrored_repeat", NULL
},
132 { "GL_EXT_stencil_wrap", NULL
},
133 { "GL_EXT_texture_edge_clamp", NULL
},
134 { "GL_EXT_texture_env_combine", NULL
},
135 { "GL_EXT_texture_lod_bias", NULL
},
136 { "GL_EXT_texture_rectangle", NULL
},
137 { "GL_MESA_ycbcr_texture", NULL
},
138 { "GL_NV_blend_square", NULL
},
139 { "GL_SGIS_generate_mipmap", NULL
},
143 extern const struct tnl_pipeline_stage _i810_render_stage
;
145 static const struct tnl_pipeline_stage
*i810_pipeline
[] = {
146 &_tnl_vertex_transform_stage
,
147 &_tnl_normal_transform_stage
,
148 &_tnl_lighting_stage
,
149 &_tnl_fog_coordinate_stage
,
151 &_tnl_texture_transform_stage
,
152 /* REMOVE: point attenuation stage */
154 &_i810_render_stage
, /* ADD: unclipped rastersetup-to-dma */
160 static const struct dri_debug_control debug_control
[] =
162 { "fall", DEBUG_FALLBACKS
},
163 { "tex", DEBUG_TEXTURE
},
164 { "ioctl", DEBUG_IOCTL
},
165 { "prim", DEBUG_PRIMS
},
166 { "vert", DEBUG_VERTS
},
167 { "state", DEBUG_STATE
},
168 { "verb", DEBUG_VERBOSE
},
169 { "dri", DEBUG_DRI
},
170 { "dma", DEBUG_DMA
},
171 { "san", DEBUG_SANITY
},
172 { "sync", DEBUG_SYNC
},
173 { "sleep", DEBUG_SLEEP
},
178 i810CreateContext( const __GLcontextModes
*mesaVis
,
179 __DRIcontextPrivate
*driContextPriv
,
180 void *sharedContextPrivate
)
182 GLcontext
*ctx
, *shareCtx
;
183 i810ContextPtr imesa
;
184 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
185 i810ScreenPrivate
*i810Screen
= (i810ScreenPrivate
*)sPriv
->private;
186 I810SAREAPtr saPriv
= (I810SAREAPtr
)
187 (((GLubyte
*)sPriv
->pSAREA
) + i810Screen
->sarea_priv_offset
);
188 struct dd_function_table functions
;
190 /* Allocate i810 context */
191 imesa
= (i810ContextPtr
) CALLOC_STRUCT(i810_context_t
);
196 driContextPriv
->driverPrivate
= imesa
;
198 imesa
->i810Screen
= i810Screen
;
199 imesa
->driScreen
= sPriv
;
200 imesa
->sarea
= saPriv
;
201 imesa
->glBuffer
= NULL
;
203 /* Init default driver functions then plug in our I810-specific functions
204 * (the texture functions are especially important)
206 _mesa_init_driver_functions( &functions
);
207 i810InitIoctlFuncs( &functions
);
208 i810InitTextureFuncs( &functions
);
211 /* Allocate the Mesa context */
212 if (sharedContextPrivate
)
213 shareCtx
= ((i810ContextPtr
) sharedContextPrivate
)->glCtx
;
216 imesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
217 &functions
, (void*) imesa
);
223 (void) memset( imesa
->texture_heaps
, 0, sizeof( imesa
->texture_heaps
) );
224 make_empty_list( & imesa
->swapped
);
227 imesa
->texture_heaps
[0] = driCreateTextureHeap( 0, imesa
,
228 i810Screen
->textureSize
,
231 imesa
->sarea
->texList
,
232 (unsigned *) & imesa
->sarea
->texAge
, /* XXX we shouldn't cast! */
234 sizeof( struct i810_texture_object_t
),
235 (destroy_texture_object_t
*) i810DestroyTexObj
);
239 /* Set the maximum texture size small enough that we can guarentee
240 * that both texture units can bind a maximal texture and have them
247 ctx
->Const
.MaxTextureUnits
= 2;
248 ctx
->Const
.MaxTextureImageUnits
= 2;
249 ctx
->Const
.MaxTextureCoordUnits
= 2;
252 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
253 * FIXME: packed, but they're not in Intel graphics hardware.
255 driCalculateMaxTextureLevels( imesa
->texture_heaps
,
259 11, /* max 2D texture size is 2048x2048 */
260 0, /* 3D textures unsupported */
261 0, /* cube textures unsupported. */
262 0, /* texture rectangles unsupported. */
267 ctx
->Const
.MinLineWidth
= 1.0;
268 ctx
->Const
.MinLineWidthAA
= 1.0;
269 ctx
->Const
.MaxLineWidth
= 3.0;
270 ctx
->Const
.MaxLineWidthAA
= 3.0;
271 ctx
->Const
.LineWidthGranularity
= 1.0;
273 ctx
->Const
.MinPointSize
= 1.0;
274 ctx
->Const
.MinPointSizeAA
= 1.0;
275 ctx
->Const
.MaxPointSize
= 3.0;
276 ctx
->Const
.MaxPointSizeAA
= 3.0;
277 ctx
->Const
.PointSizeGranularity
= 1.0;
279 ctx
->Driver
.GetBufferSize
= i810BufferSize
;
280 ctx
->Driver
.GetString
= i810GetString
;
284 ctx
->DriverCtx
= (void *) imesa
;
287 /* Initialize the software rasterizer and helper modules.
289 _swrast_CreateContext( ctx
);
290 _vbo_CreateContext( ctx
);
291 _tnl_CreateContext( ctx
);
292 _swsetup_CreateContext( ctx
);
294 /* Install the customized pipeline:
296 _tnl_destroy_pipeline( ctx
);
297 _tnl_install_pipeline( ctx
, i810_pipeline
);
299 /* Configure swrast and T&L to match hardware characteristics:
301 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
302 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
303 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
304 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
308 imesa
->hHWContext
= driContextPriv
->hHWContext
;
309 imesa
->driFd
= sPriv
->fd
;
310 imesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
312 imesa
->stipple_in_hw
= 1;
313 imesa
->RenderIndex
= ~0;
314 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
315 imesa
->upload_cliprects
= GL_TRUE
;
317 imesa
->CurrentTexObj
[0] = 0;
318 imesa
->CurrentTexObj
[1] = 0;
320 _math_matrix_ctr( &imesa
->ViewportMatrix
);
322 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
323 /* XXX these should really go right after _mesa_init_driver_functions() */
324 i810InitStateFuncs( ctx
);
325 i810InitTriFuncs( ctx
);
326 i810InitSpanFuncs( ctx
);
328 i810InitState( ctx
);
331 I810_DEBUG
= driParseDebugString( getenv( "I810_DEBUG" ),
333 I810_DEBUG
|= driParseDebugString( getenv( "INTEL_DEBUG" ),
341 i810DestroyContext(__DRIcontextPrivate
*driContextPriv
)
343 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
345 assert(imesa
); /* should never be null */
347 GLboolean release_texture_heaps
;
350 release_texture_heaps
= (imesa
->glCtx
->Shared
->RefCount
== 1);
351 _swsetup_DestroyContext( imesa
->glCtx
);
352 _tnl_DestroyContext( imesa
->glCtx
);
353 _vbo_DestroyContext( imesa
->glCtx
);
354 _swrast_DestroyContext( imesa
->glCtx
);
356 i810FreeVB( imesa
->glCtx
);
358 /* free the Mesa context */
359 imesa
->glCtx
->DriverCtx
= NULL
;
360 _mesa_destroy_context(imesa
->glCtx
);
361 if ( release_texture_heaps
) {
362 /* This share group is about to go away, free our private
363 * texture object data.
367 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
368 driDestroyTextureHeap( imesa
->texture_heaps
[ i
] );
369 imesa
->texture_heaps
[ i
] = NULL
;
372 assert( is_empty_list( & imesa
->swapped
) );
380 void i810XMesaSetFrontClipRects( i810ContextPtr imesa
)
382 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
384 imesa
->numClipRects
= dPriv
->numClipRects
;
385 imesa
->pClipRects
= dPriv
->pClipRects
;
386 imesa
->drawX
= dPriv
->x
;
387 imesa
->drawY
= dPriv
->y
;
389 i810EmitDrawingRectangle( imesa
);
390 imesa
->upload_cliprects
= GL_TRUE
;
394 void i810XMesaSetBackClipRects( i810ContextPtr imesa
)
396 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
398 if (imesa
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0)
400 imesa
->numClipRects
= dPriv
->numClipRects
;
401 imesa
->pClipRects
= dPriv
->pClipRects
;
402 imesa
->drawX
= dPriv
->x
;
403 imesa
->drawY
= dPriv
->y
;
405 imesa
->numClipRects
= dPriv
->numBackClipRects
;
406 imesa
->pClipRects
= dPriv
->pBackClipRects
;
407 imesa
->drawX
= dPriv
->backX
;
408 imesa
->drawY
= dPriv
->backY
;
411 i810EmitDrawingRectangle( imesa
);
412 imesa
->upload_cliprects
= GL_TRUE
;
416 static void i810XMesaWindowMoved( i810ContextPtr imesa
)
418 /* Determine current color drawing buffer */
419 switch (imesa
->glCtx
->DrawBuffer
->_ColorDrawBufferMask
[0]) {
420 case BUFFER_BIT_FRONT_LEFT
:
421 i810XMesaSetFrontClipRects( imesa
);
423 case BUFFER_BIT_BACK_LEFT
:
424 i810XMesaSetBackClipRects( imesa
);
427 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
428 i810XMesaSetFrontClipRects( imesa
);
434 i810UnbindContext(__DRIcontextPrivate
*driContextPriv
)
436 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
438 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
439 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
440 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
448 i810MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
449 __DRIdrawablePrivate
*driDrawPriv
,
450 __DRIdrawablePrivate
*driReadPriv
)
452 if (driContextPriv
) {
453 i810ContextPtr imesa
= (i810ContextPtr
) driContextPriv
->driverPrivate
;
455 /* Shouldn't the readbuffer be stored also?
457 imesa
->driDrawable
= driDrawPriv
;
459 _mesa_make_current(imesa
->glCtx
,
460 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
461 (GLframebuffer
*) driReadPriv
->driverPrivate
);
463 /* Are these necessary?
465 i810XMesaWindowMoved( imesa
);
468 _mesa_make_current(NULL
, NULL
, NULL
);
475 i810UpdatePageFlipping( i810ContextPtr imesa
)
477 GLcontext
*ctx
= imesa
->glCtx
;
480 /* Determine current color drawing buffer */
481 switch (ctx
->DrawBuffer
->_ColorDrawBufferMask
[0]) {
482 case BUFFER_BIT_FRONT_LEFT
:
485 case BUFFER_BIT_BACK_LEFT
:
492 if ( imesa
->sarea
->pf_current_page
== 1 )
495 driFlipRenderbuffers(ctx
->WinSysDrawBuffer
, front
);
498 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->fbOffset
| imesa
->i810Screen
->backPitchBits
;
500 imesa
->BufferSetup
[I810_DESTREG_DI1
] = imesa
->i810Screen
->backOffset
| imesa
->i810Screen
->backPitchBits
;
503 imesa
->dirty
|= I810_UPLOAD_BUFFERS
;
506 void i810GetLock( i810ContextPtr imesa
, GLuint flags
)
508 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
509 __DRIscreenPrivate
*sPriv
= imesa
->driScreen
;
510 I810SAREAPtr sarea
= imesa
->sarea
;
511 int me
= imesa
->hHWContext
;
514 drmGetLock(imesa
->driFd
, imesa
->hHWContext
, flags
);
516 /* If the window moved, may need to set a new cliprect now.
518 * NOTE: This releases and regains the hw lock, so all state
519 * checking must be done *after* this call:
521 DRI_VALIDATE_DRAWABLE_INFO(sPriv
, dPriv
);
524 /* If we lost context, need to dump all registers to hardware.
525 * Note that we don't care about 2d contexts, even if they perform
526 * accelerated commands, so the DRI locking in the X server is even
527 * more broken than usual.
529 if (sarea
->ctxOwner
!= me
) {
530 driUpdateFramebufferSize(imesa
->glCtx
, dPriv
);
531 imesa
->upload_cliprects
= GL_TRUE
;
532 imesa
->dirty
= I810_UPLOAD_CTX
|I810_UPLOAD_BUFFERS
;
533 if (imesa
->CurrentTexObj
[0]) imesa
->dirty
|= I810_UPLOAD_TEX0
;
534 if (imesa
->CurrentTexObj
[1]) imesa
->dirty
|= I810_UPLOAD_TEX1
;
535 sarea
->ctxOwner
= me
;
538 /* Shared texture managment - if another client has played with
539 * texture space, figure out which if any of our textures have been
540 * ejected, and update our global LRU.
542 for ( i
= 0 ; i
< imesa
->nr_heaps
; i
++ ) {
543 DRI_AGE_TEXTURES( imesa
->texture_heaps
[ i
] );
546 if (imesa
->lastStamp
!= dPriv
->lastStamp
) {
547 i810UpdatePageFlipping( imesa
);
548 i810XMesaWindowMoved( imesa
);
549 imesa
->lastStamp
= dPriv
->lastStamp
;
555 i810SwapBuffers( __DRIdrawablePrivate
*dPriv
)
557 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
558 i810ContextPtr imesa
;
560 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
562 if (ctx
->Visual
.doubleBufferMode
) {
563 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
564 if ( imesa
->sarea
->pf_active
) {
565 i810PageFlip( dPriv
);
567 i810CopyBuffer( dPriv
);
572 /* XXX this shouldn't be an error but we can't handle it for now */
573 _mesa_problem(NULL
, "i810SwapBuffers: drawable has no context!\n");