Merge commit 'origin/gallium-0.2' into gallium-master-merge
[mesa.git] / src / mesa / drivers / dri / r128 / r128_screen.c
1 /**************************************************************************
2
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
4 Cedar Park, Texas.
5 All Rights Reserved.
6
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:
13
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
16 Software.
17
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.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Gareth Hughes <gareth@valinux.com>
31 * Kevin E. Martin <martin@valinux.com>
32 *
33 */
34
35 #include "r128_dri.h"
36
37 #include "r128_context.h"
38 #include "r128_ioctl.h"
39 #include "r128_span.h"
40 #include "r128_tris.h"
41
42 #include "main/context.h"
43 #include "main/imports.h"
44 #include "main/framebuffer.h"
45 #include "main/renderbuffer.h"
46
47 #include "utils.h"
48 #include "vblank.h"
49
50 #include "GL/internal/dri_interface.h"
51
52 /* R128 configuration
53 */
54 #include "xmlpool.h"
55
56 PUBLIC const char __driConfigOptions[] =
57 DRI_CONF_BEGIN
58 DRI_CONF_SECTION_PERFORMANCE
59 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
60 DRI_CONF_SECTION_END
61 DRI_CONF_SECTION_QUALITY
62 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
63 DRI_CONF_SECTION_END
64 DRI_CONF_SECTION_DEBUG
65 DRI_CONF_NO_RAST(false)
66 #if ENABLE_PERF_BOXES
67 DRI_CONF_PERFORMANCE_BOXES(false)
68 #endif
69 DRI_CONF_SECTION_END
70 DRI_CONF_END;
71 #if ENABLE_PERF_BOXES
72 static const GLuint __driNConfigOptions = 4;
73 #else
74 static const GLuint __driNConfigOptions = 3;
75 #endif
76
77 extern const struct dri_extension card_extensions[];
78
79 #if 1
80 /* Including xf86PciInfo.h introduces a bunch of errors...
81 */
82 #define PCI_CHIP_RAGE128LE 0x4C45
83 #define PCI_CHIP_RAGE128LF 0x4C46
84 #define PCI_CHIP_RAGE128PF 0x5046
85 #define PCI_CHIP_RAGE128PR 0x5052
86 #define PCI_CHIP_RAGE128RE 0x5245
87 #define PCI_CHIP_RAGE128RF 0x5246
88 #define PCI_CHIP_RAGE128RK 0x524B
89 #define PCI_CHIP_RAGE128RL 0x524C
90 #endif
91
92
93 /* Create the device specific screen private data struct.
94 */
95 static r128ScreenPtr
96 r128CreateScreen( __DRIscreenPrivate *sPriv )
97 {
98 r128ScreenPtr r128Screen;
99 R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
100 int i;
101
102 if (sPriv->devPrivSize != sizeof(R128DRIRec)) {
103 fprintf(stderr,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
104 return GL_FALSE;
105 }
106
107 /* Allocate the private area */
108 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
109 if ( !r128Screen ) return NULL;
110
111 /* parse information in __driConfigOptions */
112 driParseOptionInfo (&r128Screen->optionCache,
113 __driConfigOptions, __driNConfigOptions);
114
115 /* This is first since which regions we map depends on whether or
116 * not we are using a PCI card.
117 */
118 r128Screen->IsPCI = r128DRIPriv->IsPCI;
119 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
120
121 if (sPriv->drm_version.minor >= 3) {
122 drm_r128_getparam_t gp;
123 int ret;
124
125 gp.param = R128_PARAM_IRQ_NR;
126 gp.value = &r128Screen->irq;
127
128 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
129 &gp, sizeof(gp));
130 if (ret) {
131 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
132 FREE( r128Screen );
133 return NULL;
134 }
135 }
136
137 r128Screen->mmio.handle = r128DRIPriv->registerHandle;
138 r128Screen->mmio.size = r128DRIPriv->registerSize;
139 if ( drmMap( sPriv->fd,
140 r128Screen->mmio.handle,
141 r128Screen->mmio.size,
142 (drmAddressPtr)&r128Screen->mmio.map ) ) {
143 FREE( r128Screen );
144 return NULL;
145 }
146
147 r128Screen->buffers = drmMapBufs( sPriv->fd );
148 if ( !r128Screen->buffers ) {
149 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
150 FREE( r128Screen );
151 return NULL;
152 }
153
154 if ( !r128Screen->IsPCI ) {
155 r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
156 r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
157 if ( drmMap( sPriv->fd,
158 r128Screen->agpTextures.handle,
159 r128Screen->agpTextures.size,
160 (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
161 drmUnmapBufs( r128Screen->buffers );
162 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
163 FREE( r128Screen );
164 return NULL;
165 }
166 }
167
168 switch ( r128DRIPriv->deviceID ) {
169 case PCI_CHIP_RAGE128RE:
170 case PCI_CHIP_RAGE128RF:
171 case PCI_CHIP_RAGE128RK:
172 case PCI_CHIP_RAGE128RL:
173 r128Screen->chipset = R128_CARD_TYPE_R128;
174 break;
175 case PCI_CHIP_RAGE128PF:
176 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
177 break;
178 case PCI_CHIP_RAGE128LE:
179 case PCI_CHIP_RAGE128LF:
180 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
181 break;
182 default:
183 r128Screen->chipset = R128_CARD_TYPE_R128;
184 break;
185 }
186
187 r128Screen->cpp = r128DRIPriv->bpp / 8;
188 r128Screen->AGPMode = r128DRIPriv->AGPMode;
189
190 r128Screen->frontOffset = r128DRIPriv->frontOffset;
191 r128Screen->frontPitch = r128DRIPriv->frontPitch;
192 r128Screen->backOffset = r128DRIPriv->backOffset;
193 r128Screen->backPitch = r128DRIPriv->backPitch;
194 r128Screen->depthOffset = r128DRIPriv->depthOffset;
195 r128Screen->depthPitch = r128DRIPriv->depthPitch;
196 r128Screen->spanOffset = r128DRIPriv->spanOffset;
197
198 if ( r128DRIPriv->textureSize == 0 ) {
199 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] =
200 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
201 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
202 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] =
203 r128DRIPriv->log2AGPTexGran;
204 } else {
205 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureOffset;
206 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize;
207 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran;
208 }
209
210 if ( !r128Screen->agpTextures.map || r128DRIPriv->textureSize == 0 ) {
211 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
212 r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0;
213 r128Screen->texSize[R128_AGP_TEX_HEAP] = 0;
214 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] = 0;
215 } else {
216 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
217 r128Screen->texOffset[R128_AGP_TEX_HEAP] =
218 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
219 r128Screen->texSize[R128_AGP_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
220 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] =
221 r128DRIPriv->log2AGPTexGran;
222 }
223
224 r128Screen->driScreen = sPriv;
225
226 i = 0;
227 r128Screen->extensions[i++] = &driFrameTrackingExtension.base;
228 if ( r128Screen->irq != 0 ) {
229 r128Screen->extensions[i++] = &driSwapControlExtension.base;
230 r128Screen->extensions[i++] = &driMediaStreamCounterExtension.base;
231 }
232 r128Screen->extensions[i++] = NULL;
233 sPriv->extensions = r128Screen->extensions;
234
235 return r128Screen;
236 }
237
238 /* Destroy the device specific screen private data struct.
239 */
240 static void
241 r128DestroyScreen( __DRIscreenPrivate *sPriv )
242 {
243 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
244
245 if ( !r128Screen )
246 return;
247
248 if ( !r128Screen->IsPCI ) {
249 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
250 r128Screen->agpTextures.size );
251 }
252 drmUnmapBufs( r128Screen->buffers );
253 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
254
255 /* free all option information */
256 driDestroyOptionInfo (&r128Screen->optionCache);
257
258 FREE( r128Screen );
259 sPriv->private = NULL;
260 }
261
262
263 /* Create and initialize the Mesa and driver specific pixmap buffer
264 * data.
265 */
266 static GLboolean
267 r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
268 __DRIdrawablePrivate *driDrawPriv,
269 const __GLcontextModes *mesaVis,
270 GLboolean isPixmap )
271 {
272 r128ScreenPtr screen = (r128ScreenPtr) driScrnPriv->private;
273
274 if (isPixmap) {
275 return GL_FALSE; /* not implemented */
276 }
277 else {
278 const GLboolean swDepth = GL_FALSE;
279 const GLboolean swAlpha = GL_FALSE;
280 const GLboolean swAccum = mesaVis->accumRedBits > 0;
281 const GLboolean swStencil = mesaVis->stencilBits > 0 &&
282 mesaVis->depthBits != 24;
283 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
284
285 {
286 driRenderbuffer *frontRb
287 = driNewRenderbuffer(GL_RGBA,
288 NULL,
289 screen->cpp,
290 screen->frontOffset, screen->frontPitch,
291 driDrawPriv);
292 r128SetSpanFunctions(frontRb, mesaVis);
293 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
294 }
295
296 if (mesaVis->doubleBufferMode) {
297 driRenderbuffer *backRb
298 = driNewRenderbuffer(GL_RGBA,
299 NULL,
300 screen->cpp,
301 screen->backOffset, screen->backPitch,
302 driDrawPriv);
303 r128SetSpanFunctions(backRb, mesaVis);
304 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
305 }
306
307 if (mesaVis->depthBits == 16) {
308 driRenderbuffer *depthRb
309 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
310 NULL,
311 screen->cpp,
312 screen->depthOffset, screen->depthPitch,
313 driDrawPriv);
314 r128SetSpanFunctions(depthRb, mesaVis);
315 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
316 }
317 else if (mesaVis->depthBits == 24) {
318 driRenderbuffer *depthRb
319 = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
320 NULL,
321 screen->cpp,
322 screen->depthOffset, screen->depthPitch,
323 driDrawPriv);
324 r128SetSpanFunctions(depthRb, mesaVis);
325 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
326 }
327
328 if (mesaVis->stencilBits > 0 && !swStencil) {
329 driRenderbuffer *stencilRb
330 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
331 NULL,
332 screen->cpp,
333 screen->depthOffset, screen->depthPitch,
334 driDrawPriv);
335 r128SetSpanFunctions(stencilRb, mesaVis);
336 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
337 }
338
339 _mesa_add_soft_renderbuffers(fb,
340 GL_FALSE, /* color */
341 swDepth,
342 swStencil,
343 swAccum,
344 swAlpha,
345 GL_FALSE /* aux */);
346 driDrawPriv->driverPrivate = (void *) fb;
347
348 return (driDrawPriv->driverPrivate != NULL);
349 }
350 }
351
352
353 static void
354 r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
355 {
356 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
357 }
358
359
360 /* Copy the back color buffer to the front color buffer */
361 static void
362 r128SwapBuffers(__DRIdrawablePrivate *dPriv)
363 {
364 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
365 r128ContextPtr rmesa;
366 GLcontext *ctx;
367 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
368 ctx = rmesa->glCtx;
369 if (ctx->Visual.doubleBufferMode) {
370 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
371 if ( rmesa->doPageFlip ) {
372 r128PageFlip( dPriv );
373 }
374 else {
375 r128CopyBuffer( dPriv );
376 }
377 }
378 }
379 else {
380 /* XXX this shouldn't be an error but we can't handle it for now */
381 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
382 }
383 }
384
385
386 /* Initialize the driver specific screen private data.
387 */
388 static GLboolean
389 r128InitDriver( __DRIscreenPrivate *sPriv )
390 {
391 sPriv->private = (void *) r128CreateScreen( sPriv );
392
393 if ( !sPriv->private ) {
394 r128DestroyScreen( sPriv );
395 return GL_FALSE;
396 }
397
398 return GL_TRUE;
399 }
400
401 static const __DRIconfig **
402 r128FillInModes( __DRIscreenPrivate *psp,
403 unsigned pixel_bits, unsigned depth_bits,
404 unsigned stencil_bits, GLboolean have_back_buffer )
405 {
406 __DRIconfig **configs;
407 __GLcontextModes * m;
408 unsigned depth_buffer_factor;
409 unsigned back_buffer_factor;
410 GLenum fb_format;
411 GLenum fb_type;
412 int i;
413
414 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
415 * enough to add support. Basically, if a context is created with an
416 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
417 * will never be used.
418 */
419 static const GLenum back_buffer_modes[] = {
420 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
421 };
422
423 uint8_t depth_bits_array[2];
424 uint8_t stencil_bits_array[2];
425 uint8_t msaa_samples_array[1];
426
427 depth_bits_array[0] = depth_bits;
428 depth_bits_array[1] = depth_bits;
429
430 /* Just like with the accumulation buffer, always provide some modes
431 * with a stencil buffer. It will be a sw fallback, but some apps won't
432 * care about that.
433 */
434 stencil_bits_array[0] = 0;
435 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
436
437 msaa_samples_array[0] = 0;
438
439 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
440 back_buffer_factor = (have_back_buffer) ? 2 : 1;
441
442 if ( pixel_bits == 16 ) {
443 fb_format = GL_RGB;
444 fb_type = GL_UNSIGNED_SHORT_5_6_5;
445 }
446 else {
447 fb_format = GL_BGR;
448 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
449 }
450
451 configs = driCreateConfigs(fb_format, fb_type,
452 depth_bits_array, stencil_bits_array,
453 depth_buffer_factor, back_buffer_modes,
454 back_buffer_factor,
455 msaa_samples_array, 1);
456 if (configs == NULL) {
457 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
458 __LINE__);
459 return NULL;
460 }
461
462 /* Mark the visual as slow if there are "fake" stencil bits.
463 */
464 for (i = 0; configs[i]; i++) {
465 m = &configs[i]->modes;
466 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
467 m->visualRating = GLX_SLOW_CONFIG;
468 }
469 }
470
471 return (const __DRIconfig **) configs;
472 }
473
474
475 /**
476 * This is the driver specific part of the createNewScreen entry point.
477 *
478 * \todo maybe fold this into intelInitDriver
479 *
480 * \return the __GLcontextModes supported by this driver
481 */
482 static const __DRIconfig **
483 r128InitScreen(__DRIscreenPrivate *psp)
484 {
485 static const __DRIversion ddx_expected = { 4, 0, 0 };
486 static const __DRIversion dri_expected = { 4, 0, 0 };
487 static const __DRIversion drm_expected = { 2, 2, 0 };
488 R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
489
490 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
491 &psp->dri_version, & dri_expected,
492 &psp->ddx_version, & ddx_expected,
493 &psp->drm_version, & drm_expected ) )
494 return NULL;
495
496 /* Calling driInitExtensions here, with a NULL context pointer,
497 * does not actually enable the extensions. It just makes sure
498 * that all the dispatch offsets for all the extensions that
499 * *might* be enables are known. This is needed because the
500 * dispatch offsets need to be known when _mesa_context_create is
501 * called, but we can't enable the extensions until we have a
502 * context pointer.
503 *
504 * Hello chicken. Hello egg. How are you two today?
505 */
506 driInitExtensions( NULL, card_extensions, GL_FALSE );
507
508 if (!r128InitDriver(psp))
509 return NULL;
510
511 return r128FillInModes( psp,
512 dri_priv->bpp,
513 (dri_priv->bpp == 16) ? 16 : 24,
514 (dri_priv->bpp == 16) ? 0 : 8,
515 (dri_priv->backOffset != dri_priv->depthOffset) );
516 }
517
518 const struct __DriverAPIRec driDriverAPI = {
519 .InitScreen = r128InitScreen,
520 .DestroyScreen = r128DestroyScreen,
521 .CreateContext = r128CreateContext,
522 .DestroyContext = r128DestroyContext,
523 .CreateBuffer = r128CreateBuffer,
524 .DestroyBuffer = r128DestroyBuffer,
525 .SwapBuffers = r128SwapBuffers,
526 .MakeCurrent = r128MakeCurrent,
527 .UnbindContext = r128UnbindContext,
528 .GetSwapInfo = NULL,
529 .GetDrawableMSC = driDrawableGetMSC32,
530 .WaitForMSC = driWaitForMSC32,
531 .WaitForSBC = NULL,
532 .SwapBuffersMSC = NULL
533 };