DDX DDY support, not very accurate
[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 #include "points.h"
44
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
47 #include "tnl/tnl.h"
48 #include "vbo/vbo.h"
49
50 #include "tnl/t_pipeline.h"
51
52 #include "drivers/common/driverfuncs.h"
53
54 #include "i810screen.h"
55 #include "i810_dri.h"
56
57 #include "i810state.h"
58 #include "i810tex.h"
59 #include "i810span.h"
60 #include "i810tris.h"
61 #include "i810vb.h"
62 #include "i810ioctl.h"
63
64 #include "drirenderbuffer.h"
65 #include "utils.h"
66
67 #define need_GL_ARB_multisample
68 #define need_GL_ARB_texture_compression
69 #define need_GL_ARB_vertex_buffer_object
70 #include "extension_helper.h"
71
72 #ifndef I810_DEBUG
73 int I810_DEBUG = (0);
74 #endif
75
76 PUBLIC const char __driConfigOptions[] = { 0 };
77 const GLuint __driNConfigOptions = 0;
78
79 #define DRIVER_DATE "20050821"
80
81 static const GLubyte *i810GetString( GLcontext *ctx, GLenum name )
82 {
83 static char buffer[128];
84
85 switch (name) {
86 case GL_VENDOR:
87 return (GLubyte *)"Keith Whitwell";
88 case GL_RENDERER: {
89 i810ContextPtr imesa = I810_CONTEXT(ctx);
90 const char * chipset;
91
92 switch (imesa->i810Screen->deviceID) {
93 case PCI_CHIP_I810: chipset = "i810"; break;
94 case PCI_CHIP_I810_DC100: chipset = "i810 DC-100"; break;
95 case PCI_CHIP_I810_E: chipset = "i810E"; break;
96 case PCI_CHIP_I815: chipset = "i815"; break;
97 default: chipset = "Unknown i810-class Chipset"; break;
98 }
99
100 (void) driGetRendererString( buffer, chipset, DRIVER_DATE, 0 );
101 return (GLubyte *) buffer;
102 }
103 default:
104 return 0;
105 }
106 }
107
108 static void i810BufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
109 {
110 GET_CURRENT_CONTEXT(ctx);
111 i810ContextPtr imesa = I810_CONTEXT(ctx);
112
113 /* Need to lock to make sure the driDrawable is uptodate. This
114 * information is used to resize Mesa's software buffers, so it has
115 * to be correct.
116 */
117 LOCK_HARDWARE(imesa);
118 *width = imesa->driDrawable->w;
119 *height = imesa->driDrawable->h;
120 UNLOCK_HARDWARE(imesa);
121 }
122
123 /* Extension strings exported by the i810 driver.
124 */
125 const struct dri_extension card_extensions[] =
126 {
127 { "GL_ARB_multisample", GL_ARB_multisample_functions },
128 { "GL_ARB_multitexture", NULL },
129 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
130 { "GL_ARB_texture_env_add", NULL },
131 { "GL_ARB_texture_env_combine", NULL },
132 { "GL_ARB_texture_env_crossbar", NULL },
133 { "GL_ARB_texture_mirrored_repeat", NULL },
134 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
135 { "GL_EXT_stencil_wrap", NULL },
136 { "GL_EXT_texture_edge_clamp", NULL },
137 { "GL_EXT_texture_env_combine", NULL },
138 { "GL_EXT_texture_lod_bias", NULL },
139 { "GL_EXT_texture_rectangle", NULL },
140 { "GL_MESA_ycbcr_texture", NULL },
141 { "GL_NV_blend_square", NULL },
142 { "GL_SGIS_generate_mipmap", NULL },
143 { NULL, NULL }
144 };
145
146 extern const struct tnl_pipeline_stage _i810_render_stage;
147
148 static const struct tnl_pipeline_stage *i810_pipeline[] = {
149 &_tnl_vertex_transform_stage,
150 &_tnl_normal_transform_stage,
151 &_tnl_lighting_stage,
152 &_tnl_fog_coordinate_stage,
153 &_tnl_texgen_stage,
154 &_tnl_texture_transform_stage,
155 /* REMOVE: point attenuation stage */
156 #if 1
157 &_i810_render_stage, /* ADD: unclipped rastersetup-to-dma */
158 #endif
159 &_tnl_render_stage,
160 0,
161 };
162
163 static const struct dri_debug_control debug_control[] =
164 {
165 { "fall", DEBUG_FALLBACKS },
166 { "tex", DEBUG_TEXTURE },
167 { "ioctl", DEBUG_IOCTL },
168 { "prim", DEBUG_PRIMS },
169 { "vert", DEBUG_VERTS },
170 { "state", DEBUG_STATE },
171 { "verb", DEBUG_VERBOSE },
172 { "dri", DEBUG_DRI },
173 { "dma", DEBUG_DMA },
174 { "san", DEBUG_SANITY },
175 { "sync", DEBUG_SYNC },
176 { "sleep", DEBUG_SLEEP },
177 { NULL, 0 }
178 };
179
180 GLboolean
181 i810CreateContext( const __GLcontextModes *mesaVis,
182 __DRIcontextPrivate *driContextPriv,
183 void *sharedContextPrivate )
184 {
185 GLcontext *ctx, *shareCtx;
186 i810ContextPtr imesa;
187 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
188 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
189 I810SAREAPtr saPriv = (I810SAREAPtr)
190 (((GLubyte *)sPriv->pSAREA) + i810Screen->sarea_priv_offset);
191 struct dd_function_table functions;
192
193 /* Allocate i810 context */
194 imesa = (i810ContextPtr) CALLOC_STRUCT(i810_context_t);
195 if (!imesa) {
196 return GL_FALSE;
197 }
198
199 driContextPriv->driverPrivate = imesa;
200
201 imesa->i810Screen = i810Screen;
202 imesa->driScreen = sPriv;
203 imesa->sarea = saPriv;
204 imesa->glBuffer = NULL;
205
206 /* Init default driver functions then plug in our I810-specific functions
207 * (the texture functions are especially important)
208 */
209 _mesa_init_driver_functions( &functions );
210 i810InitIoctlFuncs( &functions );
211 i810InitTextureFuncs( &functions );
212
213
214 /* Allocate the Mesa context */
215 if (sharedContextPrivate)
216 shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
217 else
218 shareCtx = NULL;
219 imesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
220 &functions, (void*) imesa);
221 if (!imesa->glCtx) {
222 FREE(imesa);
223 return GL_FALSE;
224 }
225
226 (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
227 make_empty_list( & imesa->swapped );
228
229 imesa->nr_heaps = 1;
230 imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa,
231 i810Screen->textureSize,
232 12,
233 I810_NR_TEX_REGIONS,
234 imesa->sarea->texList,
235 (unsigned *) & imesa->sarea->texAge, /* XXX we shouldn't cast! */
236 & imesa->swapped,
237 sizeof( struct i810_texture_object_t ),
238 (destroy_texture_object_t *) i810DestroyTexObj );
239
240
241
242 /* Set the maximum texture size small enough that we can guarentee
243 * that both texture units can bind a maximal texture and have them
244 * in memory at once.
245 */
246
247
248
249 ctx = imesa->glCtx;
250 ctx->Const.MaxTextureUnits = 2;
251 ctx->Const.MaxTextureImageUnits = 2;
252 ctx->Const.MaxTextureCoordUnits = 2;
253
254
255 /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly
256 * FIXME: packed, but they're not in Intel graphics hardware.
257 */
258 driCalculateMaxTextureLevels( imesa->texture_heaps,
259 imesa->nr_heaps,
260 & ctx->Const,
261 4,
262 11, /* max 2D texture size is 2048x2048 */
263 0, /* 3D textures unsupported */
264 0, /* cube textures unsupported. */
265 0, /* texture rectangles unsupported. */
266 12,
267 GL_FALSE,
268 0 );
269
270 ctx->Const.MinLineWidth = 1.0;
271 ctx->Const.MinLineWidthAA = 1.0;
272 ctx->Const.MaxLineWidth = 3.0;
273 ctx->Const.MaxLineWidthAA = 3.0;
274 ctx->Const.LineWidthGranularity = 1.0;
275
276 ctx->Const.MinPointSize = 1.0;
277 ctx->Const.MinPointSizeAA = 1.0;
278 ctx->Const.MaxPointSize = 3.0;
279 ctx->Const.MaxPointSizeAA = 3.0;
280 ctx->Const.PointSizeGranularity = 1.0;
281
282 /* reinitialize the context point state.
283 * It depend on constants in __GLcontextRec::Const
284 */
285 _mesa_init_point(ctx);
286
287 ctx->Driver.GetBufferSize = i810BufferSize;
288 ctx->Driver.GetString = i810GetString;
289
290 /* Who owns who?
291 */
292 ctx->DriverCtx = (void *) imesa;
293 imesa->glCtx = ctx;
294
295 /* Initialize the software rasterizer and helper modules.
296 */
297 _swrast_CreateContext( ctx );
298 _vbo_CreateContext( ctx );
299 _tnl_CreateContext( ctx );
300 _swsetup_CreateContext( ctx );
301
302 /* Install the customized pipeline:
303 */
304 _tnl_destroy_pipeline( ctx );
305 _tnl_install_pipeline( ctx, i810_pipeline );
306
307 /* Configure swrast and T&L to match hardware characteristics:
308 */
309 _swrast_allow_pixel_fog( ctx, GL_FALSE );
310 _swrast_allow_vertex_fog( ctx, GL_TRUE );
311 _tnl_allow_pixel_fog( ctx, GL_FALSE );
312 _tnl_allow_vertex_fog( ctx, GL_TRUE );
313
314 /* Dri stuff
315 */
316 imesa->hHWContext = driContextPriv->hHWContext;
317 imesa->driFd = sPriv->fd;
318 imesa->driHwLock = &sPriv->pSAREA->lock;
319
320 imesa->stipple_in_hw = 1;
321 imesa->RenderIndex = ~0;
322 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
323 imesa->upload_cliprects = GL_TRUE;
324
325 imesa->CurrentTexObj[0] = 0;
326 imesa->CurrentTexObj[1] = 0;
327
328 _math_matrix_ctr( &imesa->ViewportMatrix );
329
330 driInitExtensions( ctx, card_extensions, GL_TRUE );
331 /* XXX these should really go right after _mesa_init_driver_functions() */
332 i810InitStateFuncs( ctx );
333 i810InitTriFuncs( ctx );
334 i810InitSpanFuncs( ctx );
335 i810InitVB( ctx );
336 i810InitState( ctx );
337
338 #if DO_DEBUG
339 I810_DEBUG = driParseDebugString( getenv( "I810_DEBUG" ),
340 debug_control );
341 I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
342 debug_control );
343 #endif
344
345 return GL_TRUE;
346 }
347
348 void
349 i810DestroyContext(__DRIcontextPrivate *driContextPriv)
350 {
351 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
352
353 assert(imesa); /* should never be null */
354 if (imesa) {
355 GLboolean release_texture_heaps;
356
357
358 release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1);
359 _swsetup_DestroyContext( imesa->glCtx );
360 _tnl_DestroyContext( imesa->glCtx );
361 _vbo_DestroyContext( imesa->glCtx );
362 _swrast_DestroyContext( imesa->glCtx );
363
364 i810FreeVB( imesa->glCtx );
365
366 /* free the Mesa context */
367 imesa->glCtx->DriverCtx = NULL;
368 _mesa_destroy_context(imesa->glCtx);
369 if ( release_texture_heaps ) {
370 /* This share group is about to go away, free our private
371 * texture object data.
372 */
373 unsigned int i;
374
375 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
376 driDestroyTextureHeap( imesa->texture_heaps[ i ] );
377 imesa->texture_heaps[ i ] = NULL;
378 }
379
380 assert( is_empty_list( & imesa->swapped ) );
381 }
382
383 FREE(imesa);
384 }
385 }
386
387
388 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
389 {
390 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
391
392 imesa->numClipRects = dPriv->numClipRects;
393 imesa->pClipRects = dPriv->pClipRects;
394 imesa->drawX = dPriv->x;
395 imesa->drawY = dPriv->y;
396
397 i810EmitDrawingRectangle( imesa );
398 imesa->upload_cliprects = GL_TRUE;
399 }
400
401
402 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
403 {
404 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
405
406 if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
407 {
408 imesa->numClipRects = dPriv->numClipRects;
409 imesa->pClipRects = dPriv->pClipRects;
410 imesa->drawX = dPriv->x;
411 imesa->drawY = dPriv->y;
412 } else {
413 imesa->numClipRects = dPriv->numBackClipRects;
414 imesa->pClipRects = dPriv->pBackClipRects;
415 imesa->drawX = dPriv->backX;
416 imesa->drawY = dPriv->backY;
417 }
418
419 i810EmitDrawingRectangle( imesa );
420 imesa->upload_cliprects = GL_TRUE;
421 }
422
423
424 static void i810XMesaWindowMoved( i810ContextPtr imesa )
425 {
426 /* Determine current color drawing buffer */
427 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
428 case BUFFER_BIT_FRONT_LEFT:
429 i810XMesaSetFrontClipRects( imesa );
430 break;
431 case BUFFER_BIT_BACK_LEFT:
432 i810XMesaSetBackClipRects( imesa );
433 break;
434 default:
435 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
436 i810XMesaSetFrontClipRects( imesa );
437 }
438 }
439
440
441 GLboolean
442 i810UnbindContext(__DRIcontextPrivate *driContextPriv)
443 {
444 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
445 if (imesa) {
446 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
447 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
448 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
449 }
450
451 return GL_TRUE;
452 }
453
454
455 GLboolean
456 i810MakeCurrent(__DRIcontextPrivate *driContextPriv,
457 __DRIdrawablePrivate *driDrawPriv,
458 __DRIdrawablePrivate *driReadPriv)
459 {
460 if (driContextPriv) {
461 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
462
463 /* Shouldn't the readbuffer be stored also?
464 */
465 imesa->driDrawable = driDrawPriv;
466
467 _mesa_make_current(imesa->glCtx,
468 (GLframebuffer *) driDrawPriv->driverPrivate,
469 (GLframebuffer *) driReadPriv->driverPrivate);
470
471 /* Are these necessary?
472 */
473 i810XMesaWindowMoved( imesa );
474 }
475 else {
476 _mesa_make_current(NULL, NULL, NULL);
477 }
478
479 return GL_TRUE;
480 }
481
482 static void
483 i810UpdatePageFlipping( i810ContextPtr imesa )
484 {
485 GLcontext *ctx = imesa->glCtx;
486 int front = 0;
487
488 /* Determine current color drawing buffer */
489 switch (ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
490 case BUFFER_BIT_FRONT_LEFT:
491 front = 1;
492 break;
493 case BUFFER_BIT_BACK_LEFT:
494 front = 0;
495 break;
496 default:
497 return;
498 }
499
500 if ( imesa->sarea->pf_current_page == 1 )
501 front ^= 1;
502
503 driFlipRenderbuffers(ctx->WinSysDrawBuffer, front);
504
505 if (front) {
506 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
507 } else {
508 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
509 }
510
511 imesa->dirty |= I810_UPLOAD_BUFFERS;
512 }
513
514 void i810GetLock( i810ContextPtr imesa, GLuint flags )
515 {
516 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
517 __DRIscreenPrivate *sPriv = imesa->driScreen;
518 I810SAREAPtr sarea = imesa->sarea;
519 int me = imesa->hHWContext;
520 unsigned i;
521
522 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
523
524 /* If the window moved, may need to set a new cliprect now.
525 *
526 * NOTE: This releases and regains the hw lock, so all state
527 * checking must be done *after* this call:
528 */
529 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
530
531
532 /* If we lost context, need to dump all registers to hardware.
533 * Note that we don't care about 2d contexts, even if they perform
534 * accelerated commands, so the DRI locking in the X server is even
535 * more broken than usual.
536 */
537 if (sarea->ctxOwner != me) {
538 driUpdateFramebufferSize(imesa->glCtx, dPriv);
539 imesa->upload_cliprects = GL_TRUE;
540 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
541 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
542 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
543 sarea->ctxOwner = me;
544 }
545
546 /* Shared texture managment - if another client has played with
547 * texture space, figure out which if any of our textures have been
548 * ejected, and update our global LRU.
549 */
550 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
551 DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
552 }
553
554 if (imesa->lastStamp != dPriv->lastStamp) {
555 i810UpdatePageFlipping( imesa );
556 i810XMesaWindowMoved( imesa );
557 imesa->lastStamp = dPriv->lastStamp;
558 }
559 }
560
561
562 void
563 i810SwapBuffers( __DRIdrawablePrivate *dPriv )
564 {
565 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
566 i810ContextPtr imesa;
567 GLcontext *ctx;
568 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
569 ctx = imesa->glCtx;
570 if (ctx->Visual.doubleBufferMode) {
571 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
572 if ( imesa->sarea->pf_active ) {
573 i810PageFlip( dPriv );
574 } else {
575 i810CopyBuffer( dPriv );
576 }
577 }
578 }
579 else {
580 /* XXX this shouldn't be an error but we can't handle it for now */
581 _mesa_problem(NULL, "i810SwapBuffers: drawable has no context!\n");
582 }
583 }
584