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