dri: Add DRI entrypoints to create a context for a given API
[mesa.git] / src / mesa / drivers / dri / mga / mga_xmesa.c
1 /*
2 * Copyright 2000-2001 VA Linux Systems, Inc.
3 * 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 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * 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 * VA LINUX SYSTEMS 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
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file mga_xmesa.c
27 * MGA screen and context initialization / creation code.
28 *
29 * \author Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include "drm.h"
35 #include "mga_drm.h"
36 #include "mga_xmesa.h"
37 #include "main/context.h"
38 #include "main/simple_list.h"
39 #include "main/imports.h"
40 #include "main/framebuffer.h"
41 #include "main/renderbuffer.h"
42
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "tnl/tnl.h"
46 #include "vbo/vbo.h"
47
48 #include "tnl/t_pipeline.h"
49
50 #include "drivers/common/driverfuncs.h"
51
52 #include "mgadd.h"
53 #include "mgastate.h"
54 #include "mgatex.h"
55 #include "mgaspan.h"
56 #include "mgaioctl.h"
57 #include "mgatris.h"
58 #include "mgavb.h"
59 #include "mgapixel.h"
60 #include "mga_xmesa.h"
61 #include "mga_dri.h"
62
63 #include "utils.h"
64 #include "vblank.h"
65
66 #include "drirenderbuffer.h"
67
68 #include "GL/internal/dri_interface.h"
69
70 #define need_GL_ARB_vertex_program
71 #define need_GL_EXT_fog_coord
72 #define need_GL_EXT_gpu_program_parameters
73 #define need_GL_EXT_secondary_color
74 #if 0
75 #define need_GL_EXT_paletted_texture
76 #endif
77 #define need_GL_APPLE_vertex_array_object
78 #define need_GL_NV_vertex_program
79 #include "main/remap_helper.h"
80
81 /* MGA configuration
82 */
83 #include "xmlpool.h"
84
85 PUBLIC const char __driConfigOptions[] =
86 DRI_CONF_BEGIN
87 DRI_CONF_SECTION_PERFORMANCE
88 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
89 DRI_CONF_SECTION_END
90 DRI_CONF_SECTION_QUALITY
91 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
92 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
93 DRI_CONF_SECTION_END
94 DRI_CONF_SECTION_SOFTWARE
95 DRI_CONF_ARB_VERTEX_PROGRAM(true)
96 DRI_CONF_NV_VERTEX_PROGRAM(true)
97 DRI_CONF_SECTION_END
98 DRI_CONF_SECTION_DEBUG
99 DRI_CONF_NO_RAST(false)
100 DRI_CONF_SECTION_END
101 DRI_CONF_END;
102 static const GLuint __driNConfigOptions = 6;
103
104 #ifndef MGA_DEBUG
105 int MGA_DEBUG = 0;
106 #endif
107
108 static const __DRIconfig **
109 mgaFillInModes( __DRIscreen *psp,
110 unsigned pixel_bits, unsigned depth_bits,
111 unsigned stencil_bits, GLboolean have_back_buffer )
112 {
113 __DRIconfig **configs;
114 __GLcontextModes * m;
115 unsigned depth_buffer_factor;
116 unsigned back_buffer_factor;
117 GLenum fb_format;
118 GLenum fb_type;
119 int i;
120
121 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
122 * support pageflipping at all.
123 */
124 static const GLenum back_buffer_modes[] = {
125 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
126 };
127
128 uint8_t depth_bits_array[3];
129 uint8_t stencil_bits_array[3];
130 uint8_t msaa_samples_array[1];
131
132
133 depth_bits_array[0] = 0;
134 depth_bits_array[1] = depth_bits;
135 depth_bits_array[2] = depth_bits;
136
137 /* Just like with the accumulation buffer, always provide some modes
138 * with a stencil buffer. It will be a sw fallback, but some apps won't
139 * care about that.
140 */
141 stencil_bits_array[0] = 0;
142 stencil_bits_array[1] = 0;
143 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
144
145 msaa_samples_array[0] = 0;
146
147 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
148 back_buffer_factor = (have_back_buffer) ? 2 : 1;
149
150 if ( pixel_bits == 16 ) {
151 fb_format = GL_RGB;
152 fb_type = GL_UNSIGNED_SHORT_5_6_5;
153 }
154 else {
155 fb_format = GL_BGR;
156 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
157 }
158
159 configs = driCreateConfigs(fb_format, fb_type,
160 depth_bits_array, stencil_bits_array,
161 depth_buffer_factor,
162 back_buffer_modes, back_buffer_factor,
163 msaa_samples_array, 1, GL_TRUE);
164 if (configs == NULL) {
165 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
166 __func__, __LINE__ );
167 return NULL;
168 }
169
170 /* Mark the visual as slow if there are "fake" stencil bits.
171 */
172 for (i = 0; configs[i]; i++) {
173 m = &configs[i]->modes;
174 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
175 m->visualRating = GLX_SLOW_CONFIG;
176 }
177 }
178
179 return (const __DRIconfig **) configs;
180 }
181
182 const __DRIextension *mgaScreenExtensions[] = {
183 &driReadDrawableExtension,
184 &driSwapControlExtension.base,
185 &driFrameTrackingExtension.base,
186 &driMediaStreamCounterExtension.base,
187 NULL
188 };
189
190 static GLboolean
191 mgaInitDriver(__DRIscreen *sPriv)
192 {
193 mgaScreenPrivate *mgaScreen;
194 MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
195
196 if (sPriv->devPrivSize != sizeof(MGADRIRec)) {
197 fprintf(stderr,"\nERROR! sizeof(MGADRIRec) does not match passed size from device driver\n");
198 return GL_FALSE;
199 }
200
201 /* Allocate the private area */
202 mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
203 if (!mgaScreen) {
204 __driUtilMessage("Couldn't malloc screen struct");
205 return GL_FALSE;
206 }
207
208 mgaScreen->sPriv = sPriv;
209 sPriv->private = (void *)mgaScreen;
210
211 if (sPriv->drm_version.minor >= 1) {
212 int ret;
213 drm_mga_getparam_t gp;
214
215 gp.param = MGA_PARAM_IRQ_NR;
216 gp.value = &mgaScreen->irq;
217 mgaScreen->irq = 0;
218
219 ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
220 &gp, sizeof(gp));
221 if (ret) {
222 fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
223 FREE(mgaScreen);
224 sPriv->private = NULL;
225 return GL_FALSE;
226 }
227 }
228
229 sPriv->extensions = mgaScreenExtensions;
230
231 if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
232 serverInfo->chipset != MGA_CARD_TYPE_G400) {
233 FREE(mgaScreen);
234 sPriv->private = NULL;
235 __driUtilMessage("Unrecognized chipset");
236 return GL_FALSE;
237 }
238
239
240 mgaScreen->chipset = serverInfo->chipset;
241 mgaScreen->cpp = serverInfo->cpp;
242
243 mgaScreen->agpMode = serverInfo->agpMode;
244
245 mgaScreen->frontPitch = serverInfo->frontPitch;
246 mgaScreen->frontOffset = serverInfo->frontOffset;
247 mgaScreen->backOffset = serverInfo->backOffset;
248 mgaScreen->backPitch = serverInfo->backPitch;
249 mgaScreen->depthOffset = serverInfo->depthOffset;
250 mgaScreen->depthPitch = serverInfo->depthPitch;
251
252
253 /* The only reason that the MMIO region needs to be accessable and the
254 * primary DMA region base address needs to be known is so that the driver
255 * can busy wait for certain DMA operations to complete (see
256 * mgaWaitForFrameCompletion in mgaioctl.c).
257 *
258 * Starting with MGA DRM version 3.2, these are completely unneeded as
259 * there is a new, in-kernel mechanism for handling the wait.
260 */
261
262 if (mgaScreen->sPriv->drm_version.minor < 2) {
263 mgaScreen->mmio.handle = serverInfo->registers.handle;
264 mgaScreen->mmio.size = serverInfo->registers.size;
265 if ( drmMap( sPriv->fd,
266 mgaScreen->mmio.handle, mgaScreen->mmio.size,
267 &mgaScreen->mmio.map ) < 0 ) {
268 FREE( mgaScreen );
269 sPriv->private = NULL;
270 __driUtilMessage( "Couldn't map MMIO registers" );
271 return GL_FALSE;
272 }
273
274 mgaScreen->primary.handle = serverInfo->primary.handle;
275 mgaScreen->primary.size = serverInfo->primary.size;
276 }
277 else {
278 (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) );
279 (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) );
280 }
281
282 mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
283 mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
284 PDEA_pagpxfer_enable | 1);
285
286 mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
287 mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
288
289
290 /* The texVirtual array stores the base addresses in the CPU's address
291 * space of the texture memory pools. The base address of the on-card
292 * memory pool is calculated as an offset of the base of video memory. The
293 * AGP texture pool has to be mapped into the processes address space by
294 * the DRM.
295 */
296
297 mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
298 serverInfo->textureOffset);
299
300 if ( serverInfo->agpTextureSize > 0 ) {
301 if (drmMap(sPriv->fd, serverInfo->agpTextureOffset,
302 serverInfo->agpTextureSize,
303 (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0) {
304 FREE(mgaScreen);
305 sPriv->private = NULL;
306 __driUtilMessage("Couldn't map agptexture region");
307 return GL_FALSE;
308 }
309 }
310
311
312 /* For calculating setupdma addresses.
313 */
314
315 mgaScreen->bufs = drmMapBufs(sPriv->fd);
316 if (!mgaScreen->bufs) {
317 FREE(mgaScreen);
318 sPriv->private = NULL;
319 __driUtilMessage("Couldn't map dma buffers");
320 return GL_FALSE;
321 }
322 mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
323
324 /* parse information in __driConfigOptions */
325 driParseOptionInfo (&mgaScreen->optionCache,
326 __driConfigOptions, __driNConfigOptions);
327
328 return GL_TRUE;
329 }
330
331
332 static void
333 mgaDestroyScreen(__DRIscreen *sPriv)
334 {
335 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
336
337 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
338 fprintf(stderr, "mgaDestroyScreen\n");
339
340 drmUnmapBufs(mgaScreen->bufs);
341
342
343 /* free all option information */
344 driDestroyOptionInfo (&mgaScreen->optionCache);
345
346 FREE(mgaScreen);
347 sPriv->private = NULL;
348 }
349
350
351 extern const struct tnl_pipeline_stage _mga_render_stage;
352
353 static const struct tnl_pipeline_stage *mga_pipeline[] = {
354 &_tnl_vertex_transform_stage,
355 &_tnl_normal_transform_stage,
356 &_tnl_lighting_stage,
357 &_tnl_fog_coordinate_stage,
358 &_tnl_texgen_stage,
359 &_tnl_texture_transform_stage,
360 &_tnl_vertex_program_stage,
361
362 /* REMOVE: point attenuation stage */
363 #if 0
364 &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
365 /* Need new ioctl for wacceptseq */
366 #endif
367 &_tnl_render_stage,
368 0,
369 };
370
371
372 static const struct dri_extension g400_extensions[] =
373 {
374 { "GL_ARB_multitexture", NULL },
375 { "GL_ARB_texture_env_add", NULL },
376 { "GL_ARB_texture_env_combine", NULL },
377 { "GL_ARB_texture_env_crossbar", NULL },
378 { "GL_EXT_texture_env_combine", NULL },
379 { "GL_EXT_texture_edge_clamp", NULL },
380 { "GL_ATI_texture_env_combine3", NULL },
381 { NULL, NULL }
382 };
383
384 static const struct dri_extension card_extensions[] =
385 {
386 { "GL_ARB_texture_rectangle", NULL },
387 { "GL_EXT_blend_logic_op", NULL },
388 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
389 /* paletted_textures currently doesn't work, but we could fix them later */
390 #if defined( need_GL_EXT_paletted_texture )
391 { "GL_EXT_shared_texture_palette", NULL },
392 { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
393 #endif
394 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
395 { "GL_EXT_stencil_wrap", NULL },
396 { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
397 { "GL_MESA_ycbcr_texture", NULL },
398 { "GL_SGIS_generate_mipmap", NULL },
399 { NULL, NULL }
400 };
401
402 static const struct dri_extension ARB_vp_extensions[] = {
403 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
404 { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
405 { NULL, NULL }
406 };
407
408 static const struct dri_extension NV_vp_extensions[] = {
409 { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
410 { "GL_NV_vertex_program1_1", NULL },
411 { NULL, NULL }
412 };
413
414 static const struct dri_debug_control debug_control[] =
415 {
416 { "fall", DEBUG_VERBOSE_FALLBACK },
417 { "tex", DEBUG_VERBOSE_TEXTURE },
418 { "ioctl", DEBUG_VERBOSE_IOCTL },
419 { "verb", DEBUG_VERBOSE_MSG },
420 { "dri", DEBUG_VERBOSE_DRI },
421 { NULL, 0 }
422 };
423
424
425 static GLboolean
426 mgaCreateContext( gl_api api,
427 const __GLcontextModes *mesaVis,
428 __DRIcontext *driContextPriv,
429 void *sharedContextPrivate )
430 {
431 int i;
432 unsigned maxlevels;
433 GLcontext *ctx, *shareCtx;
434 mgaContextPtr mmesa;
435 __DRIscreen *sPriv = driContextPriv->driScreenPriv;
436 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
437 drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
438 mgaScreen->sarea_priv_offset);
439 struct dd_function_table functions;
440
441 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
442 fprintf(stderr, "mgaCreateContext\n");
443
444 /* allocate mga context */
445 mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
446 if (!mmesa) {
447 return GL_FALSE;
448 }
449
450 /* Init default driver functions then plug in our Radeon-specific functions
451 * (the texture functions are especially important)
452 */
453 _mesa_init_driver_functions( &functions );
454 mgaInitDriverFuncs( &functions );
455 mgaInitTextureFuncs( &functions );
456 mgaInitIoctlFuncs( &functions );
457
458 /* Allocate the Mesa context */
459 if (sharedContextPrivate)
460 shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
461 else
462 shareCtx = NULL;
463 mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
464 &functions, (void *) mmesa);
465 if (!mmesa->glCtx) {
466 FREE(mmesa);
467 return GL_FALSE;
468 }
469 driContextPriv->driverPrivate = mmesa;
470
471 /* Init mga state */
472 mmesa->hHWContext = driContextPriv->hHWContext;
473 mmesa->driFd = sPriv->fd;
474 mmesa->driHwLock = &sPriv->pSAREA->lock;
475
476 mmesa->mgaScreen = mgaScreen;
477 mmesa->driScreen = sPriv;
478 mmesa->sarea = (void *)saPriv;
479
480 /* Parse configuration files */
481 driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
482 sPriv->myNum, "mga");
483
484 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
485 make_empty_list( & mmesa->swapped );
486
487 mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
488 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
489 mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
490 mgaScreen->textureSize[i],
491 6,
492 MGA_NR_TEX_REGIONS,
493 (drmTextureRegionPtr)mmesa->sarea->texList[i],
494 &mmesa->sarea->texAge[i],
495 &mmesa->swapped,
496 sizeof( mgaTextureObject_t ),
497 (destroy_texture_object_t *) mgaDestroyTexObj );
498 }
499
500 /* Set the maximum texture size small enough that we can guarentee
501 * that both texture units can bind a maximal texture and have them
502 * on the card at once.
503 */
504 ctx = mmesa->glCtx;
505 if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
506 ctx->Const.MaxTextureUnits = 1;
507 ctx->Const.MaxTextureImageUnits = 1;
508 ctx->Const.MaxTextureCoordUnits = 1;
509 maxlevels = G200_TEX_MAXLEVELS;
510
511 }
512 else {
513 ctx->Const.MaxTextureUnits = 2;
514 ctx->Const.MaxTextureImageUnits = 2;
515 ctx->Const.MaxTextureCoordUnits = 2;
516 maxlevels = G400_TEX_MAXLEVELS;
517 }
518
519 driCalculateMaxTextureLevels( mmesa->texture_heaps,
520 mmesa->nr_heaps,
521 & ctx->Const,
522 4,
523 11, /* max 2D texture size is 2048x2048 */
524 0, /* 3D textures unsupported. */
525 0, /* cube textures unsupported. */
526 11, /* max texture rect size is 2048x2048 */
527 maxlevels,
528 GL_FALSE,
529 0 );
530
531 ctx->Const.MinLineWidth = 1.0;
532 ctx->Const.MinLineWidthAA = 1.0;
533 ctx->Const.MaxLineWidth = 10.0;
534 ctx->Const.MaxLineWidthAA = 10.0;
535 ctx->Const.LineWidthGranularity = 1.0;
536
537 ctx->Const.MaxDrawBuffers = 1;
538
539 mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
540 "texture_depth");
541 if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
542 mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ?
543 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
544 mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
545
546 switch (mesaVis->depthBits) {
547 case 16:
548 mmesa->depth_scale = 1.0/(GLdouble)0xffff;
549 mmesa->depth_clear_mask = ~0;
550 mmesa->ClearDepth = 0xffff;
551 break;
552 case 24:
553 mmesa->depth_scale = 1.0/(GLdouble)0xffffff;
554 if (mmesa->hw_stencil) {
555 mmesa->depth_clear_mask = 0xffffff00;
556 mmesa->stencil_clear_mask = 0x000000ff;
557 } else
558 mmesa->depth_clear_mask = ~0;
559 mmesa->ClearDepth = 0xffffff00;
560 break;
561 case 32:
562 mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
563 mmesa->depth_clear_mask = ~0;
564 mmesa->ClearDepth = 0xffffffff;
565 break;
566 };
567
568 mmesa->haveHwStipple = GL_FALSE;
569 mmesa->RenderIndex = -1; /* impossible value */
570 mmesa->dirty = ~0;
571 mmesa->vertex_format = 0;
572 mmesa->CurrentTexObj[0] = 0;
573 mmesa->CurrentTexObj[1] = 0;
574 mmesa->tmu_source[0] = 0;
575 mmesa->tmu_source[1] = 1;
576
577 mmesa->texAge[0] = 0;
578 mmesa->texAge[1] = 0;
579
580 /* Initialize the software rasterizer and helper modules.
581 */
582 _swrast_CreateContext( ctx );
583 _vbo_CreateContext( ctx );
584 _tnl_CreateContext( ctx );
585
586 _swsetup_CreateContext( ctx );
587
588 /* Install the customized pipeline:
589 */
590 _tnl_destroy_pipeline( ctx );
591 _tnl_install_pipeline( ctx, mga_pipeline );
592
593 /* Configure swrast and T&L to match hardware characteristics:
594 */
595 _swrast_allow_pixel_fog( ctx, GL_FALSE );
596 _swrast_allow_vertex_fog( ctx, GL_TRUE );
597 _tnl_allow_pixel_fog( ctx, GL_FALSE );
598 _tnl_allow_vertex_fog( ctx, GL_TRUE );
599
600 mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
601
602 ctx->DriverCtx = (void *) mmesa;
603 mmesa->glCtx = ctx;
604
605 driInitExtensions( ctx, card_extensions, GL_FALSE );
606
607 if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
608 driInitExtensions( ctx, g400_extensions, GL_FALSE );
609 }
610
611 if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) {
612 driInitExtensions(ctx, ARB_vp_extensions, GL_FALSE);
613 }
614
615 if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) {
616 driInitExtensions( ctx, NV_vp_extensions, GL_FALSE );
617 }
618
619
620 /* XXX these should really go right after _mesa_init_driver_functions() */
621 mgaDDInitStateFuncs( ctx );
622 mgaDDInitSpanFuncs( ctx );
623 mgaDDInitPixelFuncs( ctx );
624 mgaDDInitTriFuncs( ctx );
625
626 mgaInitVB( ctx );
627 mgaInitState( mmesa );
628
629 driContextPriv->driverPrivate = (void *) mmesa;
630
631 #if DO_DEBUG
632 MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
633 debug_control );
634 #endif
635
636 (*sPriv->systemTime->getUST)( & mmesa->swap_ust );
637
638 if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
639 fprintf(stderr, "disabling 3D acceleration\n");
640 FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1);
641 }
642
643 return GL_TRUE;
644 }
645
646 static void
647 mgaDestroyContext(__DRIcontext *driContextPriv)
648 {
649 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
650
651 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
652 fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
653 __FILE__, __LINE__ );
654
655 assert(mmesa); /* should never be null */
656 if (mmesa) {
657 GLboolean release_texture_heaps;
658
659
660 release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
661 _swsetup_DestroyContext( mmesa->glCtx );
662 _tnl_DestroyContext( mmesa->glCtx );
663 _vbo_DestroyContext( mmesa->glCtx );
664 _swrast_DestroyContext( mmesa->glCtx );
665
666 mgaFreeVB( mmesa->glCtx );
667
668 /* free the Mesa context */
669 mmesa->glCtx->DriverCtx = NULL;
670 _mesa_destroy_context(mmesa->glCtx);
671
672 if ( release_texture_heaps ) {
673 /* This share group is about to go away, free our private
674 * texture object data.
675 */
676 int i;
677
678 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
679 driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
680 mmesa->texture_heaps[ i ] = NULL;
681 }
682
683 assert( is_empty_list( & mmesa->swapped ) );
684 }
685
686 /* free the option cache */
687 driDestroyOptionCache (&mmesa->optionCache);
688
689 FREE(mmesa);
690 }
691
692 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
693 fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
694 __FILE__, __LINE__ );
695 }
696
697
698 static GLboolean
699 mgaCreateBuffer( __DRIscreen *driScrnPriv,
700 __DRIdrawable *driDrawPriv,
701 const __GLcontextModes *mesaVis,
702 GLboolean isPixmap )
703 {
704 mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private;
705
706 if (isPixmap) {
707 return GL_FALSE; /* not implemented */
708 }
709 else {
710 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
711 mesaVis->depthBits != 24);
712
713 #if 0
714 driDrawPriv->driverPrivate = (void *)
715 _mesa_create_framebuffer(mesaVis,
716 GL_FALSE, /* software depth buffer? */
717 swStencil,
718 mesaVis->accumRedBits > 0,
719 mesaVis->alphaBits > 0 );
720 #else
721 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
722
723 {
724 driRenderbuffer *frontRb
725 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
726 NULL,
727 screen->cpp,
728 screen->frontOffset, screen->frontPitch,
729 driDrawPriv);
730 mgaSetSpanFunctions(frontRb, mesaVis);
731 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
732 }
733
734 if (mesaVis->doubleBufferMode) {
735 driRenderbuffer *backRb
736 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
737 NULL,
738 screen->cpp,
739 screen->backOffset, screen->backPitch,
740 driDrawPriv);
741 mgaSetSpanFunctions(backRb, mesaVis);
742 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
743 }
744
745 if (mesaVis->depthBits == 16) {
746 driRenderbuffer *depthRb
747 = driNewRenderbuffer(MESA_FORMAT_Z16,
748 NULL,
749 screen->cpp,
750 screen->depthOffset, screen->depthPitch,
751 driDrawPriv);
752 mgaSetSpanFunctions(depthRb, mesaVis);
753 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
754 }
755 else if (mesaVis->depthBits == 24) {
756 /* XXX is this right? */
757 if (mesaVis->stencilBits) {
758 driRenderbuffer *depthRb
759 = driNewRenderbuffer(MESA_FORMAT_Z24_S8,
760 NULL,
761 screen->cpp,
762 screen->depthOffset, screen->depthPitch,
763 driDrawPriv);
764 mgaSetSpanFunctions(depthRb, mesaVis);
765 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
766 }
767 else {
768 driRenderbuffer *depthRb
769 = driNewRenderbuffer(MESA_FORMAT_Z32,
770 NULL,
771 screen->cpp,
772 screen->depthOffset, screen->depthPitch,
773 driDrawPriv);
774 mgaSetSpanFunctions(depthRb, mesaVis);
775 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
776 }
777 }
778 else if (mesaVis->depthBits == 32) {
779 driRenderbuffer *depthRb
780 = driNewRenderbuffer(MESA_FORMAT_Z32,
781 NULL,
782 screen->cpp,
783 screen->depthOffset, screen->depthPitch,
784 driDrawPriv);
785 mgaSetSpanFunctions(depthRb, mesaVis);
786 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
787 }
788
789 if (mesaVis->stencilBits > 0 && !swStencil) {
790 driRenderbuffer *stencilRb
791 = driNewRenderbuffer(MESA_FORMAT_S8,
792 NULL,
793 screen->cpp,
794 screen->depthOffset, screen->depthPitch,
795 driDrawPriv);
796 mgaSetSpanFunctions(stencilRb, mesaVis);
797 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
798 }
799
800 _mesa_add_soft_renderbuffers(fb,
801 GL_FALSE, /* color */
802 GL_FALSE, /* depth */
803 swStencil,
804 mesaVis->accumRedBits > 0,
805 GL_FALSE, /* alpha */
806 GL_FALSE /* aux */);
807 driDrawPriv->driverPrivate = (void *) fb;
808 #endif
809
810 return (driDrawPriv->driverPrivate != NULL);
811 }
812 }
813
814
815 static void
816 mgaDestroyBuffer(__DRIdrawable *driDrawPriv)
817 {
818 _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
819 }
820
821 static void
822 mgaSwapBuffers(__DRIdrawable *dPriv)
823 {
824 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
825 mgaContextPtr mmesa;
826 GLcontext *ctx;
827 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
828 ctx = mmesa->glCtx;
829
830 if (ctx->Visual.doubleBufferMode) {
831 _mesa_notifySwapBuffers( ctx );
832 mgaCopyBuffer( dPriv );
833 }
834 } else {
835 /* XXX this shouldn't be an error but we can't handle it for now */
836 _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
837 }
838 }
839
840 static GLboolean
841 mgaUnbindContext(__DRIcontext *driContextPriv)
842 {
843 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
844 if (mmesa)
845 mmesa->dirty = ~0;
846
847 return GL_TRUE;
848 }
849
850 /* This looks buggy to me - the 'b' variable isn't used anywhere...
851 * Hmm - It seems that the drawable is already hooked in to
852 * driDrawablePriv.
853 *
854 * But why are we doing context initialization here???
855 */
856 static GLboolean
857 mgaMakeCurrent(__DRIcontext *driContextPriv,
858 __DRIdrawable *driDrawPriv,
859 __DRIdrawable *driReadPriv)
860 {
861 if (driContextPriv) {
862 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
863
864 if (mmesa->driDrawable != driDrawPriv) {
865 if (driDrawPriv->swap_interval == (unsigned)-1) {
866 driDrawPriv->vblFlags = (mmesa->mgaScreen->irq == 0)
867 ? VBLANK_FLAG_NO_IRQ
868 : driGetDefaultVBlankFlags(&mmesa->optionCache);
869
870 driDrawableInitVBlank( driDrawPriv );
871 }
872
873 mmesa->driDrawable = driDrawPriv;
874 mmesa->dirty = ~0;
875 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
876 }
877
878 mmesa->driReadable = driReadPriv;
879
880 _mesa_make_current(mmesa->glCtx,
881 (GLframebuffer *) driDrawPriv->driverPrivate,
882 (GLframebuffer *) driReadPriv->driverPrivate);
883 }
884 else {
885 _mesa_make_current(NULL, NULL, NULL);
886 }
887
888 return GL_TRUE;
889 }
890
891
892 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
893 {
894 __DRIdrawable *dPriv = mmesa->driDrawable;
895 drm_mga_sarea_t *sarea = mmesa->sarea;
896 int me = mmesa->hHWContext;
897 int i;
898
899 drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
900
901 DRI_VALIDATE_DRAWABLE_INFO( mmesa->driScreen, dPriv );
902 if (*(dPriv->pStamp) != mmesa->lastStamp) {
903 mmesa->lastStamp = *(dPriv->pStamp);
904 mmesa->SetupNewInputs |= VERT_BIT_POS;
905 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
906 mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
907 driUpdateFramebufferSize(mmesa->glCtx, dPriv);
908 }
909
910 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
911
912 mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
913
914 if (sarea->ctxOwner != me) {
915 mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
916 MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
917 sarea->ctxOwner=me;
918 }
919
920 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
921 DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
922 }
923 }
924
925
926 /**
927 * This is the driver specific part of the createNewScreen entry point.
928 *
929 * \todo maybe fold this into intelInitDriver
930 *
931 * \return the __GLcontextModes supported by this driver
932 */
933 static const __DRIconfig **mgaInitScreen(__DRIscreen *psp)
934 {
935 static const __DRIversion ddx_expected = { 1, 2, 0 };
936 static const __DRIversion dri_expected = { 4, 0, 0 };
937 static const __DRIversion drm_expected = { 3, 0, 0 };
938 MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv;
939
940 if ( ! driCheckDriDdxDrmVersions2( "MGA",
941 &psp->dri_version, & dri_expected,
942 &psp->ddx_version, & ddx_expected,
943 &psp->drm_version, & drm_expected ) )
944 return NULL;
945
946
947 if (!mgaInitDriver(psp))
948 return NULL;
949
950 return mgaFillInModes( psp,
951 dri_priv->cpp * 8,
952 (dri_priv->cpp == 2) ? 16 : 24,
953 (dri_priv->cpp == 2) ? 0 : 8,
954 (dri_priv->backOffset != dri_priv->depthOffset) );
955 }
956
957
958 /**
959 * Get information about previous buffer swaps.
960 */
961 static int
962 getSwapInfo( __DRIdrawable *dPriv, __DRIswapInfo * sInfo )
963 {
964 mgaContextPtr mmesa;
965
966 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
967 || (dPriv->driContextPriv->driverPrivate == NULL)
968 || (sInfo == NULL) ) {
969 return -1;
970 }
971
972 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
973 sInfo->swap_count = mmesa->swap_count;
974 sInfo->swap_ust = mmesa->swap_ust;
975 sInfo->swap_missed_count = mmesa->swap_missed_count;
976
977 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
978 ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
979 : 0.0;
980
981 return 0;
982 }
983
984 const struct __DriverAPIRec driDriverAPI = {
985 .InitScreen = mgaInitScreen,
986 .DestroyScreen = mgaDestroyScreen,
987 .CreateContext = mgaCreateContext,
988 .DestroyContext = mgaDestroyContext,
989 .CreateBuffer = mgaCreateBuffer,
990 .DestroyBuffer = mgaDestroyBuffer,
991 .SwapBuffers = mgaSwapBuffers,
992 .MakeCurrent = mgaMakeCurrent,
993 .UnbindContext = mgaUnbindContext,
994 .GetSwapInfo = getSwapInfo,
995 .GetDrawableMSC = driDrawableGetMSC32,
996 .WaitForMSC = driWaitForMSC32,
997 .WaitForSBC = NULL,
998 .SwapBuffersMSC = NULL
999 };
1000
1001 /* This is the table of extensions that the loader will dlsym() for. */
1002 PUBLIC const __DRIextension *__driDriverExtensions[] = {
1003 &driCoreExtension.base,
1004 &driLegacyExtension.base,
1005 NULL
1006 };