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/simple_list.h"
38 #include "main/imports.h"
39 #include "main/points.h"
41 #include "swrast/swrast.h"
42 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/t_pipeline.h"
48 #include "drivers/common/driverfuncs.h"
50 #include "i810screen.h"
53 #include "i810state.h"
58 #include "i810ioctl.h"
60 #include "drirenderbuffer.h"
67 PUBLIC const char __driConfigOptions[] = { 0 };
68 const GLuint __driNConfigOptions = 0;
70 static const GLubyte *i810GetString( struct gl_context *ctx, GLenum name )
72 static char buffer[128];
76 return (GLubyte *)"Keith Whitwell";
78 i810ContextPtr imesa = I810_CONTEXT(ctx);
81 switch (imesa->i810Screen->deviceID) {
82 case PCI_CHIP_I810: chipset = "i810"; break;
83 case PCI_CHIP_I810_DC100: chipset = "i810 DC-100"; break;
84 case PCI_CHIP_I810_E: chipset = "i810E"; break;
85 case PCI_CHIP_I815: chipset = "i815"; break;
86 default: chipset = "Unknown i810-class Chipset"; break;
89 (void) driGetRendererString( buffer, chipset, 0 );
90 return (GLubyte *) buffer;
97 static void i810BufferSize(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
99 GET_CURRENT_CONTEXT(ctx);
100 i810ContextPtr imesa = I810_CONTEXT(ctx);
102 /* Need to lock to make sure the driDrawable is uptodate. This
103 * information is used to resize Mesa's software buffers, so it has
106 LOCK_HARDWARE(imesa);
107 *width = imesa->driDrawable->w;
108 *height = imesa->driDrawable->h;
109 UNLOCK_HARDWARE(imesa);
112 /* Extension strings exported by the i810 driver.
114 static const struct dri_extension card_extensions[] =
116 { "GL_ARB_multitexture", NULL },
117 { "GL_ARB_texture_env_add", NULL },
118 { "GL_ARB_texture_env_combine", NULL },
119 { "GL_ARB_texture_env_crossbar", NULL },
120 { "GL_ARB_texture_mirrored_repeat", NULL },
121 { "GL_EXT_stencil_wrap", NULL },
122 { "GL_EXT_texture_edge_clamp", NULL },
123 { "GL_EXT_texture_env_combine", NULL },
124 { "GL_EXT_texture_lod_bias", NULL },
125 { "GL_EXT_texture_rectangle", NULL },
126 { "GL_MESA_ycbcr_texture", NULL },
127 { "GL_NV_blend_square", NULL },
131 extern const struct tnl_pipeline_stage _i810_render_stage;
133 static const struct tnl_pipeline_stage *i810_pipeline[] = {
134 &_tnl_vertex_transform_stage,
135 &_tnl_normal_transform_stage,
136 &_tnl_lighting_stage,
137 &_tnl_fog_coordinate_stage,
139 &_tnl_texture_transform_stage,
140 /* REMOVE: point attenuation stage */
142 &_i810_render_stage, /* ADD: unclipped rastersetup-to-dma */
148 static const struct dri_debug_control debug_control[] =
150 { "fall", DEBUG_FALLBACKS },
151 { "tex", DEBUG_TEXTURE },
152 { "ioctl", DEBUG_IOCTL },
153 { "prim", DEBUG_PRIMS },
154 { "vert", DEBUG_VERTS },
155 { "state", DEBUG_STATE },
156 { "verb", DEBUG_VERBOSE },
157 { "dri", DEBUG_DRI },
158 { "dma", DEBUG_DMA },
159 { "san", DEBUG_SANITY },
160 { "sync", DEBUG_SYNC },
161 { "sleep", DEBUG_SLEEP },
166 i810CreateContext( gl_api api,
167 const struct gl_config *mesaVis,
168 __DRIcontext *driContextPriv,
169 void *sharedContextPrivate )
171 struct gl_context *ctx, *shareCtx;
172 i810ContextPtr imesa;
173 __DRIscreen *sPriv = driContextPriv->driScreenPriv;
174 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
175 I810SAREAPtr saPriv = (I810SAREAPtr)
176 (((GLubyte *)sPriv->pSAREA) + i810Screen->sarea_priv_offset);
177 struct dd_function_table functions;
179 /* Allocate i810 context */
180 imesa = (i810ContextPtr) CALLOC_STRUCT(i810_context_t);
185 driContextPriv->driverPrivate = imesa;
187 imesa->i810Screen = i810Screen;
188 imesa->driScreen = sPriv;
189 imesa->sarea = saPriv;
190 imesa->glBuffer = NULL;
192 /* Init default driver functions then plug in our I810-specific functions
193 * (the texture functions are especially important)
195 _mesa_init_driver_functions( &functions );
196 i810InitIoctlFuncs( &functions );
197 i810InitTextureFuncs( &functions );
200 /* Allocate the Mesa context */
201 if (sharedContextPrivate)
202 shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
205 imesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx,
206 &functions, (void*) imesa);
212 (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
213 make_empty_list( & imesa->swapped );
216 imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa,
217 i810Screen->textureSize,
220 imesa->sarea->texList,
221 (unsigned *) & imesa->sarea->texAge, /* XXX we shouldn't cast! */
223 sizeof( struct i810_texture_object_t ),
224 (destroy_texture_object_t *) i810DestroyTexObj );
228 /* Set the maximum texture size small enough that we can guarentee
229 * that both texture units can bind a maximal texture and have them
236 ctx->Const.MaxTextureUnits = 2;
237 ctx->Const.MaxTextureImageUnits = 2;
238 ctx->Const.MaxTextureCoordUnits = 2;
241 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
242 * FIXME: packed, but they're not in Intel graphics hardware.
244 driCalculateMaxTextureLevels( imesa->texture_heaps,
248 11, /* max 2D texture size is 2048x2048 */
249 0, /* 3D textures unsupported */
250 0, /* cube textures unsupported. */
251 0, /* texture rectangles unsupported. */
256 ctx->Const.MinLineWidth = 1.0;
257 ctx->Const.MinLineWidthAA = 1.0;
258 ctx->Const.MaxLineWidth = 3.0;
259 ctx->Const.MaxLineWidthAA = 3.0;
260 ctx->Const.LineWidthGranularity = 1.0;
262 ctx->Const.MinPointSize = 1.0;
263 ctx->Const.MinPointSizeAA = 1.0;
264 ctx->Const.MaxPointSize = 3.0;
265 ctx->Const.MaxPointSizeAA = 3.0;
266 ctx->Const.PointSizeGranularity = 1.0;
268 /* reinitialize the context point state.
269 * It depend on constants in __struct gl_contextRec::Const
271 _mesa_init_point(ctx);
273 ctx->Driver.GetBufferSize = i810BufferSize;
274 ctx->Driver.GetString = i810GetString;
278 ctx->DriverCtx = (void *) imesa;
281 /* Initialize the software rasterizer and helper modules.
283 _swrast_CreateContext( ctx );
284 _vbo_CreateContext( ctx );
285 _tnl_CreateContext( ctx );
286 _swsetup_CreateContext( ctx );
288 /* Install the customized pipeline:
290 _tnl_destroy_pipeline( ctx );
291 _tnl_install_pipeline( ctx, i810_pipeline );
293 /* Configure swrast and T&L to match hardware characteristics:
295 _swrast_allow_pixel_fog( ctx, GL_FALSE );
296 _swrast_allow_vertex_fog( ctx, GL_TRUE );
297 _tnl_allow_pixel_fog( ctx, GL_FALSE );
298 _tnl_allow_vertex_fog( ctx, GL_TRUE );
302 imesa->hHWContext = driContextPriv->hHWContext;
303 imesa->driFd = sPriv->fd;
304 imesa->driHwLock = &sPriv->pSAREA->lock;
306 imesa->stipple_in_hw = 1;
307 imesa->RenderIndex = ~0;
308 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
309 imesa->upload_cliprects = GL_TRUE;
311 imesa->CurrentTexObj[0] = 0;
312 imesa->CurrentTexObj[1] = 0;
314 _math_matrix_ctr( &imesa->ViewportMatrix );
316 driInitExtensions( ctx, card_extensions, GL_TRUE );
317 /* XXX these should really go right after _mesa_init_driver_functions() */
318 i810InitStateFuncs( ctx );
319 i810InitTriFuncs( ctx );
320 i810InitSpanFuncs( ctx );
322 i810InitState( ctx );
325 I810_DEBUG = driParseDebugString( getenv( "I810_DEBUG" ),
327 I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
335 i810DestroyContext(__DRIcontext *driContextPriv)
337 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
339 assert(imesa); /* should never be null */
341 GLboolean release_texture_heaps;
344 release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1);
345 _swsetup_DestroyContext( imesa->glCtx );
346 _tnl_DestroyContext( imesa->glCtx );
347 _vbo_DestroyContext( imesa->glCtx );
348 _swrast_DestroyContext( imesa->glCtx );
350 i810FreeVB( imesa->glCtx );
352 /* free the Mesa context */
353 imesa->glCtx->DriverCtx = NULL;
354 _mesa_destroy_context(imesa->glCtx);
355 if ( release_texture_heaps ) {
356 /* This share group is about to go away, free our private
357 * texture object data.
361 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
362 driDestroyTextureHeap( imesa->texture_heaps[ i ] );
363 imesa->texture_heaps[ i ] = NULL;
366 assert( is_empty_list( & imesa->swapped ) );
374 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
376 __DRIdrawable *dPriv = imesa->driDrawable;
378 imesa->numClipRects = dPriv->numClipRects;
379 imesa->pClipRects = dPriv->pClipRects;
380 imesa->drawX = dPriv->x;
381 imesa->drawY = dPriv->y;
383 i810EmitDrawingRectangle( imesa );
384 imesa->upload_cliprects = GL_TRUE;
388 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
390 __DRIdrawable *dPriv = imesa->driDrawable;
392 if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
394 imesa->numClipRects = dPriv->numClipRects;
395 imesa->pClipRects = dPriv->pClipRects;
396 imesa->drawX = dPriv->x;
397 imesa->drawY = dPriv->y;
399 imesa->numClipRects = dPriv->numBackClipRects;
400 imesa->pClipRects = dPriv->pBackClipRects;
401 imesa->drawX = dPriv->backX;
402 imesa->drawY = dPriv->backY;
405 i810EmitDrawingRectangle( imesa );
406 imesa->upload_cliprects = GL_TRUE;
410 static void i810XMesaWindowMoved( i810ContextPtr imesa )
412 /* Determine current color drawing buffer */
413 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0]) {
414 case BUFFER_FRONT_LEFT:
415 i810XMesaSetFrontClipRects( imesa );
417 case BUFFER_BACK_LEFT:
418 i810XMesaSetBackClipRects( imesa );
421 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
422 i810XMesaSetFrontClipRects( imesa );
428 i810UnbindContext(__DRIcontext *driContextPriv)
430 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
432 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
433 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
434 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
442 i810MakeCurrent(__DRIcontext *driContextPriv,
443 __DRIdrawable *driDrawPriv,
444 __DRIdrawable *driReadPriv)
446 if (driContextPriv) {
447 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
449 /* Shouldn't the readbuffer be stored also?
451 imesa->driDrawable = driDrawPriv;
453 _mesa_make_current(imesa->glCtx,
454 (struct gl_framebuffer *) driDrawPriv->driverPrivate,
455 (struct gl_framebuffer *) driReadPriv->driverPrivate);
457 /* Are these necessary?
459 i810XMesaWindowMoved( imesa );
462 _mesa_make_current(NULL, NULL, NULL);
469 i810UpdatePageFlipping( i810ContextPtr imesa )
471 struct gl_context *ctx = imesa->glCtx;
474 /* Determine current color drawing buffer */
475 switch (ctx->DrawBuffer->_ColorDrawBufferIndexes[0]) {
476 case BUFFER_FRONT_LEFT:
479 case BUFFER_BACK_LEFT:
486 if ( imesa->sarea->pf_current_page == 1 )
489 driFlipRenderbuffers(ctx->WinSysDrawBuffer, front);
492 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
494 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
497 imesa->dirty |= I810_UPLOAD_BUFFERS;
500 void i810GetLock( i810ContextPtr imesa, GLuint flags )
502 __DRIdrawable *dPriv = imesa->driDrawable;
503 __DRIscreen *sPriv = imesa->driScreen;
504 I810SAREAPtr sarea = imesa->sarea;
505 int me = imesa->hHWContext;
508 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
510 /* If the window moved, may need to set a new cliprect now.
512 * NOTE: This releases and regains the hw lock, so all state
513 * checking must be done *after* this call:
515 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
518 /* If we lost context, need to dump all registers to hardware.
519 * Note that we don't care about 2d contexts, even if they perform
520 * accelerated commands, so the DRI locking in the X server is even
521 * more broken than usual.
523 if (sarea->ctxOwner != me) {
524 driUpdateFramebufferSize(imesa->glCtx, dPriv);
525 imesa->upload_cliprects = GL_TRUE;
526 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
527 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
528 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
529 sarea->ctxOwner = me;
532 /* Shared texture managment - if another client has played with
533 * texture space, figure out which if any of our textures have been
534 * ejected, and update our global LRU.
536 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
537 DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
540 if (imesa->lastStamp != dPriv->lastStamp) {
541 i810UpdatePageFlipping( imesa );
542 i810XMesaWindowMoved( imesa );
543 imesa->lastStamp = dPriv->lastStamp;
549 i810SwapBuffers( __DRIdrawable *dPriv )
551 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
552 i810ContextPtr imesa;
553 struct gl_context *ctx;
554 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
556 if (ctx->Visual.doubleBufferMode) {
557 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
558 if ( imesa->sarea->pf_active ) {
559 i810PageFlip( dPriv );
561 i810CopyBuffer( dPriv );
566 /* XXX this shouldn't be an error but we can't handle it for now */
567 _mesa_problem(NULL, "i810SwapBuffers: drawable has no context!\n");