Merge git://proxy01.pd.intel.com:9419/git/mesa/mesa into crestline
[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 "vbo/vbo.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 #define need_GL_ARB_vertex_buffer_object
69 #include "extension_helper.h"
70
71 #ifndef I810_DEBUG
72 int I810_DEBUG = (0);
73 #endif
74
75 PUBLIC const char __driConfigOptions[] = { 0 };
76 const GLuint __driNConfigOptions = 0;
77
78 #define DRIVER_DATE "20050821"
79
80 static const GLubyte *i810GetString( GLcontext *ctx, GLenum name )
81 {
82 static char buffer[128];
83
84 switch (name) {
85 case GL_VENDOR:
86 return (GLubyte *)"Keith Whitwell";
87 case GL_RENDERER: {
88 i810ContextPtr imesa = I810_CONTEXT(ctx);
89 const char * chipset;
90
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;
97 }
98
99 (void) driGetRendererString( buffer, chipset, DRIVER_DATE, 0 );
100 return (GLubyte *) buffer;
101 }
102 default:
103 return 0;
104 }
105 }
106
107 static void i810BufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
108 {
109 GET_CURRENT_CONTEXT(ctx);
110 i810ContextPtr imesa = I810_CONTEXT(ctx);
111
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
114 * to be correct.
115 */
116 LOCK_HARDWARE(imesa);
117 *width = imesa->driDrawable->w;
118 *height = imesa->driDrawable->h;
119 UNLOCK_HARDWARE(imesa);
120 }
121
122 /* Extension strings exported by the i810 driver.
123 */
124 const struct dri_extension card_extensions[] =
125 {
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 },
142 { NULL, NULL }
143 };
144
145 extern const struct tnl_pipeline_stage _i810_render_stage;
146
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,
152 &_tnl_texgen_stage,
153 &_tnl_texture_transform_stage,
154 /* REMOVE: point attenuation stage */
155 #if 1
156 &_i810_render_stage, /* ADD: unclipped rastersetup-to-dma */
157 #endif
158 &_tnl_render_stage,
159 0,
160 };
161
162 static const struct dri_debug_control debug_control[] =
163 {
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 },
176 { NULL, 0 }
177 };
178
179 GLboolean
180 i810CreateContext( const __GLcontextModes *mesaVis,
181 __DRIcontextPrivate *driContextPriv,
182 void *sharedContextPrivate )
183 {
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;
191
192 /* Allocate i810 context */
193 imesa = (i810ContextPtr) CALLOC_STRUCT(i810_context_t);
194 if (!imesa) {
195 return GL_FALSE;
196 }
197
198 driContextPriv->driverPrivate = imesa;
199
200 imesa->i810Screen = i810Screen;
201 imesa->driScreen = sPriv;
202 imesa->sarea = saPriv;
203 imesa->glBuffer = NULL;
204
205 /* Init default driver functions then plug in our I810-specific functions
206 * (the texture functions are especially important)
207 */
208 _mesa_init_driver_functions( &functions );
209 i810InitIoctlFuncs( &functions );
210 i810InitTextureFuncs( &functions );
211
212
213 /* Allocate the Mesa context */
214 if (sharedContextPrivate)
215 shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
216 else
217 shareCtx = NULL;
218 imesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
219 &functions, (void*) imesa);
220 if (!imesa->glCtx) {
221 FREE(imesa);
222 return GL_FALSE;
223 }
224
225 (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
226 make_empty_list( & imesa->swapped );
227
228 imesa->nr_heaps = 1;
229 imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa,
230 i810Screen->textureSize,
231 12,
232 I810_NR_TEX_REGIONS,
233 imesa->sarea->texList,
234 (unsigned *) & imesa->sarea->texAge, /* XXX we shouldn't cast! */
235 & imesa->swapped,
236 sizeof( struct i810_texture_object_t ),
237 (destroy_texture_object_t *) i810DestroyTexObj );
238
239
240
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
243 * in memory at once.
244 */
245
246
247
248 ctx = imesa->glCtx;
249 ctx->Const.MaxTextureUnits = 2;
250 ctx->Const.MaxTextureImageUnits = 2;
251 ctx->Const.MaxTextureCoordUnits = 2;
252
253
254 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
255 * FIXME: packed, but they're not in Intel graphics hardware.
256 */
257 driCalculateMaxTextureLevels( imesa->texture_heaps,
258 imesa->nr_heaps,
259 & ctx->Const,
260 4,
261 11, /* max 2D texture size is 2048x2048 */
262 0, /* 3D textures unsupported */
263 0, /* cube textures unsupported. */
264 0, /* texture rectangles unsupported. */
265 12,
266 GL_FALSE,
267 0 );
268
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;
274
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;
280
281 ctx->Driver.GetBufferSize = i810BufferSize;
282 ctx->Driver.GetString = i810GetString;
283
284 /* Who owns who?
285 */
286 ctx->DriverCtx = (void *) imesa;
287 imesa->glCtx = ctx;
288
289 /* Initialize the software rasterizer and helper modules.
290 */
291 _swrast_CreateContext( ctx );
292 _vbo_CreateContext( ctx );
293 _tnl_CreateContext( ctx );
294 _swsetup_CreateContext( ctx );
295
296 /* Install the customized pipeline:
297 */
298 _tnl_destroy_pipeline( ctx );
299 _tnl_install_pipeline( ctx, i810_pipeline );
300
301 /* Configure swrast and T&L to match hardware characteristics:
302 */
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 );
307
308 /* Dri stuff
309 */
310 imesa->hHWContext = driContextPriv->hHWContext;
311 imesa->driFd = sPriv->fd;
312 imesa->driHwLock = &sPriv->pSAREA->lock;
313
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;
318
319 imesa->CurrentTexObj[0] = 0;
320 imesa->CurrentTexObj[1] = 0;
321
322 _math_matrix_ctr( &imesa->ViewportMatrix );
323
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 );
329 i810InitVB( ctx );
330 i810InitState( ctx );
331
332 #if DO_DEBUG
333 I810_DEBUG = driParseDebugString( getenv( "I810_DEBUG" ),
334 debug_control );
335 I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
336 debug_control );
337 #endif
338
339 return GL_TRUE;
340 }
341
342 void
343 i810DestroyContext(__DRIcontextPrivate *driContextPriv)
344 {
345 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
346
347 assert(imesa); /* should never be null */
348 if (imesa) {
349 GLboolean release_texture_heaps;
350
351
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 );
357
358 i810FreeVB( imesa->glCtx );
359
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.
366 */
367 unsigned int i;
368
369 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
370 driDestroyTextureHeap( imesa->texture_heaps[ i ] );
371 imesa->texture_heaps[ i ] = NULL;
372 }
373
374 assert( is_empty_list( & imesa->swapped ) );
375 }
376
377 FREE(imesa);
378 }
379 }
380
381
382 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
383 {
384 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
385
386 imesa->numClipRects = dPriv->numClipRects;
387 imesa->pClipRects = dPriv->pClipRects;
388 imesa->drawX = dPriv->x;
389 imesa->drawY = dPriv->y;
390
391 i810EmitDrawingRectangle( imesa );
392 imesa->upload_cliprects = GL_TRUE;
393 }
394
395
396 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
397 {
398 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
399
400 if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
401 {
402 imesa->numClipRects = dPriv->numClipRects;
403 imesa->pClipRects = dPriv->pClipRects;
404 imesa->drawX = dPriv->x;
405 imesa->drawY = dPriv->y;
406 } else {
407 imesa->numClipRects = dPriv->numBackClipRects;
408 imesa->pClipRects = dPriv->pBackClipRects;
409 imesa->drawX = dPriv->backX;
410 imesa->drawY = dPriv->backY;
411 }
412
413 i810EmitDrawingRectangle( imesa );
414 imesa->upload_cliprects = GL_TRUE;
415 }
416
417
418 static void i810XMesaWindowMoved( i810ContextPtr imesa )
419 {
420 /* Determine current color drawing buffer */
421 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
422 case BUFFER_BIT_FRONT_LEFT:
423 i810XMesaSetFrontClipRects( imesa );
424 break;
425 case BUFFER_BIT_BACK_LEFT:
426 i810XMesaSetBackClipRects( imesa );
427 break;
428 default:
429 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
430 i810XMesaSetFrontClipRects( imesa );
431 }
432 }
433
434
435 GLboolean
436 i810UnbindContext(__DRIcontextPrivate *driContextPriv)
437 {
438 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
439 if (imesa) {
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;
443 }
444
445 return GL_TRUE;
446 }
447
448
449 GLboolean
450 i810MakeCurrent(__DRIcontextPrivate *driContextPriv,
451 __DRIdrawablePrivate *driDrawPriv,
452 __DRIdrawablePrivate *driReadPriv)
453 {
454 if (driContextPriv) {
455 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
456
457 /* Shouldn't the readbuffer be stored also?
458 */
459 imesa->driDrawable = driDrawPriv;
460
461 _mesa_make_current(imesa->glCtx,
462 (GLframebuffer *) driDrawPriv->driverPrivate,
463 (GLframebuffer *) driReadPriv->driverPrivate);
464
465 /* Are these necessary?
466 */
467 i810XMesaWindowMoved( imesa );
468 }
469 else {
470 _mesa_make_current(NULL, NULL, NULL);
471 }
472
473 return GL_TRUE;
474 }
475
476 static void
477 i810UpdatePageFlipping( i810ContextPtr imesa )
478 {
479 GLcontext *ctx = imesa->glCtx;
480 int front = 0;
481
482 /* Determine current color drawing buffer */
483 switch (ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
484 case BUFFER_BIT_FRONT_LEFT:
485 front = 1;
486 break;
487 case BUFFER_BIT_BACK_LEFT:
488 front = 0;
489 break;
490 default:
491 return;
492 }
493
494 if ( imesa->sarea->pf_current_page == 1 )
495 front ^= 1;
496
497 driFlipRenderbuffers(ctx->WinSysDrawBuffer, front);
498
499 if (front) {
500 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
501 } else {
502 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
503 }
504
505 imesa->dirty |= I810_UPLOAD_BUFFERS;
506 }
507
508 void i810GetLock( i810ContextPtr imesa, GLuint flags )
509 {
510 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
511 __DRIscreenPrivate *sPriv = imesa->driScreen;
512 I810SAREAPtr sarea = imesa->sarea;
513 int me = imesa->hHWContext;
514 unsigned i;
515
516 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
517
518 /* If the window moved, may need to set a new cliprect now.
519 *
520 * NOTE: This releases and regains the hw lock, so all state
521 * checking must be done *after* this call:
522 */
523 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
524
525
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.
530 */
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;
538 }
539
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.
543 */
544 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
545 DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
546 }
547
548 if (imesa->lastStamp != dPriv->lastStamp) {
549 i810UpdatePageFlipping( imesa );
550 i810XMesaWindowMoved( imesa );
551 imesa->lastStamp = dPriv->lastStamp;
552 }
553 }
554
555
556 void
557 i810SwapBuffers( __DRIdrawablePrivate *dPriv )
558 {
559 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
560 i810ContextPtr imesa;
561 GLcontext *ctx;
562 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
563 ctx = imesa->glCtx;
564 if (ctx->Visual.doubleBufferMode) {
565 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
566 if ( imesa->sarea->pf_active ) {
567 i810PageFlip( dPriv );
568 } else {
569 i810CopyBuffer( dPriv );
570 }
571 }
572 }
573 else {
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");
576 }
577 }
578