Remove Driver.ResizeBuffers = _mesa_resize_framebuffer lines.
[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.GetString = i810GetString;
281
282 /* Who owns who?
283 */
284 ctx->DriverCtx = (void *) imesa;
285 imesa->glCtx = ctx;
286
287 /* Initialize the software rasterizer and helper modules.
288 */
289 _swrast_CreateContext( ctx );
290 _ac_CreateContext( ctx );
291 _tnl_CreateContext( ctx );
292 _swsetup_CreateContext( ctx );
293
294 /* Install the customized pipeline:
295 */
296 _tnl_destroy_pipeline( ctx );
297 _tnl_install_pipeline( ctx, i810_pipeline );
298
299 /* Configure swrast and T&L to match hardware characteristics:
300 */
301 _swrast_allow_pixel_fog( ctx, GL_FALSE );
302 _swrast_allow_vertex_fog( ctx, GL_TRUE );
303 _tnl_allow_pixel_fog( ctx, GL_FALSE );
304 _tnl_allow_vertex_fog( ctx, GL_TRUE );
305
306 /* Dri stuff
307 */
308 imesa->hHWContext = driContextPriv->hHWContext;
309 imesa->driFd = sPriv->fd;
310 imesa->driHwLock = &sPriv->pSAREA->lock;
311
312 imesa->stipple_in_hw = 1;
313 imesa->RenderIndex = ~0;
314 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
315 imesa->upload_cliprects = GL_TRUE;
316
317 imesa->CurrentTexObj[0] = 0;
318 imesa->CurrentTexObj[1] = 0;
319
320 _math_matrix_ctr( &imesa->ViewportMatrix );
321
322 driInitExtensions( ctx, card_extensions, GL_TRUE );
323 /* XXX these should really go right after _mesa_init_driver_functions() */
324 i810InitStateFuncs( ctx );
325 i810InitTriFuncs( ctx );
326 i810InitSpanFuncs( ctx );
327 i810InitVB( ctx );
328 i810InitState( ctx );
329
330 #if DO_DEBUG
331 I810_DEBUG = driParseDebugString( getenv( "I810_DEBUG" ),
332 debug_control );
333 I810_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
334 debug_control );
335 #endif
336
337 return GL_TRUE;
338 }
339
340 void
341 i810DestroyContext(__DRIcontextPrivate *driContextPriv)
342 {
343 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
344
345 assert(imesa); /* should never be null */
346 if (imesa) {
347 GLboolean release_texture_heaps;
348
349
350 release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1);
351 _swsetup_DestroyContext( imesa->glCtx );
352 _tnl_DestroyContext( imesa->glCtx );
353 _ac_DestroyContext( imesa->glCtx );
354 _swrast_DestroyContext( imesa->glCtx );
355
356 i810FreeVB( imesa->glCtx );
357
358 /* free the Mesa context */
359 imesa->glCtx->DriverCtx = NULL;
360 _mesa_destroy_context(imesa->glCtx);
361 if ( release_texture_heaps ) {
362 /* This share group is about to go away, free our private
363 * texture object data.
364 */
365 unsigned int i;
366
367 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
368 driDestroyTextureHeap( imesa->texture_heaps[ i ] );
369 imesa->texture_heaps[ i ] = NULL;
370 }
371
372 assert( is_empty_list( & imesa->swapped ) );
373 }
374
375 FREE(imesa);
376 }
377 }
378
379
380 void i810XMesaSetFrontClipRects( i810ContextPtr imesa )
381 {
382 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
383
384 imesa->numClipRects = dPriv->numClipRects;
385 imesa->pClipRects = dPriv->pClipRects;
386 imesa->drawX = dPriv->x;
387 imesa->drawY = dPriv->y;
388
389 i810EmitDrawingRectangle( imesa );
390 imesa->upload_cliprects = GL_TRUE;
391 }
392
393
394 void i810XMesaSetBackClipRects( i810ContextPtr imesa )
395 {
396 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
397
398 if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0)
399 {
400 imesa->numClipRects = dPriv->numClipRects;
401 imesa->pClipRects = dPriv->pClipRects;
402 imesa->drawX = dPriv->x;
403 imesa->drawY = dPriv->y;
404 } else {
405 imesa->numClipRects = dPriv->numBackClipRects;
406 imesa->pClipRects = dPriv->pBackClipRects;
407 imesa->drawX = dPriv->backX;
408 imesa->drawY = dPriv->backY;
409 }
410
411 i810EmitDrawingRectangle( imesa );
412 imesa->upload_cliprects = GL_TRUE;
413 }
414
415
416 static void i810XMesaWindowMoved( i810ContextPtr imesa )
417 {
418 /* Determine current color drawing buffer */
419 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
420 case BUFFER_BIT_FRONT_LEFT:
421 i810XMesaSetFrontClipRects( imesa );
422 break;
423 case BUFFER_BIT_BACK_LEFT:
424 i810XMesaSetBackClipRects( imesa );
425 break;
426 default:
427 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
428 i810XMesaSetFrontClipRects( imesa );
429 }
430 }
431
432
433 GLboolean
434 i810UnbindContext(__DRIcontextPrivate *driContextPriv)
435 {
436 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
437 if (imesa) {
438 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
439 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
440 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
441 }
442
443 return GL_TRUE;
444 }
445
446
447 GLboolean
448 i810MakeCurrent(__DRIcontextPrivate *driContextPriv,
449 __DRIdrawablePrivate *driDrawPriv,
450 __DRIdrawablePrivate *driReadPriv)
451 {
452 if (driContextPriv) {
453 i810ContextPtr imesa = (i810ContextPtr) driContextPriv->driverPrivate;
454
455 /* Shouldn't the readbuffer be stored also?
456 */
457 imesa->driDrawable = driDrawPriv;
458
459 _mesa_make_current(imesa->glCtx,
460 (GLframebuffer *) driDrawPriv->driverPrivate,
461 (GLframebuffer *) driReadPriv->driverPrivate);
462
463 /* Are these necessary?
464 */
465 i810XMesaWindowMoved( imesa );
466 }
467 else {
468 _mesa_make_current(NULL, NULL, NULL);
469 }
470
471 return GL_TRUE;
472 }
473
474 static void
475 i810UpdatePageFlipping( i810ContextPtr imesa )
476 {
477 GLcontext *ctx = imesa->glCtx;
478 int front = 0;
479
480 /* Determine current color drawing buffer */
481 switch (ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
482 case BUFFER_BIT_FRONT_LEFT:
483 front = 1;
484 break;
485 case BUFFER_BIT_BACK_LEFT:
486 front = 0;
487 break;
488 default:
489 return;
490 }
491
492 if ( imesa->sarea->pf_current_page == 1 )
493 front ^= 1;
494
495 driFlipRenderbuffers(ctx->WinSysDrawBuffer, front);
496
497 if (front) {
498 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits;
499 } else {
500 imesa->BufferSetup[I810_DESTREG_DI1] = imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits;
501 }
502
503 imesa->dirty |= I810_UPLOAD_BUFFERS;
504 }
505
506 void i810GetLock( i810ContextPtr imesa, GLuint flags )
507 {
508 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
509 __DRIscreenPrivate *sPriv = imesa->driScreen;
510 I810SAREAPtr sarea = imesa->sarea;
511 int me = imesa->hHWContext;
512 unsigned i;
513
514 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
515
516 /* If the window moved, may need to set a new cliprect now.
517 *
518 * NOTE: This releases and regains the hw lock, so all state
519 * checking must be done *after* this call:
520 */
521 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
522
523
524 /* If we lost context, need to dump all registers to hardware.
525 * Note that we don't care about 2d contexts, even if they perform
526 * accelerated commands, so the DRI locking in the X server is even
527 * more broken than usual.
528 */
529 if (sarea->ctxOwner != me) {
530 driUpdateFramebufferSize(imesa->glCtx, dPriv);
531 imesa->upload_cliprects = GL_TRUE;
532 imesa->dirty = I810_UPLOAD_CTX|I810_UPLOAD_BUFFERS;
533 if (imesa->CurrentTexObj[0]) imesa->dirty |= I810_UPLOAD_TEX0;
534 if (imesa->CurrentTexObj[1]) imesa->dirty |= I810_UPLOAD_TEX1;
535 sarea->ctxOwner = me;
536 }
537
538 /* Shared texture managment - if another client has played with
539 * texture space, figure out which if any of our textures have been
540 * ejected, and update our global LRU.
541 */
542 for ( i = 0 ; i < imesa->nr_heaps ; i++ ) {
543 DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] );
544 }
545
546 if (imesa->lastStamp != dPriv->lastStamp) {
547 i810UpdatePageFlipping( imesa );
548 i810XMesaWindowMoved( imesa );
549 imesa->lastStamp = dPriv->lastStamp;
550 }
551 }
552
553
554 void
555 i810SwapBuffers( __DRIdrawablePrivate *dPriv )
556 {
557 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
558 i810ContextPtr imesa;
559 GLcontext *ctx;
560 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
561 ctx = imesa->glCtx;
562 if (ctx->Visual.doubleBufferMode) {
563 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
564 if ( imesa->sarea->pf_active ) {
565 i810PageFlip( dPriv );
566 } else {
567 i810CopyBuffer( dPriv );
568 }
569 }
570 }
571 else {
572 /* XXX this shouldn't be an error but we can't handle it for now */
573 _mesa_problem(NULL, "i810SwapBuffers: drawable has no context!\n");
574 }
575 }
576