1 /**************************************************************************
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Gareth Hughes <gareth@valinux.com>
31 * Kevin E. Martin <martin@valinux.com>
37 #include "r128_context.h"
38 #include "r128_ioctl.h"
39 #include "r128_span.h"
41 #include "main/context.h"
42 #include "main/imports.h"
43 #include "main/framebuffer.h"
44 #include "main/renderbuffer.h"
49 #include "GL/internal/dri_interface.h"
55 PUBLIC const char __driConfigOptions[] =
57 DRI_CONF_SECTION_PERFORMANCE
58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
60 DRI_CONF_SECTION_QUALITY
61 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
63 DRI_CONF_SECTION_DEBUG
64 DRI_CONF_NO_RAST(false)
66 DRI_CONF_PERFORMANCE_BOXES(false)
71 static const GLuint __driNConfigOptions = 4;
73 static const GLuint __driNConfigOptions = 3;
77 /* Including xf86PciInfo.h introduces a bunch of errors...
79 #define PCI_CHIP_RAGE128LE 0x4C45
80 #define PCI_CHIP_RAGE128LF 0x4C46
81 #define PCI_CHIP_RAGE128PF 0x5046
82 #define PCI_CHIP_RAGE128PR 0x5052
83 #define PCI_CHIP_RAGE128RE 0x5245
84 #define PCI_CHIP_RAGE128RF 0x5246
85 #define PCI_CHIP_RAGE128RK 0x524B
86 #define PCI_CHIP_RAGE128RL 0x524C
90 /* Create the device specific screen private data struct.
93 r128CreateScreen( __DRIscreen *sPriv )
95 r128ScreenPtr r128Screen;
96 R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
99 if (sPriv->devPrivSize != sizeof(R128DRIRec)) {
100 fprintf(stderr,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
104 /* Allocate the private area */
105 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
106 if ( !r128Screen ) return NULL;
108 /* parse information in __driConfigOptions */
109 driParseOptionInfo (&r128Screen->optionCache,
110 __driConfigOptions, __driNConfigOptions);
112 /* This is first since which regions we map depends on whether or
113 * not we are using a PCI card.
115 r128Screen->IsPCI = r128DRIPriv->IsPCI;
116 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
118 if (sPriv->drm_version.minor >= 3) {
119 drm_r128_getparam_t gp;
122 gp.param = R128_PARAM_IRQ_NR;
123 gp.value = &r128Screen->irq;
125 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
128 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
134 r128Screen->mmio.handle = r128DRIPriv->registerHandle;
135 r128Screen->mmio.size = r128DRIPriv->registerSize;
136 if ( drmMap( sPriv->fd,
137 r128Screen->mmio.handle,
138 r128Screen->mmio.size,
139 (drmAddressPtr)&r128Screen->mmio.map ) ) {
144 r128Screen->buffers = drmMapBufs( sPriv->fd );
145 if ( !r128Screen->buffers ) {
146 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
151 if ( !r128Screen->IsPCI ) {
152 r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
153 r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
154 if ( drmMap( sPriv->fd,
155 r128Screen->agpTextures.handle,
156 r128Screen->agpTextures.size,
157 (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
158 drmUnmapBufs( r128Screen->buffers );
159 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
165 switch ( r128DRIPriv->deviceID ) {
166 case PCI_CHIP_RAGE128RE:
167 case PCI_CHIP_RAGE128RF:
168 case PCI_CHIP_RAGE128RK:
169 case PCI_CHIP_RAGE128RL:
170 r128Screen->chipset = R128_CARD_TYPE_R128;
172 case PCI_CHIP_RAGE128PF:
173 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
175 case PCI_CHIP_RAGE128LE:
176 case PCI_CHIP_RAGE128LF:
177 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
180 r128Screen->chipset = R128_CARD_TYPE_R128;
184 r128Screen->cpp = r128DRIPriv->bpp / 8;
185 r128Screen->AGPMode = r128DRIPriv->AGPMode;
187 r128Screen->frontOffset = r128DRIPriv->frontOffset;
188 r128Screen->frontPitch = r128DRIPriv->frontPitch;
189 r128Screen->backOffset = r128DRIPriv->backOffset;
190 r128Screen->backPitch = r128DRIPriv->backPitch;
191 r128Screen->depthOffset = r128DRIPriv->depthOffset;
192 r128Screen->depthPitch = r128DRIPriv->depthPitch;
193 r128Screen->spanOffset = r128DRIPriv->spanOffset;
195 if ( r128DRIPriv->textureSize == 0 ) {
196 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] =
197 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
198 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
199 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] =
200 r128DRIPriv->log2AGPTexGran;
202 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureOffset;
203 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize;
204 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran;
207 if ( !r128Screen->agpTextures.map || r128DRIPriv->textureSize == 0 ) {
208 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
209 r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0;
210 r128Screen->texSize[R128_AGP_TEX_HEAP] = 0;
211 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] = 0;
213 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
214 r128Screen->texOffset[R128_AGP_TEX_HEAP] =
215 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
216 r128Screen->texSize[R128_AGP_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
217 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] =
218 r128DRIPriv->log2AGPTexGran;
221 r128Screen->driScreen = sPriv;
224 if ( r128Screen->irq != 0 ) {
225 r128Screen->extensions[i++] = &driSwapControlExtension.base;
226 r128Screen->extensions[i++] = &driMediaStreamCounterExtension.base;
228 r128Screen->extensions[i++] = NULL;
229 sPriv->extensions = r128Screen->extensions;
234 /* Destroy the device specific screen private data struct.
237 r128DestroyScreen( __DRIscreen *sPriv )
239 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
244 if ( !r128Screen->IsPCI ) {
245 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
246 r128Screen->agpTextures.size );
248 drmUnmapBufs( r128Screen->buffers );
249 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
251 /* free all option information */
252 driDestroyOptionInfo (&r128Screen->optionCache);
255 sPriv->private = NULL;
259 /* Create and initialize the Mesa and driver specific pixmap buffer
263 r128CreateBuffer( __DRIscreen *driScrnPriv,
264 __DRIdrawable *driDrawPriv,
265 const struct gl_config *mesaVis,
268 r128ScreenPtr screen = (r128ScreenPtr) driScrnPriv->private;
271 return GL_FALSE; /* not implemented */
274 const GLboolean swDepth = GL_FALSE;
275 const GLboolean swAlpha = GL_FALSE;
276 const GLboolean swAccum = mesaVis->accumRedBits > 0;
277 const GLboolean swStencil = mesaVis->stencilBits > 0 &&
278 mesaVis->depthBits != 24;
279 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
282 driRenderbuffer *frontRb
283 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
286 screen->frontOffset, screen->frontPitch,
288 r128SetSpanFunctions(frontRb, mesaVis);
289 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
292 if (mesaVis->doubleBufferMode) {
293 driRenderbuffer *backRb
294 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
297 screen->backOffset, screen->backPitch,
299 r128SetSpanFunctions(backRb, mesaVis);
300 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
303 if (mesaVis->depthBits == 16) {
304 driRenderbuffer *depthRb
305 = driNewRenderbuffer(MESA_FORMAT_Z16,
308 screen->depthOffset, screen->depthPitch,
310 r128SetSpanFunctions(depthRb, mesaVis);
311 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
313 else if (mesaVis->depthBits == 24) {
314 driRenderbuffer *depthRb
315 = driNewRenderbuffer(MESA_FORMAT_S8_Z24,
318 screen->depthOffset, screen->depthPitch,
320 r128SetSpanFunctions(depthRb, mesaVis);
321 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
324 if (mesaVis->stencilBits > 0 && !swStencil) {
325 driRenderbuffer *stencilRb
326 = driNewRenderbuffer(MESA_FORMAT_S8,
329 screen->depthOffset, screen->depthPitch,
331 r128SetSpanFunctions(stencilRb, mesaVis);
332 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
335 _mesa_add_soft_renderbuffers(fb,
336 GL_FALSE, /* color */
342 driDrawPriv->driverPrivate = (void *) fb;
344 return (driDrawPriv->driverPrivate != NULL);
350 r128DestroyBuffer(__DRIdrawable *driDrawPriv)
352 _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
356 /* Copy the back color buffer to the front color buffer */
358 r128SwapBuffers(__DRIdrawable *dPriv)
360 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
361 r128ContextPtr rmesa;
362 struct gl_context *ctx;
363 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
365 if (ctx->Visual.doubleBufferMode) {
366 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
367 if ( rmesa->doPageFlip ) {
368 r128PageFlip( dPriv );
371 r128CopyBuffer( dPriv );
376 /* XXX this shouldn't be an error but we can't handle it for now */
377 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
382 /* Initialize the driver specific screen private data.
385 r128InitDriver( __DRIscreen *sPriv )
387 sPriv->private = (void *) r128CreateScreen( sPriv );
389 if ( !sPriv->private ) {
390 r128DestroyScreen( sPriv );
397 static const __DRIconfig **
398 r128FillInModes( __DRIscreen *psp,
399 unsigned pixel_bits, unsigned depth_bits,
400 unsigned stencil_bits, GLboolean have_back_buffer )
402 __DRIconfig **configs;
403 struct gl_config * m;
404 unsigned depth_buffer_factor;
405 unsigned back_buffer_factor;
410 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
411 * enough to add support. Basically, if a context is created with an
412 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
413 * will never be used.
415 static const GLenum back_buffer_modes[] = {
416 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
419 uint8_t depth_bits_array[2];
420 uint8_t stencil_bits_array[2];
421 uint8_t msaa_samples_array[1];
423 depth_bits_array[0] = depth_bits;
424 depth_bits_array[1] = depth_bits;
426 /* Just like with the accumulation buffer, always provide some modes
427 * with a stencil buffer. It will be a sw fallback, but some apps won't
430 stencil_bits_array[0] = 0;
431 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
433 msaa_samples_array[0] = 0;
435 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
436 back_buffer_factor = (have_back_buffer) ? 2 : 1;
438 if ( pixel_bits == 16 ) {
440 fb_type = GL_UNSIGNED_SHORT_5_6_5;
444 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
447 configs = driCreateConfigs(fb_format, fb_type,
448 depth_bits_array, stencil_bits_array,
449 depth_buffer_factor, back_buffer_modes,
451 msaa_samples_array, 1, GL_TRUE);
452 if (configs == NULL) {
453 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
458 /* Mark the visual as slow if there are "fake" stencil bits.
460 for (i = 0; configs[i]; i++) {
461 m = &configs[i]->modes;
462 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
463 m->visualRating = GLX_SLOW_CONFIG;
467 return (const __DRIconfig **) configs;
472 * This is the driver specific part of the createNewScreen entry point.
474 * \todo maybe fold this into intelInitDriver
476 * \return the struct gl_config supported by this driver
478 static const __DRIconfig **
479 r128InitScreen(__DRIscreen *psp)
481 static const __DRIversion ddx_expected = { 4, 0, 0 };
482 static const __DRIversion dri_expected = { 4, 0, 0 };
483 static const __DRIversion drm_expected = { 2, 2, 0 };
484 R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
486 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
487 &psp->dri_version, & dri_expected,
488 &psp->ddx_version, & ddx_expected,
489 &psp->drm_version, & drm_expected ) )
492 if (!r128InitDriver(psp))
495 return r128FillInModes( psp,
497 (dri_priv->bpp == 16) ? 16 : 24,
498 (dri_priv->bpp == 16) ? 0 : 8,
499 (dri_priv->backOffset != dri_priv->depthOffset) );
502 const struct __DriverAPIRec driDriverAPI = {
503 .InitScreen = r128InitScreen,
504 .DestroyScreen = r128DestroyScreen,
505 .CreateContext = r128CreateContext,
506 .DestroyContext = r128DestroyContext,
507 .CreateBuffer = r128CreateBuffer,
508 .DestroyBuffer = r128DestroyBuffer,
509 .SwapBuffers = r128SwapBuffers,
510 .MakeCurrent = r128MakeCurrent,
511 .UnbindContext = r128UnbindContext,
513 .GetDrawableMSC = driDrawableGetMSC32,
514 .WaitForMSC = driWaitForMSC32,
516 .SwapBuffersMSC = NULL
519 /* This is the table of extensions that the loader will dlsym() for. */
520 PUBLIC const __DRIextension *__driDriverExtensions[] = {
521 &driCoreExtension.base,
522 &driLegacyExtension.base,