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