Add new void *addr and __DRIdrawablePrivate parameters to
[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 #include <X11/Xlibint.h>
27 #include <stdio.h>
28
29 #include "savagecontext.h"
30 #include "context.h"
31 #include "matrix.h"
32 #include "framebuffer.h"
33 #include "renderbuffer.h"
34 #include "simple_list.h"
35
36 #include "utils.h"
37
38 #include "extensions.h"
39
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/tnl.h"
43 #include "array_cache/acache.h"
44
45 #include "tnl/t_pipeline.h"
46
47 #include "drivers/common/driverfuncs.h"
48
49 #include "savagedd.h"
50 #include "savagestate.h"
51 #include "savagetex.h"
52 #include "savagespan.h"
53 #include "savagetris.h"
54 #include "savageioctl.h"
55 #include "savage_bci.h"
56
57 #include "savage_dri.h"
58
59 #include "texmem.h"
60
61 #define need_GL_ARB_multisample
62 #define need_GL_ARB_texture_compression
63 #include "extension_helper.h"
64
65 #include "xmlpool.h"
66
67 /* Driver-specific options
68 */
69 #define SAVAGE_ENABLE_VDMA(def) \
70 DRI_CONF_OPT_BEGIN(enable_vdma,bool,def) \
71 DRI_CONF_DESC(en,"Use DMA for vertex transfers") \
72 DRI_CONF_DESC(de,"Benutze DMA für Vertextransfers") \
73 DRI_CONF_OPT_END
74 #define SAVAGE_ENABLE_FASTPATH(def) \
75 DRI_CONF_OPT_BEGIN(enable_fastpath,bool,def) \
76 DRI_CONF_DESC(en,"Use fast path for unclipped primitives") \
77 DRI_CONF_DESC(de,"Schneller Codepfad für ungeschnittene Polygone") \
78 DRI_CONF_OPT_END
79 #define SAVAGE_SYNC_FRAMES(def) \
80 DRI_CONF_OPT_BEGIN(sync_frames,bool,def) \
81 DRI_CONF_DESC(en,"Synchronize with graphics hardware after each frame") \
82 DRI_CONF_DESC(de,"Synchronisiere nach jedem Frame mit Grafikhardware") \
83 DRI_CONF_OPT_END
84
85 /* Configuration
86 */
87 PUBLIC const char __driConfigOptions[] =
88 DRI_CONF_BEGIN
89 DRI_CONF_SECTION_QUALITY
90 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
91 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
92 DRI_CONF_FLOAT_DEPTH(false)
93 DRI_CONF_SECTION_END
94 DRI_CONF_SECTION_PERFORMANCE
95 SAVAGE_ENABLE_VDMA(true)
96 SAVAGE_ENABLE_FASTPATH(true)
97 SAVAGE_SYNC_FRAMES(false)
98 DRI_CONF_MAX_TEXTURE_UNITS(2,1,2)
99 DRI_CONF_TEXTURE_HEAPS(DRI_CONF_TEXTURE_HEAPS_ALL)
100 DRI_CONF_FORCE_S3TC_ENABLE(false)
101 DRI_CONF_SECTION_END
102 DRI_CONF_SECTION_DEBUG
103 DRI_CONF_NO_RAST(false)
104 DRI_CONF_SECTION_END
105 DRI_CONF_END;
106 static const GLuint __driNConfigOptions = 10;
107
108
109 static const struct dri_debug_control debug_control[] =
110 {
111 { "fall", DEBUG_FALLBACKS },
112 { "api", DEBUG_VERBOSE_API },
113 { "tex", DEBUG_VERBOSE_TEX },
114 { "verb", DEBUG_VERBOSE_MSG },
115 { "dma", DEBUG_DMA },
116 { "state", DEBUG_STATE },
117 { NULL, 0 }
118 };
119 #ifndef SAVAGE_DEBUG
120 int SAVAGE_DEBUG = 0;
121 #endif
122
123
124 /*For time caculating test*/
125 #if defined(DEBUG_TIME) && DEBUG_TIME
126 struct timeval tv_s,tv_f;
127 unsigned long time_sum=0;
128 struct timeval tv_s1,tv_f1;
129 #endif
130
131 static const struct dri_extension card_extensions[] =
132 {
133 { "GL_ARB_multisample", GL_ARB_multisample_functions },
134 { "GL_ARB_multitexture", NULL },
135 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
136 { "GL_EXT_stencil_wrap", NULL },
137 { "GL_EXT_texture_lod_bias", NULL },
138 { NULL, NULL }
139 };
140
141 static const struct dri_extension s4_extensions[] =
142 {
143 { "GL_ARB_texture_env_add", NULL },
144 { NULL, NULL }
145 };
146
147 extern struct tnl_pipeline_stage _savage_texnorm_stage;
148 extern struct tnl_pipeline_stage _savage_render_stage;
149
150 static const struct tnl_pipeline_stage *savage_pipeline[] = {
151
152 &_tnl_vertex_transform_stage,
153 &_tnl_normal_transform_stage,
154 &_tnl_lighting_stage,
155 &_tnl_fog_coordinate_stage,
156 &_tnl_texgen_stage,
157 &_tnl_texture_transform_stage,
158 &_savage_texnorm_stage,
159 &_savage_render_stage,
160 &_tnl_render_stage,
161 0,
162 };
163
164
165 /* this is first function called in dirver*/
166
167 static GLboolean
168 savageInitDriver(__DRIscreenPrivate *sPriv)
169 {
170 savageScreenPrivate *savageScreen;
171 SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
172
173 if (sPriv->devPrivSize != sizeof(SAVAGEDRIRec)) {
174 fprintf(stderr,"\nERROR! sizeof(SAVAGEDRIRec) does not match passed size from device driver\n");
175 return GL_FALSE;
176 }
177
178 /* Allocate the private area */
179 savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate));
180 if (!savageScreen)
181 return GL_FALSE;
182
183 savageScreen->driScrnPriv = sPriv;
184 sPriv->private = (void *)savageScreen;
185
186 savageScreen->chipset=gDRIPriv->chipset;
187 savageScreen->width=gDRIPriv->width;
188 savageScreen->height=gDRIPriv->height;
189 savageScreen->mem=gDRIPriv->mem;
190 savageScreen->cpp=gDRIPriv->cpp;
191 savageScreen->zpp=gDRIPriv->zpp;
192
193 savageScreen->agpMode=gDRIPriv->agpMode;
194
195 savageScreen->bufferSize=gDRIPriv->bufferSize;
196
197 if (gDRIPriv->cpp == 4)
198 savageScreen->frontFormat = DV_PF_8888;
199 else
200 savageScreen->frontFormat = DV_PF_565;
201 savageScreen->frontOffset=gDRIPriv->frontOffset;
202 savageScreen->backOffset = gDRIPriv->backOffset;
203 savageScreen->depthOffset=gDRIPriv->depthOffset;
204
205 savageScreen->textureOffset[SAVAGE_CARD_HEAP] =
206 gDRIPriv->textureOffset;
207 savageScreen->textureSize[SAVAGE_CARD_HEAP] =
208 gDRIPriv->textureSize;
209 savageScreen->logTextureGranularity[SAVAGE_CARD_HEAP] =
210 gDRIPriv->logTextureGranularity;
211
212 savageScreen->textureOffset[SAVAGE_AGP_HEAP] =
213 gDRIPriv->agpTextureHandle;
214 savageScreen->textureSize[SAVAGE_AGP_HEAP] =
215 gDRIPriv->agpTextureSize;
216 savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] =
217 gDRIPriv->logAgpTextureGranularity;
218
219 savageScreen->agpTextures.handle = gDRIPriv->agpTextureHandle;
220 savageScreen->agpTextures.size = gDRIPriv->agpTextureSize;
221 if (gDRIPriv->agpTextureSize) {
222 if (drmMap(sPriv->fd,
223 savageScreen->agpTextures.handle,
224 savageScreen->agpTextures.size,
225 (drmAddress *)&(savageScreen->agpTextures.map)) != 0) {
226 Xfree(savageScreen);
227 sPriv->private = NULL;
228 return GL_FALSE;
229 }
230 } else
231 savageScreen->agpTextures.map = NULL;
232
233 savageScreen->texVirtual[SAVAGE_CARD_HEAP] =
234 (drmAddress)(((GLubyte *)sPriv->pFB)+gDRIPriv->textureOffset);
235 savageScreen->texVirtual[SAVAGE_AGP_HEAP] =
236 (drmAddress)(savageScreen->agpTextures.map);
237
238 savageScreen->aperture.handle = gDRIPriv->apertureHandle;
239 savageScreen->aperture.size = gDRIPriv->apertureSize;
240 savageScreen->aperturePitch = gDRIPriv->aperturePitch;
241 if (drmMap(sPriv->fd,
242 savageScreen->aperture.handle,
243 savageScreen->aperture.size,
244 (drmAddress *)&savageScreen->aperture.map) != 0)
245 {
246 Xfree(savageScreen);
247 sPriv->private = NULL;
248 return GL_FALSE;
249 }
250
251 savageScreen->bufs = drmMapBufs(sPriv->fd);
252
253 savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
254
255 /* parse information in __driConfigOptions */
256 driParseOptionInfo (&savageScreen->optionCache,
257 __driConfigOptions, __driNConfigOptions);
258
259 #if 0
260 savageDDFastPathInit();
261 savageDDTrifuncInit();
262 savageDDSetupInit();
263 #endif
264 return GL_TRUE;
265 }
266
267 /* Accessed by dlsym from dri_mesa_init.c
268 */
269 static void
270 savageDestroyScreen(__DRIscreenPrivate *sPriv)
271 {
272 savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
273
274 if (savageScreen->bufs)
275 drmUnmapBufs(savageScreen->bufs);
276
277 /* free all option information */
278 driDestroyOptionInfo (&savageScreen->optionCache);
279
280 Xfree(savageScreen);
281 sPriv->private = NULL;
282 }
283
284 #if 0
285 GLvisual *XMesaCreateVisual(Display *dpy,
286 __DRIscreenPrivate *driScrnPriv,
287 const XVisualInfo *visinfo,
288 const __GLXvisualConfig *config)
289 {
290 /* Drivers may change the args to _mesa_create_visual() in order to
291 * setup special visuals.
292 */
293 return _mesa_create_visual( config->rgba,
294 config->doubleBuffer,
295 config->stereo,
296 _mesa_bitcount(visinfo->red_mask),
297 _mesa_bitcount(visinfo->green_mask),
298 _mesa_bitcount(visinfo->blue_mask),
299 config->alphaSize,
300 0, /* index bits */
301 config->depthSize,
302 config->stencilSize,
303 config->accumRedSize,
304 config->accumGreenSize,
305 config->accumBlueSize,
306 config->accumAlphaSize,
307 0 /* num samples */ );
308 }
309 #endif
310
311
312 static GLboolean
313 savageCreateContext( const __GLcontextModes *mesaVis,
314 __DRIcontextPrivate *driContextPriv,
315 void *sharedContextPrivate )
316 {
317 GLcontext *ctx, *shareCtx;
318 savageContextPtr imesa;
319 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
320 struct dd_function_table functions;
321 savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
322 drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+
323 savageScreen->sarea_priv_offset);
324 int textureSize[SAVAGE_NR_TEX_HEAPS];
325 int i;
326 imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1);
327 if (!imesa) {
328 return GL_FALSE;
329 }
330
331 /* Init default driver functions then plug in savage-specific texture
332 * functions that are needed as early as during context creation. */
333 _mesa_init_driver_functions( &functions );
334 savageDDInitTextureFuncs( &functions );
335
336 /* Allocate the Mesa context */
337 if (sharedContextPrivate)
338 shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx;
339 else
340 shareCtx = NULL;
341 ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa);
342 if (!ctx) {
343 Xfree(imesa);
344 return GL_FALSE;
345 }
346 driContextPriv->driverPrivate = imesa;
347
348 imesa->cmdBuf.size = SAVAGE_CMDBUF_SIZE;
349 imesa->cmdBuf.base = imesa->cmdBuf.write =
350 malloc(SAVAGE_CMDBUF_SIZE * sizeof(drm_savage_cmd_header_t));
351 if (!imesa->cmdBuf.base)
352 return GL_FALSE;
353
354 /* Parse configuration files */
355 driParseConfigFiles (&imesa->optionCache, &savageScreen->optionCache,
356 sPriv->myNum, "savage");
357
358 imesa->float_depth = driQueryOptionb(&imesa->optionCache, "float_depth") &&
359 savageScreen->chipset >= S3_SAVAGE4;
360 imesa->no_rast = driQueryOptionb(&imesa->optionCache, "no_rast");
361
362 #if 0
363 ctx->Const.MinLineWidth = 1.0;
364 ctx->Const.MinLineWidthAA = 1.0;
365 ctx->Const.MaxLineWidth = 3.0;
366 ctx->Const.MaxLineWidthAA = 3.0;
367 ctx->Const.LineWidthGranularity = 1.0;
368 #endif
369
370 /* Dri stuff
371 */
372 imesa->hHWContext = driContextPriv->hHWContext;
373 imesa->driFd = sPriv->fd;
374 imesa->driHwLock = &sPriv->pSAREA->lock;
375
376 imesa->savageScreen = savageScreen;
377 imesa->driScreen = sPriv;
378 imesa->sarea = saPriv;
379 imesa->glBuffer = NULL;
380
381 /* DMA buffer */
382
383 for(i=0;i<5;i++)
384 {
385 imesa->apertureBase[i] = (GLubyte *)savageScreen->aperture.map +
386 0x01000000 * i;
387 }
388
389 imesa->aperturePitch = savageScreen->aperturePitch;
390
391 /* change texHeap initialize to support two kind of texture heap*/
392 /* here is some parts of initialization, others in InitDriver() */
393
394 (void) memset( imesa->textureHeaps, 0, sizeof( imesa->textureHeaps ) );
395 make_empty_list( & imesa->swapped );
396
397 textureSize[SAVAGE_CARD_HEAP] = savageScreen->textureSize[SAVAGE_CARD_HEAP];
398 textureSize[SAVAGE_AGP_HEAP] = savageScreen->textureSize[SAVAGE_AGP_HEAP];
399 imesa->lastTexHeap = savageScreen->texVirtual[SAVAGE_AGP_HEAP] ? 2 : 1;
400 switch(driQueryOptioni (&imesa->optionCache, "texture_heaps")) {
401 case DRI_CONF_TEXTURE_HEAPS_CARD: /* only use card memory, if available */
402 if (textureSize[SAVAGE_CARD_HEAP])
403 imesa->lastTexHeap = 1;
404 break;
405 case DRI_CONF_TEXTURE_HEAPS_GART: /* only use gart memory, if available */
406 if (imesa->lastTexHeap == 2 && textureSize[SAVAGE_AGP_HEAP])
407 textureSize[SAVAGE_CARD_HEAP] = 0;
408 break;
409 /*default: Nothing to do, use all available memory. */
410 }
411
412 for (i = 0; i < imesa->lastTexHeap; i++) {
413 imesa->textureHeaps[i] = driCreateTextureHeap(
414 i, imesa,
415 textureSize[i],
416 11, /* 2^11 = 2k alignment */
417 SAVAGE_NR_TEX_REGIONS,
418 (drmTextureRegionPtr)imesa->sarea->texList[i],
419 &imesa->sarea->texAge[i],
420 &imesa->swapped,
421 sizeof( savageTexObj ),
422 (destroy_texture_object_t *) savageDestroyTexObj );
423 /* If textureSize[i] == 0 textureHeaps[i] is NULL. This can happen
424 * if there is not enough card memory for a card texture heap. */
425 if (imesa->textureHeaps[i])
426 driSetTextureSwapCounterLocation( imesa->textureHeaps[i],
427 & imesa->c_textureSwaps );
428 }
429 imesa->texture_depth = driQueryOptioni (&imesa->optionCache,
430 "texture_depth");
431 if (imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
432 imesa->texture_depth = ( savageScreen->cpp == 4 ) ?
433 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
434
435 if (savageScreen->chipset >= S3_SAVAGE4)
436 ctx->Const.MaxTextureUnits = 2;
437 else
438 ctx->Const.MaxTextureUnits = 1;
439 if (driQueryOptioni(&imesa->optionCache, "texture_units") <
440 ctx->Const.MaxTextureUnits)
441 ctx->Const.MaxTextureUnits =
442 driQueryOptioni(&imesa->optionCache, "texture_units");
443 ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
444 ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
445
446 driCalculateMaxTextureLevels( imesa->textureHeaps,
447 imesa->lastTexHeap,
448 & ctx->Const,
449 4,
450 11, /* max 2D texture size is 2048x2048 */
451 0, /* 3D textures unsupported. */
452 0, /* cube textures unsupported. */
453 0, /* texture rectangles unsupported. */
454 12,
455 GL_FALSE );
456 if (ctx->Const.MaxTextureLevels <= 6) { /*spec requires at least 64x64*/
457 __driUtilMessage("Not enough texture memory. "
458 "Falling back to indirect rendering.");
459 Xfree(imesa);
460 return GL_FALSE;
461 }
462
463 imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
464 imesa->depth_scale = (imesa->savageScreen->zpp == 2) ?
465 (1.0F/0xffff):(1.0F/0xffffff);
466
467 imesa->bufferSize = savageScreen->bufferSize;
468 imesa->dmaVtxBuf.total = 0;
469 imesa->dmaVtxBuf.used = 0;
470 imesa->dmaVtxBuf.flushed = 0;
471
472 imesa->clientVtxBuf.total = imesa->bufferSize / 4;
473 imesa->clientVtxBuf.used = 0;
474 imesa->clientVtxBuf.flushed = 0;
475 imesa->clientVtxBuf.buf = (u_int32_t *)malloc(imesa->bufferSize);
476
477 imesa->vtxBuf = &imesa->clientVtxBuf;
478
479 imesa->firstElt = -1;
480
481 /* Uninitialized vertex format. Force setting the vertex state in
482 * savageRenderStart.
483 */
484 imesa->vertex_size = 0;
485
486 /* Utah stuff
487 */
488 imesa->new_state = ~0;
489 imesa->new_gl_state = ~0;
490 imesa->RenderIndex = ~0;
491 imesa->dirty = ~0;
492 imesa->lostContext = GL_TRUE;
493 imesa->CurrentTexObj[0] = 0;
494 imesa->CurrentTexObj[1] = 0;
495
496 /* Initialize the software rasterizer and helper modules.
497 */
498 _swrast_CreateContext( ctx );
499 _ac_CreateContext( ctx );
500 _tnl_CreateContext( ctx );
501
502 _swsetup_CreateContext( ctx );
503
504 /* Install the customized pipeline:
505 */
506 _tnl_destroy_pipeline( ctx );
507 _tnl_install_pipeline( ctx, savage_pipeline );
508
509 imesa->enable_fastpath = driQueryOptionb(&imesa->optionCache,
510 "enable_fastpath");
511 /* DRM versions before 2.1.3 would only render triangle lists. ELTS
512 * support was added in 2.2.0. */
513 if (imesa->enable_fastpath && sPriv->drmMinor < 2) {
514 fprintf (stderr,
515 "*** Disabling fast path because your DRM version is buggy "
516 "or doesn't\n*** support ELTS. You need at least Savage DRM "
517 "version 2.2.\n");
518 imesa->enable_fastpath = GL_FALSE;
519 }
520
521 if (!savageScreen->bufs || savageScreen->chipset == S3_SUPERSAVAGE)
522 imesa->enable_vdma = GL_FALSE;
523 else
524 imesa->enable_vdma = driQueryOptionb(&imesa->optionCache, "enable_vdma");
525
526 imesa->sync_frames = driQueryOptionb(&imesa->optionCache, "sync_frames");
527
528 /* Configure swrast to match hardware characteristics:
529 */
530 _tnl_allow_pixel_fog( ctx, GL_FALSE );
531 _tnl_allow_vertex_fog( ctx, GL_TRUE );
532 _swrast_allow_pixel_fog( ctx, GL_FALSE );
533 _swrast_allow_vertex_fog( ctx, GL_TRUE );
534
535 ctx->DriverCtx = (void *) imesa;
536 imesa->glCtx = ctx;
537
538 #ifndef SAVAGE_DEBUG
539 SAVAGE_DEBUG = driParseDebugString( getenv( "SAVAGE_DEBUG" ),
540 debug_control );
541 #endif
542
543 driInitExtensions( ctx, card_extensions, GL_TRUE );
544 if (savageScreen->chipset >= S3_SAVAGE4)
545 driInitExtensions( ctx, s4_extensions, GL_FALSE );
546 if (ctx->Mesa_DXTn ||
547 driQueryOptionb (&imesa->optionCache, "force_s3tc_enable")) {
548 _mesa_enable_extension( ctx, "GL_S3_s3tc" );
549 if (savageScreen->chipset >= S3_SAVAGE4)
550 /* This extension needs DXT3 and DTX5 support in hardware.
551 * Not available on Savage3D/MX/IX. */
552 _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
553 }
554
555 savageDDInitStateFuncs( ctx );
556 savageDDInitSpanFuncs( ctx );
557 savageDDInitDriverFuncs( ctx );
558 savageDDInitIoctlFuncs( ctx );
559 savageInitTriFuncs( ctx );
560
561 savageDDInitState( imesa );
562
563 driContextPriv->driverPrivate = (void *) imesa;
564
565 return GL_TRUE;
566 }
567
568 static void
569 savageDestroyContext(__DRIcontextPrivate *driContextPriv)
570 {
571 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
572 GLuint i;
573
574 assert (imesa); /* should never be NULL */
575 if (imesa) {
576 savageFlushVertices(imesa);
577 savageReleaseIndexedVerts(imesa);
578 savageFlushCmdBuf(imesa, GL_TRUE); /* release DMA buffer */
579 WAIT_IDLE_EMPTY(imesa);
580
581 for (i = 0; i < imesa->lastTexHeap; i++)
582 driDestroyTextureHeap(imesa->textureHeaps[i]);
583
584 free(imesa->cmdBuf.base);
585 free(imesa->clientVtxBuf.buf);
586
587 _swsetup_DestroyContext(imesa->glCtx );
588 _tnl_DestroyContext( imesa->glCtx );
589 _ac_DestroyContext( imesa->glCtx );
590 _swrast_DestroyContext( imesa->glCtx );
591
592 /* free the Mesa context */
593 imesa->glCtx->DriverCtx = NULL;
594 _mesa_destroy_context(imesa->glCtx);
595
596 /* no longer use vertex_dma_buf*/
597 Xfree(imesa);
598 }
599 }
600
601
602 static GLboolean
603 savageCreateBuffer( __DRIscreenPrivate *driScrnPriv,
604 __DRIdrawablePrivate *driDrawPriv,
605 const __GLcontextModes *mesaVis,
606 GLboolean isPixmap)
607 {
608 savageScreenPrivate *screen = (savageScreenPrivate *) driScrnPriv->private;
609
610 if (isPixmap) {
611 return GL_FALSE; /* not implemented */
612 }
613 else {
614 GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
615 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
616 /*
617 * XXX: this value needs to be set according to the config file
618 * setting. But we don't get that until we create a rendering
619 * context!!!!
620 */
621 GLboolean float_depth = GL_FALSE;
622
623 {
624 driRenderbuffer *frontRb
625 = driNewRenderbuffer(GL_RGBA,
626 (GLubyte *) screen->aperture.map
627 + 0x01000000 * TARGET_FRONT,
628 screen->cpp,
629 screen->frontOffset, screen->aperturePitch,
630 driDrawPriv);
631 savageSetSpanFunctions(frontRb, mesaVis, float_depth);
632 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
633 }
634
635 if (mesaVis->doubleBufferMode) {
636 driRenderbuffer *backRb
637 = driNewRenderbuffer(GL_RGBA,
638 (GLubyte *) screen->aperture.map
639 + 0x01000000 * TARGET_BACK,
640 screen->cpp,
641 screen->backOffset, screen->aperturePitch,
642 driDrawPriv);
643 savageSetSpanFunctions(backRb, mesaVis, float_depth);
644 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
645 }
646
647 if (mesaVis->depthBits == 16) {
648 driRenderbuffer *depthRb
649 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
650 (GLubyte *) screen->aperture.map
651 + 0x01000000 * TARGET_DEPTH,
652 screen->zpp,
653 screen->depthOffset, screen->aperturePitch,
654 driDrawPriv);
655 savageSetSpanFunctions(depthRb, mesaVis, float_depth);
656 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
657 }
658 else if (mesaVis->depthBits == 24) {
659 driRenderbuffer *depthRb
660 = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
661 (GLubyte *) screen->aperture.map
662 + 0x01000000 * TARGET_DEPTH,
663 screen->zpp,
664 screen->depthOffset, screen->aperturePitch,
665 driDrawPriv);
666 savageSetSpanFunctions(depthRb, mesaVis, float_depth);
667 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
668 }
669
670 if (mesaVis->stencilBits > 0 && !swStencil) {
671 driRenderbuffer *stencilRb
672 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
673 (GLubyte *) screen->aperture.map
674 + 0x01000000 * TARGET_DEPTH,
675 screen->zpp,
676 screen->depthOffset, screen->aperturePitch,
677 driDrawPriv);
678 savageSetSpanFunctions(stencilRb, mesaVis, float_depth);
679 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
680 }
681
682 _mesa_add_soft_renderbuffers(fb,
683 GL_FALSE, /* color */
684 GL_FALSE, /* depth */
685 swStencil,
686 mesaVis->accumRedBits > 0,
687 GL_FALSE, /* alpha */
688 GL_FALSE /* aux */);
689 driDrawPriv->driverPrivate = (void *) fb;
690
691 return (driDrawPriv->driverPrivate != NULL);
692 }
693 }
694
695 static void
696 savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
697 {
698 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
699 }
700
701 #if 0
702 void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv)
703 {
704 /* XXX should do swap according to the buffer, not the context! */
705 savageContextPtr imesa = savageCtx;
706
707 FLUSH_VB( imesa->glCtx, "swap buffers" );
708 savageSwapBuffers(imesa);
709 }
710 #endif
711
712 void savageXMesaSetFrontClipRects( savageContextPtr imesa )
713 {
714 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
715
716 imesa->numClipRects = dPriv->numClipRects;
717 imesa->pClipRects = dPriv->pClipRects;
718 imesa->drawX = dPriv->x;
719 imesa->drawY = dPriv->y;
720
721 savageCalcViewport( imesa->glCtx );
722 }
723
724
725 void savageXMesaSetBackClipRects( savageContextPtr imesa )
726 {
727 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
728
729 if (dPriv->numBackClipRects == 0)
730 {
731
732
733 imesa->numClipRects = dPriv->numClipRects;
734 imesa->pClipRects = dPriv->pClipRects;
735 imesa->drawX = dPriv->x;
736 imesa->drawY = dPriv->y;
737 } else {
738
739
740 imesa->numClipRects = dPriv->numBackClipRects;
741 imesa->pClipRects = dPriv->pBackClipRects;
742 imesa->drawX = dPriv->backX;
743 imesa->drawY = dPriv->backY;
744 }
745
746 savageCalcViewport( imesa->glCtx );
747 }
748
749
750 static void savageXMesaWindowMoved( savageContextPtr imesa )
751 {
752 if (0)
753 fprintf(stderr, "savageXMesaWindowMoved\n\n");
754
755 switch (imesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
756 case BUFFER_BIT_FRONT_LEFT:
757 savageXMesaSetFrontClipRects( imesa );
758 break;
759 case BUFFER_BIT_BACK_LEFT:
760 savageXMesaSetBackClipRects( imesa );
761 break;
762 default:
763 break;
764 }
765 }
766
767
768 static GLboolean
769 savageUnbindContext(__DRIcontextPrivate *driContextPriv)
770 {
771 savageContextPtr savage = (savageContextPtr) driContextPriv->driverPrivate;
772 if (savage)
773 savage->dirty = ~0;
774
775 return GL_TRUE;
776 }
777
778 #if 0
779 static GLboolean
780 savageOpenFullScreen(__DRIcontextPrivate *driContextPriv)
781 {
782
783
784
785 if (driContextPriv) {
786 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
787 imesa->IsFullScreen = GL_TRUE;
788 imesa->backup_frontOffset = imesa->savageScreen->frontOffset;
789 imesa->backup_backOffset = imesa->savageScreen->backOffset;
790 imesa->backup_frontBitmapDesc = imesa->savageScreen->frontBitmapDesc;
791 imesa->savageScreen->frontBitmapDesc = imesa->savageScreen->backBitmapDesc;
792 imesa->toggle = TARGET_BACK;
793 }
794
795 return GL_TRUE;
796 }
797
798 static GLboolean
799 savageCloseFullScreen(__DRIcontextPrivate *driContextPriv)
800 {
801
802 if (driContextPriv) {
803 savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
804 WAIT_IDLE_EMPTY(imesa);
805 imesa->IsFullScreen = GL_FALSE;
806 imesa->savageScreen->frontOffset = imesa->backup_frontOffset;
807 imesa->savageScreen->backOffset = imesa->backup_backOffset;
808 imesa->savageScreen->frontBitmapDesc = imesa->backup_frontBitmapDesc;
809 }
810 return GL_TRUE;
811 }
812 #endif
813
814 static GLboolean
815 savageMakeCurrent(__DRIcontextPrivate *driContextPriv,
816 __DRIdrawablePrivate *driDrawPriv,
817 __DRIdrawablePrivate *driReadPriv)
818 {
819 if (driContextPriv) {
820 savageContextPtr imesa
821 = (savageContextPtr) driContextPriv->driverPrivate;
822 struct gl_framebuffer *drawBuffer
823 = (GLframebuffer *) driDrawPriv->driverPrivate;
824 struct gl_framebuffer *readBuffer
825 = (GLframebuffer *) driReadPriv->driverPrivate;
826 driRenderbuffer *frontRb = (driRenderbuffer *)
827 drawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
828 driRenderbuffer *backRb = (driRenderbuffer *)
829 drawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
830
831 assert(frontRb->Base.Data);
832 assert(backRb->Base.Data);
833
834 imesa->driReadable = driReadPriv;
835 imesa->driDrawable = driDrawPriv;
836 imesa->dirty = ~0;
837
838 _mesa_make_current(imesa->glCtx, drawBuffer, readBuffer);
839
840 savageXMesaWindowMoved( imesa );
841 }
842 else
843 {
844 _mesa_make_current(NULL, NULL, NULL);
845 }
846 return GL_TRUE;
847 }
848
849
850 void savageGetLock( savageContextPtr imesa, GLuint flags )
851 {
852 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
853 __DRIscreenPrivate *sPriv = imesa->driScreen;
854 drm_savage_sarea_t *sarea = imesa->sarea;
855 int me = imesa->hHWContext;
856 int stamp = dPriv->lastStamp;
857 int heap;
858 unsigned int timestamp = 0;
859
860
861
862 /* We know there has been contention.
863 */
864 drmGetLock(imesa->driFd, imesa->hHWContext, flags);
865
866
867 /* Note contention for throttling hint
868 */
869 imesa->any_contend = 1;
870
871 /* If the window moved, may need to set a new cliprect now.
872 *
873 * NOTE: This releases and regains the hw lock, so all state
874 * checking must be done *after* this call:
875 */
876 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
877
878
879
880
881 /* If we lost context, need to dump all registers to hardware.
882 * Note that we don't care about 2d contexts, even if they perform
883 * accelerated commands, so the DRI locking in the X server is even
884 * more broken than usual.
885 */
886 if (sarea->ctxOwner != me) {
887 imesa->dirty |= (SAVAGE_UPLOAD_LOCAL |
888 SAVAGE_UPLOAD_GLOBAL |
889 SAVAGE_UPLOAD_FOGTBL |
890 SAVAGE_UPLOAD_TEX0 |
891 SAVAGE_UPLOAD_TEX1 |
892 SAVAGE_UPLOAD_TEXGLOBAL);
893 imesa->lostContext = GL_TRUE;
894 sarea->ctxOwner = me;
895 }
896
897 for (heap = 0; heap < imesa->lastTexHeap; ++heap) {
898 /* If a heap was changed, update its timestamp. Do this before
899 * DRI_AGE_TEXTURES updates the local_age. */
900 if (imesa->textureHeaps[heap] &&
901 imesa->textureHeaps[heap]->global_age[0] >
902 imesa->textureHeaps[heap]->local_age) {
903 if (timestamp == 0)
904 timestamp = savageEmitEventLocked(imesa, 0);
905 imesa->textureHeaps[heap]->timestamp = timestamp;
906 }
907 DRI_AGE_TEXTURES( imesa->textureHeaps[heap] );
908 }
909
910 if (dPriv->lastStamp != stamp)
911 savageXMesaWindowMoved( imesa );
912
913
914
915 }
916
917
918
919 static const struct __DriverAPIRec savageAPI = {
920 savageInitDriver,
921 savageDestroyScreen,
922 savageCreateContext,
923 savageDestroyContext,
924 savageCreateBuffer,
925 savageDestroyBuffer,
926 savageSwapBuffers,
927 savageMakeCurrent,
928 savageUnbindContext
929 };
930
931
932 static __GLcontextModes *
933 savageFillInModes( unsigned pixel_bits, unsigned depth_bits,
934 unsigned stencil_bits, GLboolean have_back_buffer )
935 {
936 __GLcontextModes * modes;
937 __GLcontextModes * m;
938 unsigned num_modes;
939 unsigned depth_buffer_factor;
940 unsigned back_buffer_factor;
941 GLenum fb_format;
942 GLenum fb_type;
943
944 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
945 * enough to add support. Basically, if a context is created with an
946 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
947 * will never be used.
948 *
949 * FK: What about drivers that don't use page flipping? Could they
950 * just expose GLX_SWAP_COPY_OML?
951 */
952 static const GLenum back_buffer_modes[] = {
953 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
954 };
955
956 u_int8_t depth_bits_array[2];
957 u_int8_t stencil_bits_array[2];
958
959
960 depth_bits_array[0] = depth_bits;
961 depth_bits_array[1] = depth_bits;
962
963 /* Just like with the accumulation buffer, always provide some modes
964 * with a stencil buffer. It will be a sw fallback, but some apps won't
965 * care about that.
966 */
967 stencil_bits_array[0] = 0;
968 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
969
970 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
971 back_buffer_factor = (have_back_buffer) ? 2 : 1;
972
973 num_modes = depth_buffer_factor * back_buffer_factor * 4;
974
975 if ( pixel_bits == 16 ) {
976 fb_format = GL_RGB;
977 fb_type = GL_UNSIGNED_SHORT_5_6_5;
978 }
979 else {
980 fb_format = GL_BGR;
981 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
982 }
983
984 modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
985 m = modes;
986 if ( ! driFillInModes( & m, fb_format, fb_type,
987 depth_bits_array, stencil_bits_array, depth_buffer_factor,
988 back_buffer_modes, back_buffer_factor,
989 GLX_TRUE_COLOR ) ) {
990 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
991 __func__, __LINE__ );
992 return NULL;
993 }
994
995 if ( ! driFillInModes( & m, fb_format, fb_type,
996 depth_bits_array, stencil_bits_array, depth_buffer_factor,
997 back_buffer_modes, back_buffer_factor,
998 GLX_DIRECT_COLOR ) ) {
999 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
1000 __func__, __LINE__ );
1001 return NULL;
1002 }
1003
1004 /* Mark the visual as slow if there are "fake" stencil bits.
1005 */
1006 for ( m = modes ; m != NULL ; m = m->next ) {
1007 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
1008 m->visualRating = GLX_SLOW_CONFIG;
1009 }
1010 }
1011
1012 return modes;
1013 }
1014
1015
1016 /**
1017 * This is the bootstrap function for the driver. libGL supplies all of the
1018 * requisite information about the system, and the driver initializes itself.
1019 * This routine also fills in the linked list pointed to by \c driver_modes
1020 * with the \c __GLcontextModes that the driver can support for windows or
1021 * pbuffers.
1022 *
1023 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
1024 * failure.
1025 */
1026 PUBLIC
1027 void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
1028 const __GLcontextModes * modes,
1029 const __DRIversion * ddx_version,
1030 const __DRIversion * dri_version,
1031 const __DRIversion * drm_version,
1032 const __DRIframebuffer * frame_buffer,
1033 drmAddress pSAREA, int fd,
1034 int internal_api_version,
1035 const __DRIinterfaceMethods * interface,
1036 __GLcontextModes ** driver_modes )
1037
1038 {
1039 __DRIscreenPrivate *psp;
1040 static const __DRIversion ddx_expected = { 2, 0, 0 };
1041 static const __DRIversion dri_expected = { 4, 0, 0 };
1042 static const __DRIversion drm_expected = { 2, 1, 0 };
1043
1044 dri_interface = interface;
1045
1046 if ( ! driCheckDriDdxDrmVersions2( "Savage",
1047 dri_version, & dri_expected,
1048 ddx_version, & ddx_expected,
1049 drm_version, & drm_expected ) ) {
1050 return NULL;
1051 }
1052
1053 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
1054 ddx_version, dri_version, drm_version,
1055 frame_buffer, pSAREA, fd,
1056 internal_api_version, &savageAPI);
1057 if ( psp != NULL ) {
1058 SAVAGEDRIPtr dri_priv = (SAVAGEDRIPtr)psp->pDevPriv;
1059 *driver_modes = savageFillInModes( dri_priv->cpp*8,
1060 (dri_priv->cpp == 2) ? 16 : 24,
1061 (dri_priv->cpp == 2) ? 0 : 8,
1062 (dri_priv->backOffset != dri_priv->depthOffset) );
1063
1064 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
1065 * enable the extensions. It just makes sure that all the dispatch offsets for all
1066 * the extensions that *might* be enables are known. This is needed because the
1067 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
1068 * enable the extensions until we have a context pointer.
1069 *
1070 * Hello chicken. Hello egg. How are you two today?
1071 */
1072 driInitExtensions( NULL, card_extensions, GL_FALSE );
1073 }
1074
1075 return (void *) psp;
1076 }