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