b3cf3a9982ea35578fc3ef44e1132129093a4b85
[mesa.git] / src / mesa / drivers / dri / savage / savage_xmesa.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #ifdef GLX_DIRECT_RENDERING
27
28 #include <X11/Xlibint.h>
29 #include <stdio.h>
30
31 #include "savagecontext.h"
32 #include "context.h"
33 #include "matrix.h"
34
35 #include "simple_list.h"
36
37 #include "utils.h"
38
39 #include "swrast/swrast.h"
40 #include "swrast_setup/swrast_setup.h"
41 #include "tnl/tnl.h"
42 #include "array_cache/acache.h"
43
44 #include "tnl/t_pipeline.h"
45
46 #include "drivers/common/driverfuncs.h"
47
48 #include "savagedd.h"
49 #include "savagestate.h"
50 #include "savagetex.h"
51 #include "savagespan.h"
52 #include "savagetris.h"
53 #include "savageioctl.h"
54 #include "savage_bci.h"
55
56 #include "savage_dri.h"
57
58 #include "xmlpool.h"
59
60 /* Configuration
61 */
62 PUBLIC const char __driConfigOptions[] =
63 DRI_CONF_BEGIN
64 DRI_CONF_SECTION_QUALITY
65 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
66 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
67 DRI_CONF_FLOAT_DEPTH(false)
68 DRI_CONF_SECTION_END
69 DRI_CONF_SECTION_PERFORMANCE
70 DRI_CONF_MAX_TEXTURE_UNITS(2,1,2)
71 DRI_CONF_SECTION_END
72 DRI_CONF_SECTION_DEBUG
73 DRI_CONF_NO_RAST(false)
74 DRI_CONF_SECTION_END
75 DRI_CONF_END;
76 static const GLuint __driNConfigOptions = 5;
77
78 #ifdef USE_NEW_INTERFACE
79 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
80 #endif /* USE_NEW_INTERFACE */
81
82 static const struct dri_debug_control debug_control[] =
83 {
84 { "fall", DEBUG_FALLBACKS },
85 { "api", DEBUG_VERBOSE_API },
86 { "lru", DEBUG_VERBOSE_LRU },
87 { "verb", DEBUG_VERBOSE_MSG },
88 { "dma", DEBUG_DMA },
89 { "state", DEBUG_STATE },
90 { NULL, 0 }
91 };
92 #ifndef SAVAGE_DEBUG
93 int SAVAGE_DEBUG = 0;
94 #endif
95
96
97 /*For time caculating test*/
98 #if defined(DEBUG_TIME) && DEBUG_TIME
99 struct timeval tv_s,tv_f;
100 unsigned long time_sum=0;
101 struct timeval tv_s1,tv_f1;
102 #endif
103
104 static const char *const card_extensions[] =
105 {
106 "GL_ARB_multitexture",
107 "GL_EXT_texture_lod_bias",
108 "GL_EXT_texture_env_add",
109 NULL
110 };
111
112 extern const struct tnl_pipeline_stage _savage_texnorm_stage;
113
114 static const struct tnl_pipeline_stage *savage_pipeline[] = {
115
116 &_tnl_vertex_transform_stage,
117 &_tnl_normal_transform_stage,
118 &_tnl_lighting_stage,
119 &_tnl_fog_coordinate_stage,
120 &_tnl_texgen_stage,
121 &_tnl_texture_transform_stage,
122 &_savage_texnorm_stage,
123 &_tnl_render_stage,
124 0,
125 };
126
127
128 /* this is first function called in dirver*/
129
130 static GLboolean
131 savageInitDriver(__DRIscreenPrivate *sPriv)
132 {
133 savageScreenPrivate *savageScreen;
134 SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
135
136 /* Allocate the private area */
137 savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate));
138 if (!savageScreen)
139 return GL_FALSE;
140
141 savageScreen->driScrnPriv = sPriv;
142 sPriv->private = (void *)savageScreen;
143
144 savageScreen->chipset=gDRIPriv->chipset;
145 savageScreen->width=gDRIPriv->width;
146 savageScreen->height=gDRIPriv->height;
147 savageScreen->mem=gDRIPriv->mem;
148 savageScreen->cpp=gDRIPriv->cpp;
149 savageScreen->zpp=gDRIPriv->zpp;
150
151 savageScreen->agpMode=gDRIPriv->agpMode;
152
153 savageScreen->bufferSize=gDRIPriv->bufferSize;
154
155 if (gDRIPriv->cpp == 4)
156 savageScreen->frontFormat = DV_PF_8888;
157 else
158 savageScreen->frontFormat = DV_PF_565;
159 savageScreen->frontOffset=gDRIPriv->frontOffset;
160 savageScreen->backOffset = gDRIPriv->backOffset;
161 savageScreen->depthOffset=gDRIPriv->depthOffset;
162
163 savageScreen->textureOffset[SAVAGE_CARD_HEAP] =
164 gDRIPriv->textureOffset;
165 savageScreen->textureSize[SAVAGE_CARD_HEAP] =
166 gDRIPriv->textureSize;
167 savageScreen->logTextureGranularity[SAVAGE_CARD_HEAP] =
168 gDRIPriv->logTextureGranularity;
169
170 savageScreen->textureOffset[SAVAGE_AGP_HEAP] =
171 gDRIPriv->agpTextureHandle;
172 savageScreen->textureSize[SAVAGE_AGP_HEAP] =
173 gDRIPriv->agpTextureSize;
174 savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] =
175 gDRIPriv->logAgpTextureGranularity;
176
177 savageScreen->agpTextures.handle = gDRIPriv->agpTextureHandle;
178 savageScreen->agpTextures.size = gDRIPriv->agpTextureSize;
179 if (gDRIPriv->agpTextureSize) {
180 if (drmMap(sPriv->fd,
181 savageScreen->agpTextures.handle,
182 savageScreen->agpTextures.size,
183 (drmAddress *)&(savageScreen->agpTextures.map)) != 0) {
184 Xfree(savageScreen);
185 sPriv->private = NULL;
186 return GL_FALSE;
187 }
188 } else
189 savageScreen->agpTextures.map = NULL;
190
191 savageScreen->texVirtual[SAVAGE_CARD_HEAP] =
192 (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->textureOffset);
193 savageScreen->texVirtual[SAVAGE_AGP_HEAP] =
194 (drmAddress)(savageScreen->agpTextures.map);
195
196 savageScreen->aperture.handle = gDRIPriv->apertureHandle;
197 savageScreen->aperture.size = gDRIPriv->apertureSize;
198 savageScreen->aperturePitch = gDRIPriv->aperturePitch;
199 if (drmMap(sPriv->fd,
200 savageScreen->aperture.handle,
201 savageScreen->aperture.size,
202 (drmAddress *)&savageScreen->aperture.map) != 0)
203 {
204 Xfree(savageScreen);
205 sPriv->private = NULL;
206 return GL_FALSE;
207 }
208
209 savageScreen->bufs = drmMapBufs(sPriv->fd);
210
211 savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
212
213 /* parse information in __driConfigOptions */
214 driParseOptionInfo (&savageScreen->optionCache,
215 __driConfigOptions, __driNConfigOptions);
216
217 #if 0
218 savageDDFastPathInit();
219 savageDDTrifuncInit();
220 savageDDSetupInit();
221 #endif
222 return GL_TRUE;
223 }
224
225 /* Accessed by dlsym from dri_mesa_init.c
226 */
227 static void
228 savageDestroyScreen(__DRIscreenPrivate *sPriv)
229 {
230 savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
231
232 drmUnmapBufs(savageScreen->bufs);
233
234 /* free all option information */
235 driDestroyOptionInfo (&savageScreen->optionCache);
236
237 Xfree(savageScreen);
238 sPriv->private = NULL;
239 }
240
241 #if 0
242 GLvisual *XMesaCreateVisual(Display *dpy,
243 __DRIscreenPrivate *driScrnPriv,
244 const XVisualInfo *visinfo,
245 const __GLXvisualConfig *config)
246 {
247 /* Drivers may change the args to _mesa_create_visual() in order to
248 * setup special visuals.
249 */
250 return _mesa_create_visual( config->rgba,
251 config->doubleBuffer,
252 config->stereo,
253 _mesa_bitcount(visinfo->red_mask),
254 _mesa_bitcount(visinfo->green_mask),
255 _mesa_bitcount(visinfo->blue_mask),
256 config->alphaSize,
257 0, /* index bits */
258 config->depthSize,
259 config->stencilSize,
260 config->accumRedSize,
261 config->accumGreenSize,
262 config->accumBlueSize,
263 config->accumAlphaSize,
264 0 /* num samples */ );
265 }
266 #endif
267
268
269 static GLboolean
270 savageCreateContext( const __GLcontextModes *mesaVis,
271 __DRIcontextPrivate *driContextPriv,
272 void *sharedContextPrivate )
273 {
274 GLcontext *ctx, *shareCtx;
275 savageContextPtr imesa;
276 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
277 struct dd_function_table functions;
278 savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
279 drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+
280 savageScreen->sarea_priv_offset);
281 GLuint maxTextureSize, minTextureSize, maxTextureLevels;
282 int i;
283 imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1);
284 if (!imesa) {
285 return GL_FALSE;
286 }
287
288 /* Init default driver functions then plug in savage-specific texture
289 * functions that are needed as early as during context creation. */
290 _mesa_init_driver_functions( &functions );
291 savageDDInitTextureFuncs( &functions );
292
293 /* Allocate the Mesa context */
294 if (sharedContextPrivate)
295 shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx;
296 else
297 shareCtx = NULL;
298 ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa);
299 if (!ctx) {
300 Xfree(imesa);
301 return GL_FALSE;
302 }
303 driContextPriv->driverPrivate = imesa;
304
305 imesa->cmdBuf.size = SAVAGE_CMDBUF_SIZE;
306 imesa->cmdBuf.base = imesa->cmdBuf.write =
307 malloc(SAVAGE_CMDBUF_SIZE * sizeof(drm_savage_cmd_header_t));
308 if (!imesa->cmdBuf.base)
309 return GL_FALSE;
310
311 /* Parse configuration files */
312 driParseConfigFiles (&imesa->optionCache, &savageScreen->optionCache,
313 sPriv->myNum, "savage");
314
315 imesa->float_depth = driQueryOptionb(&imesa->optionCache, "float_depth") &&
316 savageScreen->chipset >= S3_SAVAGE4;
317 imesa->no_rast = driQueryOptionb(&imesa->optionCache, "no_rast");
318 imesa->texture_depth = driQueryOptioni (&imesa->optionCache,
319 "texture_depth");
320 if (imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
321 imesa->texture_depth = ( savageScreen->cpp == 4 ) ?
322 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
323
324 if (savageScreen->chipset >= S3_SAVAGE4)
325 ctx->Const.MaxTextureUnits = 2;
326 else
327 ctx->Const.MaxTextureUnits = 1;
328 if (driQueryOptioni(&imesa->optionCache, "texture_units") <
329 ctx->Const.MaxTextureUnits)
330 ctx->Const.MaxTextureUnits =
331 driQueryOptioni(&imesa->optionCache, "texture_units");
332 ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
333 ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
334
335 /* Set the maximum texture size small enough that we can guarentee
336 * that all texture units can bind a maximal texture and have them
337 * in memory at once.
338 */
339 if (savageScreen->textureSize[SAVAGE_CARD_HEAP] >
340 savageScreen->textureSize[SAVAGE_AGP_HEAP]) {
341 maxTextureSize = savageScreen->textureSize[SAVAGE_CARD_HEAP];
342 minTextureSize = savageScreen->textureSize[SAVAGE_AGP_HEAP];
343 } else {
344 maxTextureSize = savageScreen->textureSize[SAVAGE_AGP_HEAP];
345 minTextureSize = savageScreen->textureSize[SAVAGE_CARD_HEAP];
346 }
347 if (ctx->Const.MaxTextureUnits == 2) {
348 /* How to distribute two maximum sized textures to two texture heaps?
349 * If the smaller heap is less then half the size of the bigger one
350 * then the maximum size is half the size of the bigger heap.
351 * Otherwise it's the size of the smaller heap. */
352 if (minTextureSize < maxTextureSize / 2)
353 maxTextureSize = maxTextureSize / 2;
354 else
355 maxTextureSize = minTextureSize;
356 }
357 for (maxTextureLevels = 1; maxTextureLevels <= 11; ++maxTextureLevels) {
358 GLuint size = 1 << maxTextureLevels;
359 size *= size * 4; /* 4 bytes per texel */
360 size = size * 4/3; /* all mipmap levels together take roughly
361 4/3 the size of the biggest level */
362 if (size > maxTextureSize)
363 break;
364 }
365 ctx->Const.MaxTextureLevels = maxTextureLevels;
366 if (ctx->Const.MaxTextureLevels <= 6) { /*spec requires at least 64x64*/
367 __driUtilMessage("Not enough texture memory. "
368 "Falling back to indirect rendering.");
369 Xfree(imesa);
370 return GL_FALSE;
371 }
372
373 #if 0
374 ctx->Const.MinLineWidth = 1.0;
375 ctx->Const.MinLineWidthAA = 1.0;
376 ctx->Const.MaxLineWidth = 3.0;
377 ctx->Const.MaxLineWidthAA = 3.0;
378 ctx->Const.LineWidthGranularity = 1.0;
379 #endif
380
381 /* Dri stuff
382 */
383 imesa->hHWContext = driContextPriv->hHWContext;
384 imesa->driFd = sPriv->fd;
385 imesa->driHwLock = &sPriv->pSAREA->lock;
386
387 imesa->savageScreen = savageScreen;
388 imesa->driScreen = sPriv;
389 imesa->sarea = saPriv;
390 imesa->glBuffer = NULL;
391
392 /* DMA buffer */
393
394 for(i=0;i<5;i++)
395 {
396 imesa->apertureBase[i] = ((GLuint)savageScreen->aperture.map +
397 0x01000000 * i );
398 }
399
400 imesa->aperturePitch = savageScreen->aperturePitch;
401
402 /* change texHeap initialize to support two kind of texture heap*/
403 /* here is some parts of initialization, others in InitDriver() */
404
405 imesa->lastTexHeap = savageScreen->texVirtual[SAVAGE_AGP_HEAP] ? 2 : 1;
406
407 /*allocate texHeap for multi-tex*/
408 {
409 int i;
410
411 for(i=0;i<imesa->lastTexHeap;i++)
412 {
413 imesa->texHeap[i] = mmInit( 0, savageScreen->textureSize[i] );
414 make_empty_list(&imesa->TexObjList[i]);
415 }
416
417 make_empty_list(&imesa->SwappedOut);
418 }
419
420 imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
421 imesa->depth_scale = (imesa->savageScreen->zpp == 2) ?
422 (1.0F/0xffff):(1.0F/0xffffff);
423
424 imesa->bufferSize = savageScreen->bufferSize;
425 imesa->dmaVtxBuf.total = 0;
426 imesa->dmaVtxBuf.used = 0;
427 imesa->dmaVtxBuf.flushed = 0;
428
429 imesa->clientVtxBuf.total = 16384;
430 imesa->clientVtxBuf.used = 0;
431 imesa->clientVtxBuf.flushed = 0;
432 imesa->clientVtxBuf.buf = (u_int32_t *)malloc(16384*4);
433
434 imesa->vtxBuf = &imesa->clientVtxBuf;
435
436 /* Uninitialized vertex format. Force setting the vertex state in
437 * savageRenderStart.
438 */
439 imesa->vertex_size = 0;
440
441 /* Utah stuff
442 */
443 imesa->new_state = ~0;
444 imesa->new_gl_state = ~0;
445 imesa->RenderIndex = ~0;
446 imesa->dirty = ~0;
447 imesa->lostContext = GL_TRUE;
448 imesa->TextureMode = ctx->Texture.Unit[0].EnvMode;
449 imesa->CurrentTexObj[0] = 0;
450 imesa->CurrentTexObj[1] = 0;
451 imesa->texAge[SAVAGE_CARD_HEAP]=0;
452 imesa->texAge[SAVAGE_AGP_HEAP]=0;
453
454 /* Initialize the software rasterizer and helper modules.
455 */
456 _swrast_CreateContext( ctx );
457 _ac_CreateContext( ctx );
458 _tnl_CreateContext( ctx );
459
460 _swsetup_CreateContext( ctx );
461
462 /* Install the customized pipeline:
463 */
464 #if 1
465 _tnl_destroy_pipeline( ctx );
466 _tnl_install_pipeline( ctx, savage_pipeline );
467 #endif
468
469 /* Configure swrast to match hardware characteristics:
470 */
471 _tnl_allow_pixel_fog( ctx, GL_FALSE );
472 _tnl_allow_vertex_fog( ctx, GL_TRUE );
473 _swrast_allow_pixel_fog( ctx, GL_FALSE );
474 _swrast_allow_vertex_fog( ctx, GL_TRUE );
475
476 ctx->DriverCtx = (void *) imesa;
477 imesa->glCtx = ctx;
478
479 #ifndef SAVAGE_DEBUG
480 SAVAGE_DEBUG = driParseDebugString( getenv( "SAVAGE_DEBUG" ),
481 debug_control );
482 #endif
483
484 driInitExtensions( ctx, card_extensions, GL_TRUE );
485
486 savageDDInitStateFuncs( ctx );
487 savageDDInitSpanFuncs( ctx );
488 savageDDInitDriverFuncs( ctx );
489 savageDDInitIoctlFuncs( ctx );
490 savageInitTriFuncs( ctx );
491
492 savageDDInitState( imesa );
493
494 driContextPriv->driverPrivate = (void *) imesa;
495
496 return GL_TRUE;
497 }
498
499 static void
500 savageDestroyContext(__DRIcontextPrivate *driContextPriv)
501 {
502 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
503
504 assert (imesa); /* should never be NULL */
505 if (imesa) {
506 savageTextureObjectPtr next_t, t;
507
508 FLUSH_BATCH(imesa);
509
510 /* update for multi-tex*/
511 {
512 int i;
513 for(i=0;i<imesa->lastTexHeap;i++)
514 foreach_s (t, next_t, &(imesa->TexObjList[i]))
515 savageDestroyTexObj(imesa, t);
516 }
517 foreach_s (t, next_t, &(imesa->SwappedOut))
518 savageDestroyTexObj(imesa, t);
519
520 free(imesa->cmdBuf.base);
521 free(imesa->clientVtxBuf.buf);
522
523 _swsetup_DestroyContext(imesa->glCtx );
524 _tnl_DestroyContext( imesa->glCtx );
525 _ac_DestroyContext( imesa->glCtx );
526 _swrast_DestroyContext( imesa->glCtx );
527
528 /* free the Mesa context */
529 imesa->glCtx->DriverCtx = NULL;
530 _mesa_destroy_context(imesa->glCtx);
531
532 /* no longer use vertex_dma_buf*/
533 Xfree(imesa);
534 }
535 }
536
537 static GLboolean
538 savageCreateBuffer( __DRIscreenPrivate *driScrnPriv,
539 __DRIdrawablePrivate *driDrawPriv,
540 const __GLcontextModes *mesaVis,
541 GLboolean isPixmap)
542 {
543 if (isPixmap) {
544 return GL_FALSE; /* not implemented */
545 }
546 else {
547 GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
548 driDrawPriv->driverPrivate = (void *)
549 _mesa_create_framebuffer(mesaVis,
550 GL_FALSE, /* software depth buffer? */
551 swStencil,
552 mesaVis->accumRedBits > 0,
553 mesaVis->alphaBits > 0 );
554
555 return (driDrawPriv->driverPrivate != NULL);
556 }
557 }
558
559 static void
560 savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
561 {
562 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
563 }
564
565 #if 0
566 void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv)
567 {
568 /* XXX should do swap according to the buffer, not the context! */
569 savageContextPtr imesa = savageCtx;
570
571 FLUSH_VB( imesa->glCtx, "swap buffers" );
572 savageSwapBuffers(imesa);
573 }
574 #endif
575
576 void savageXMesaSetFrontClipRects( savageContextPtr imesa )
577 {
578 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
579
580 imesa->numClipRects = dPriv->numClipRects;
581 imesa->pClipRects = dPriv->pClipRects;
582 imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
583 imesa->drawX = dPriv->x;
584 imesa->drawY = dPriv->y;
585
586 savageEmitDrawingRectangle( imesa );
587 }
588
589
590 void savageXMesaSetBackClipRects( savageContextPtr imesa )
591 {
592 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
593
594 if (dPriv->numBackClipRects == 0)
595 {
596
597
598 imesa->numClipRects = dPriv->numClipRects;
599 imesa->pClipRects = dPriv->pClipRects;
600 imesa->drawX = dPriv->x;
601 imesa->drawY = dPriv->y;
602 } else {
603
604
605 imesa->numClipRects = dPriv->numBackClipRects;
606 imesa->pClipRects = dPriv->pBackClipRects;
607 imesa->drawX = dPriv->backX;
608 imesa->drawY = dPriv->backY;
609 }
610
611 savageEmitDrawingRectangle( imesa );
612 imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
613
614
615 }
616
617
618 static void savageXMesaWindowMoved( savageContextPtr imesa )
619 {
620 if (0)
621 fprintf(stderr, "savageXMesaWindowMoved\n\n");
622
623 switch (imesa->glCtx->Color._DrawDestMask[0]) {
624 case DD_FRONT_LEFT_BIT:
625 savageXMesaSetFrontClipRects( imesa );
626 break;
627 case DD_BACK_LEFT_BIT:
628 savageXMesaSetBackClipRects( imesa );
629 break;
630 default:
631 break;
632 }
633 }
634
635
636 static GLboolean
637 savageUnbindContext(__DRIcontextPrivate *driContextPriv)
638 {
639 savageContextPtr savage = (savageContextPtr) driContextPriv->driverPrivate;
640 if (savage)
641 savage->dirty = ~0;
642
643 return GL_TRUE;
644 }
645
646 #if 0
647 static GLboolean
648 savageOpenFullScreen(__DRIcontextPrivate *driContextPriv)
649 {
650
651
652
653 if (driContextPriv) {
654 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
655 imesa->IsFullScreen = GL_TRUE;
656 imesa->backup_frontOffset = imesa->savageScreen->frontOffset;
657 imesa->backup_backOffset = imesa->savageScreen->backOffset;
658 imesa->backup_frontBitmapDesc = imesa->savageScreen->frontBitmapDesc;
659 imesa->savageScreen->frontBitmapDesc = imesa->savageScreen->backBitmapDesc;
660 imesa->toggle = TARGET_BACK;
661 }
662
663 return GL_TRUE;
664 }
665
666 static GLboolean
667 savageCloseFullScreen(__DRIcontextPrivate *driContextPriv)
668 {
669
670 if (driContextPriv) {
671 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
672 WAIT_IDLE_EMPTY;
673 imesa->IsFullScreen = GL_FALSE;
674 imesa->savageScreen->frontOffset = imesa->backup_frontOffset;
675 imesa->savageScreen->backOffset = imesa->backup_backOffset;
676 imesa->savageScreen->frontBitmapDesc = imesa->backup_frontBitmapDesc;
677 }
678 return GL_TRUE;
679 }
680 #endif
681
682 static GLboolean
683 savageMakeCurrent(__DRIcontextPrivate *driContextPriv,
684 __DRIdrawablePrivate *driDrawPriv,
685 __DRIdrawablePrivate *driReadPriv)
686 {
687 if (driContextPriv) {
688 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
689
690 imesa->driReadable = driReadPriv;
691 imesa->driDrawable = driDrawPriv;
692 imesa->mesa_drawable = driDrawPriv;
693 imesa->dirty = ~0;
694
695 _mesa_make_current2(imesa->glCtx,
696 (GLframebuffer *) driDrawPriv->driverPrivate,
697 (GLframebuffer *) driReadPriv->driverPrivate);
698
699 savageXMesaWindowMoved( imesa );
700 }
701 else
702 {
703 _mesa_make_current(NULL, NULL);
704 }
705 return GL_TRUE;
706 }
707
708
709 void savageGetLock( savageContextPtr imesa, GLuint flags )
710 {
711 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
712 __DRIscreenPrivate *sPriv = imesa->driScreen;
713 drm_savage_sarea_t *sarea = imesa->sarea;
714 int me = imesa->hHWContext;
715 int stamp = dPriv->lastStamp;
716 int heap;
717
718
719
720 /* We know there has been contention.
721 */
722 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
723
724
725 /* Note contention for throttling hint
726 */
727 imesa->any_contend = 1;
728
729 /* If the window moved, may need to set a new cliprect now.
730 *
731 * NOTE: This releases and regains the hw lock, so all state
732 * checking must be done *after* this call:
733 */
734 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
735
736
737
738
739 /* If we lost context, need to dump all registers to hardware.
740 * Note that we don't care about 2d contexts, even if they perform
741 * accelerated commands, so the DRI locking in the X server is even
742 * more broken than usual.
743 */
744 if (sarea->ctxOwner != me) {
745 imesa->dirty |= (SAVAGE_UPLOAD_LOCAL |
746 SAVAGE_UPLOAD_GLOBAL |
747 SAVAGE_UPLOAD_FOGTBL |
748 SAVAGE_UPLOAD_TEX0 |
749 SAVAGE_UPLOAD_TEX1 |
750 SAVAGE_UPLOAD_TEXGLOBAL |
751 SAVAGE_UPLOAD_CLIPRECTS);
752 imesa->lostContext = GL_TRUE;
753 sarea->ctxOwner = me;
754 }
755
756 /* Shared texture managment - if another client has played with
757 * texture space, figure out which if any of our textures have been
758 * ejected, and update our global LRU.
759 */
760 /*frank just for compiling,texAge,texList,AGP*/
761
762 for(heap= 0 ;heap < imesa->lastTexHeap ; heap++)
763 {
764 if (sarea->texAge[heap] != imesa->texAge[heap]) {
765 int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]);
766 int idx, nr = 0;
767
768 /* Have to go right round from the back to ensure stuff ends up
769 * LRU in our local list...
770 */
771 for (idx = sarea->texList[heap][SAVAGE_NR_TEX_REGIONS].prev ;
772 idx != SAVAGE_NR_TEX_REGIONS && nr < SAVAGE_NR_TEX_REGIONS ;
773 idx = sarea->texList[heap][idx].prev, nr++)
774 {
775 if (sarea->texList[heap][idx].age > imesa->texAge[heap])
776 {
777 savageTexturesGone(imesa, heap ,idx * sz, sz,
778 sarea->texList[heap][idx].in_use);
779 }
780 }
781
782 if (nr == SAVAGE_NR_TEX_REGIONS)
783 {
784 savageTexturesGone(imesa, heap, 0,
785 imesa->savageScreen->textureSize[heap], 0);
786 savageResetGlobalLRU( imesa , heap );
787 }
788
789 imesa->texAge[heap] = sarea->texAge[heap];
790 }
791 } /* end of for loop */
792
793 if (dPriv->lastStamp != stamp)
794 savageXMesaWindowMoved( imesa );
795
796
797
798 }
799
800
801
802 static const struct __DriverAPIRec savageAPI = {
803 savageInitDriver,
804 savageDestroyScreen,
805 savageCreateContext,
806 savageDestroyContext,
807 savageCreateBuffer,
808 savageDestroyBuffer,
809 savageSwapBuffers,
810 savageMakeCurrent,
811 savageUnbindContext
812 };
813
814
815
816 #ifndef DRI_NEW_INTERFACE_ONLY
817 /*
818 * This is the (old) bootstrap function for the driver.
819 * The __driCreateScreen name is the symbol that libGL.so fetches.
820 * Return: pointer to a __DRIscreenPrivate.
821 */
822 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
823 int numConfigs, __GLXvisualConfig *config)
824 {
825 __DRIscreenPrivate *psp;
826 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &savageAPI);
827 return (void *) psp;
828 }
829 #endif /* DRI_NEW_INTERFACE_ONLY */
830
831
832
833 #ifdef USE_NEW_INTERFACE
834 static __GLcontextModes *
835 savageFillInModes( unsigned pixel_bits, unsigned depth_bits,
836 unsigned stencil_bits, GLboolean have_back_buffer )
837 {
838 __GLcontextModes * modes;
839 __GLcontextModes * m;
840 unsigned num_modes;
841 unsigned depth_buffer_factor;
842 unsigned back_buffer_factor;
843 GLenum fb_format;
844 GLenum fb_type;
845
846 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
847 * enough to add support. Basically, if a context is created with an
848 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
849 * will never be used.
850 *
851 * FK: What about drivers that don't use page flipping? Could they
852 * just expose GLX_SWAP_COPY_OML?
853 */
854 static const GLenum back_buffer_modes[] = {
855 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
856 };
857
858 u_int8_t depth_bits_array[2];
859 u_int8_t stencil_bits_array[2];
860
861
862 depth_bits_array[0] = depth_bits;
863 depth_bits_array[1] = depth_bits;
864
865 /* Just like with the accumulation buffer, always provide some modes
866 * with a stencil buffer. It will be a sw fallback, but some apps won't
867 * care about that.
868 */
869 stencil_bits_array[0] = 0;
870 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
871
872 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
873 back_buffer_factor = (have_back_buffer) ? 2 : 1;
874
875 num_modes = depth_buffer_factor * back_buffer_factor * 4;
876
877 if ( pixel_bits == 16 ) {
878 fb_format = GL_RGB;
879 fb_type = GL_UNSIGNED_SHORT_5_6_5;
880 }
881 else {
882 fb_format = GL_BGR;
883 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
884 }
885
886 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
887 m = modes;
888 if ( ! driFillInModes( & m, fb_format, fb_type,
889 depth_bits_array, stencil_bits_array, depth_buffer_factor,
890 back_buffer_modes, back_buffer_factor,
891 GLX_TRUE_COLOR ) ) {
892 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
893 __func__, __LINE__ );
894 return NULL;
895 }
896
897 if ( ! driFillInModes( & m, fb_format, fb_type,
898 depth_bits_array, stencil_bits_array, depth_buffer_factor,
899 back_buffer_modes, back_buffer_factor,
900 GLX_DIRECT_COLOR ) ) {
901 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
902 __func__, __LINE__ );
903 return NULL;
904 }
905
906 /* Mark the visual as slow if there are "fake" stencil bits.
907 */
908 for ( m = modes ; m != NULL ; m = m->next ) {
909 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
910 m->visualRating = GLX_SLOW_CONFIG;
911 }
912 }
913
914 return modes;
915 }
916
917
918 /**
919 * This is the bootstrap function for the driver. libGL supplies all of the
920 * requisite information about the system, and the driver initializes itself.
921 * This routine also fills in the linked list pointed to by \c driver_modes
922 * with the \c __GLcontextModes that the driver can support for windows or
923 * pbuffers.
924 *
925 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
926 * failure.
927 */
928 PUBLIC
929 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
930 const __GLcontextModes * modes,
931 const __DRIversion * ddx_version,
932 const __DRIversion * dri_version,
933 const __DRIversion * drm_version,
934 const __DRIframebuffer * frame_buffer,
935 drmAddress pSAREA, int fd,
936 int internal_api_version,
937 __GLcontextModes ** driver_modes )
938
939 {
940 __DRIscreenPrivate *psp;
941 static const __DRIversion ddx_expected = { 2, 0, 0 };
942 static const __DRIversion dri_expected = { 4, 0, 0 };
943 static const __DRIversion drm_expected = { 2, 0, 0 };
944
945 if ( ! driCheckDriDdxDrmVersions2( "Savage",
946 dri_version, & dri_expected,
947 ddx_version, & ddx_expected,
948 drm_version, & drm_expected ) ) {
949 return NULL;
950 }
951
952 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
953 ddx_version, dri_version, drm_version,
954 frame_buffer, pSAREA, fd,
955 internal_api_version, &savageAPI);
956 if ( psp != NULL ) {
957 create_context_modes = (PFNGLXCREATECONTEXTMODES)
958 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
959 if ( create_context_modes != NULL ) {
960 SAVAGEDRIPtr dri_priv = (SAVAGEDRIPtr)psp->pDevPriv;
961 *driver_modes = savageFillInModes( dri_priv->cpp*8,
962 (dri_priv->cpp == 2) ? 16 : 24,
963 (dri_priv->cpp == 2) ? 0 : 8,
964 (dri_priv->backOffset != dri_priv->depthOffset) );
965 }
966 }
967
968 return (void *) psp;
969 }
970 #endif /* USE_NEW_INTERFACE */
971
972 #endif