23373ef73b1dd8f5ab2488372bc7f593bb3a33db
[mesa.git] / src / mesa / drivers / dri / i810 / i810context.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5
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:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
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.
25
26 **************************************************************************/
27 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810context.c,v 1.3 2002/10/30 12:51:33 alanh Exp $ */
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 *
33 */
34
35
36 #include "glheader.h"
37 #include "context.h"
38 #include "matrix.h"
39 #include "simple_list.h"
40 #include "extensions.h"
41 #include "framebuffer.h"
42 #include "imports.h"
43
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/tnl.h"
47 #include "array_cache/acache.h"
48
49 #include "tnl/t_pipeline.h"
50
51 #include "drivers/common/driverfuncs.h"
52
53 #include "i810screen.h"
54 #include "i810_dri.h"
55
56 #include "i810state.h"
57 #include "i810tex.h"
58 #include "i810span.h"
59 #include "i810tris.h"
60 #include "i810vb.h"
61 #include "i810ioctl.h"
62
63 #include "drirenderbuffer.h"
64 #include "utils.h"
65
66 #define need_GL_ARB_multisample
67 #define need_GL_ARB_texture_compression
68 #include "extension_helper.h"
69
70 #ifndef I810_DEBUG
71 int I810_DEBUG = (0);
72 #endif
73
74 PUBLIC const char __driConfigOptions[] = { 0 };
75 const GLuint __driNConfigOptions = 0;
76
77 #define DRIVER_DATE "20050821"
78
79 static const GLubyte *i810GetString( GLcontext *ctx, GLenum name )
80 {
81 static char buffer[128];
82
83 switch (name) {
84 case GL_VENDOR:
85 return (GLubyte *)"Keith Whitwell";
86 case GL_RENDERER: {
87 i810ContextPtr imesa = I810_CONTEXT(ctx);
88 const char * chipset;
89
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;
96 }
97
98 (void) driGetRendererString( buffer, chipset, DRIVER_DATE, 0 );
99 return (GLubyte *) buffer;
100 }
101 default:
102 return 0;
103 }
104 }
105
106 static void i810BufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
107 {
108 GET_CURRENT_CONTEXT(ctx);
109 i810ContextPtr imesa = I810_CONTEXT(ctx);
110
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
113 * to be correct.
114 */
115 LOCK_HARDWARE(imesa);
116 *width = imesa->driDrawable->w;
117 *height = imesa->driDrawable->h;
118 UNLOCK_HARDWARE(imesa);
119 }
120
121 /* Extension strings exported by the i810 driver.
122 */
123 const struct dri_extension card_extensions[] =
124 {
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 },
140 { NULL, NULL }
141 };
142
143 extern const struct tnl_pipeline_stage _i810_render_stage;
144
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,
150 &_tnl_texgen_stage,
151 &_tnl_texture_transform_stage,
152 /* REMOVE: point attenuation stage */
153 #if 1
154 &_i810_render_stage, /* ADD: unclipped rastersetup-to-dma */
155 #endif
156 &_tnl_render_stage,
157 0,
158 };
159
160 static const struct dri_debug_control debug_control[] =
161 {
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 },
174 { NULL, 0 }
175 };
176
177 GLboolean
178 i810CreateContext( const __GLcontextModes *mesaVis,
179 __DRIcontextPrivate *driContextPriv,
180 void *sharedContextPrivate )
181 {
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;
189
190 /* Allocate i810 context */
191 imesa = (i810ContextPtr) CALLOC_STRUCT(i810_context_t);
192 if (!imesa) {
193 return GL_FALSE;
194 }
195
196 driContextPriv->driverPrivate = imesa;
197
198 imesa->i810Screen = i810Screen;
199 imesa->driScreen = sPriv;
200 imesa->sarea = saPriv;
201 imesa->glBuffer = NULL;
202
203 /* Init default driver functions then plug in our I810-specific functions
204 * (the texture functions are especially important)
205 */
206 _mesa_init_driver_functions( &functions );
207 i810InitIoctlFuncs( &functions );
208 i810InitTextureFuncs( &functions );
209
210
211 /* Allocate the Mesa context */
212 if (sharedContextPrivate)
213 shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
214 else
215 shareCtx = NULL;
216 imesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
217 &functions, (void*) imesa);
218 if (!imesa->glCtx) {
219 FREE(imesa);
220 return GL_FALSE;
221 }
222
223 (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
224 make_empty_list( & imesa->swapped );
225
226 imesa->nr_heaps = 1;
227 imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa,
228 i810Screen->textureSize,
229 12,
230 I810_NR_TEX_REGIONS,
231 imesa->sarea->texList,
232 (unsigned *) & imesa->sarea->texAge, /* XXX we shouldn't cast! */
233 & imesa->swapped,
234 sizeof( struct i810_texture_object_t ),
235 (destroy_texture_object_t *) i810DestroyTexObj );
236
237
238
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
241 * in memory at once.
242 */
243
244
245
246 ctx = imesa->glCtx;
247 ctx->Const.MaxTextureUnits = 2;
248 ctx->Const.MaxTextureImageUnits = 2;
249 ctx->Const.MaxTextureCoordUnits = 2;
250
251
252 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
253 * FIXME: packed, but they're not in Intel graphics hardware.
254 */
255 driCalculateMaxTextureLevels( imesa->texture_heaps,
256 imesa->nr_heaps,
257 & ctx->Const,
258 4,
259 11, /* max 2D texture size is 2048x2048 */
260 0, /* 3D textures unsupported */
261 0, /* cube textures unsupported. */
262 0, /* texture rectangles unsupported. */
263 12,
264 GL_FALSE,
265 0 );
266
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;
272
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;
278
279 ctx->Driver.GetBufferSize = i810BufferSize;
280 ctx->Driver.ResizeBuffers = _mesa_resize_framebuffer;
281 ctx->Driver.GetString = i810GetString;
282
283 /* Who owns who?
284 */
285 ctx->DriverCtx = (void *) imesa;
286 imesa->glCtx = ctx;
287
288 /* Initialize the software rasterizer and helper modules.
289 */
290 _swrast_CreateContext( ctx );
291 _ac_CreateContext( ctx );
292 _tnl_CreateContext( ctx );
293 _swsetup_CreateContext( ctx );
294
295 /* Install the customized pipeline:
296 */
297 _tnl_destroy_pipeline( ctx );
298 _tnl_install_pipeline( ctx, i810_pipeline );
299
300 /* Configure swrast and T&L to match hardware characteristics:
301 */
302 _swrast_allow_pixel_fog( ctx, GL_FALSE );
303 _swrast_allow_vertex_fog( ctx, GL_TRUE );
304 _tnl_allow_pixel_fog( ctx, GL_FALSE );
305 _tnl_allow_vertex_fog( ctx, GL_TRUE );
306
307 /* Dri stuff
308 */
309 imesa->hHWContext = driContextPriv->hHWContext;
310 imesa->driFd = sPriv->fd;
311 imesa->driHwLock = &sPriv->pSAREA->lock;
312
313 imesa->stipple_in_hw = 1;
314 imesa->RenderIndex = ~0;
315 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
316 imesa->upload_cliprects = GL_TRUE;
317
318 imesa->CurrentTexObj[0] = 0;
319 imesa->CurrentTexObj[1] = 0;
320
321 _math_matrix_ctr( &imesa->ViewportMatrix );
322
323 driInitExtensions( ctx, card_extensions, GL_TRUE );
324 /* XXX these should really go right after _mesa_init_driver_functions() */
325 i810InitStateFuncs( ctx );
326 i810InitTriFuncs( ctx );
327 i810InitSpanFuncs( ctx );
328 i810InitVB( ctx );
329 i810InitState( ctx );
330
331 #if DO_DEBUG
332 I810_DEBUG = driParseDebugString( getenv( "I810_DEBUG" ),
333 debug_control );
334 I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
335 debug_control );
336 #endif
337
338 return GL_TRUE;
339 }
340
341 void
342 i810DestroyContext(__DRIcontextPrivate *driContextPriv)
343 {
344 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
345
346 assert(imesa); /* should never be null */
347 if (imesa) {
348 GLboolean release_texture_heaps;
349
350
351 release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1);
352 _swsetup_DestroyContext( imesa->glCtx );
353 _tnl_DestroyContext( imesa->glCtx );
354 _ac_DestroyContext( imesa->glCtx );
355 _swrast_DestroyContext( imesa->glCtx );
356
357 i810FreeVB( imesa->glCtx );
358
359 /* free the Mesa context */
360 imesa->glCtx->DriverCtx = NULL;
361 _mesa_destroy_context(imesa->glCtx);
362 if ( release_texture_heaps ) {
363 /* This share group is about to go away, free our private
364 * texture object data.
365 */
366 unsigned int i;
367
368 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
369 driDestroyTextureHeap( imesa->texture_heaps[ i ] );
370 imesa->texture_heaps[ i ] = NULL;
371 }
372
373 assert( is_empty_list( & imesa->swapped ) );
374 }
375
376 FREE(imesa);
377 }
378 }
379
380
381 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
382 {
383 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
384
385 imesa->numClipRects = dPriv->numClipRects;
386 imesa->pClipRects = dPriv->pClipRects;
387 imesa->drawX = dPriv->x;
388 imesa->drawY = dPriv->y;
389
390 i810EmitDrawingRectangle( imesa );
391 imesa->upload_cliprects = GL_TRUE;
392 }
393
394
395 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
396 {
397 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
398
399 if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
400 {
401 imesa->numClipRects = dPriv->numClipRects;
402 imesa->pClipRects = dPriv->pClipRects;
403 imesa->drawX = dPriv->x;
404 imesa->drawY = dPriv->y;
405 } else {
406 imesa->numClipRects = dPriv->numBackClipRects;
407 imesa->pClipRects = dPriv->pBackClipRects;
408 imesa->drawX = dPriv->backX;
409 imesa->drawY = dPriv->backY;
410 }
411
412 i810EmitDrawingRectangle( imesa );
413 imesa->upload_cliprects = GL_TRUE;
414 }
415
416
417 static void i810XMesaWindowMoved( i810ContextPtr imesa )
418 {
419 /* Determine current color drawing buffer */
420 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
421 case BUFFER_BIT_FRONT_LEFT:
422 i810XMesaSetFrontClipRects( imesa );
423 break;
424 case BUFFER_BIT_BACK_LEFT:
425 i810XMesaSetBackClipRects( imesa );
426 break;
427 default:
428 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
429 i810XMesaSetFrontClipRects( imesa );
430 }
431 }
432
433
434 GLboolean
435 i810UnbindContext(__DRIcontextPrivate *driContextPriv)
436 {
437 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
438 if (imesa) {
439 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
440 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
441 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
442 }
443
444 return GL_TRUE;
445 }
446
447
448 GLboolean
449 i810MakeCurrent(__DRIcontextPrivate *driContextPriv,
450 __DRIdrawablePrivate *driDrawPriv,
451 __DRIdrawablePrivate *driReadPriv)
452 {
453 if (driContextPriv) {
454 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
455
456 /* Shouldn't the readbuffer be stored also?
457 */
458 imesa->driDrawable = driDrawPriv;
459
460 _mesa_make_current(imesa->glCtx,
461 (GLframebuffer *) driDrawPriv->driverPrivate,
462 (GLframebuffer *) driReadPriv->driverPrivate);
463
464 /* Are these necessary?
465 */
466 i810XMesaWindowMoved( imesa );
467 }
468 else {
469 _mesa_make_current(NULL, NULL, NULL);
470 }
471
472 return GL_TRUE;
473 }
474
475 static void
476 i810UpdatePageFlipping( i810ContextPtr imesa )
477 {
478 GLcontext *ctx = imesa->glCtx;
479 int front = 0;
480
481 /* Determine current color drawing buffer */
482 switch (ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
483 case BUFFER_BIT_FRONT_LEFT:
484 front = 1;
485 break;
486 case BUFFER_BIT_BACK_LEFT:
487 front = 0;
488 break;
489 default:
490 return;
491 }
492
493 if ( imesa->sarea->pf_current_page == 1 )
494 front ^= 1;
495
496 driFlipRenderbuffers(ctx->WinSysDrawBuffer, front);
497
498 if (front) {
499 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
500 } else {
501 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
502 }
503
504 imesa->dirty |= I810_UPLOAD_BUFFERS;
505 }
506
507 void i810GetLock( i810ContextPtr imesa, GLuint flags )
508 {
509 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
510 __DRIscreenPrivate *sPriv = imesa->driScreen;
511 I810SAREAPtr sarea = imesa->sarea;
512 int me = imesa->hHWContext;
513 unsigned i;
514
515 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
516
517 /* If the window moved, may need to set a new cliprect now.
518 *
519 * NOTE: This releases and regains the hw lock, so all state
520 * checking must be done *after* this call:
521 */
522 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
523
524
525 /* If we lost context, need to dump all registers to hardware.
526 * Note that we don't care about 2d contexts, even if they perform
527 * accelerated commands, so the DRI locking in the X server is even
528 * more broken than usual.
529 */
530 if (sarea->ctxOwner != me) {
531 driUpdateFramebufferSize(imesa->glCtx, dPriv);
532 imesa->upload_cliprects = GL_TRUE;
533 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
534 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
535 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
536 sarea->ctxOwner = me;
537 }
538
539 /* Shared texture managment - if another client has played with
540 * texture space, figure out which if any of our textures have been
541 * ejected, and update our global LRU.
542 */
543 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
544 DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
545 }
546
547 if (imesa->lastStamp != dPriv->lastStamp) {
548 i810UpdatePageFlipping( imesa );
549 i810XMesaWindowMoved( imesa );
550 imesa->lastStamp = dPriv->lastStamp;
551 }
552 }
553
554
555 void
556 i810SwapBuffers( __DRIdrawablePrivate *dPriv )
557 {
558 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
559 i810ContextPtr imesa;
560 GLcontext *ctx;
561 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
562 ctx = imesa->glCtx;
563 if (ctx->Visual.doubleBufferMode) {
564 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
565 if ( imesa->sarea->pf_active ) {
566 i810PageFlip( dPriv );
567 } else {
568 i810CopyBuffer( dPriv );
569 }
570 }
571 }
572 else {
573 /* XXX this shouldn't be an error but we can't handle it for now */
574 _mesa_problem(NULL, "i810SwapBuffers: drawable has no context!\n");
575 }
576 }
577