dri/swrast: Remove unnecessary header.
[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
41 #include "main/context.h"
42 #include "main/imports.h"
43 #include "main/framebuffer.h"
44 #include "main/renderbuffer.h"
45
46 #include "utils.h"
47 #include "vblank.h"
48
49 #include "GL/internal/dri_interface.h"
50
51 /* R128 configuration
52 */
53 #include "xmlpool.h"
54
55 PUBLIC const char __driConfigOptions[] =
56 DRI_CONF_BEGIN
57 DRI_CONF_SECTION_PERFORMANCE
58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
59 DRI_CONF_SECTION_END
60 DRI_CONF_SECTION_QUALITY
61 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
62 DRI_CONF_SECTION_END
63 DRI_CONF_SECTION_DEBUG
64 DRI_CONF_NO_RAST(false)
65 #if ENABLE_PERF_BOXES
66 DRI_CONF_PERFORMANCE_BOXES(false)
67 #endif
68 DRI_CONF_SECTION_END
69 DRI_CONF_END;
70 #if ENABLE_PERF_BOXES
71 static const GLuint __driNConfigOptions = 4;
72 #else
73 static const GLuint __driNConfigOptions = 3;
74 #endif
75
76 #if 1
77 /* Including xf86PciInfo.h introduces a bunch of errors...
78 */
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
87 #endif
88
89
90 /* Create the device specific screen private data struct.
91 */
92 static r128ScreenPtr
93 r128CreateScreen( __DRIscreen *sPriv )
94 {
95 r128ScreenPtr r128Screen;
96 R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
97 int i;
98
99 if (sPriv->devPrivSize != sizeof(R128DRIRec)) {
100 fprintf(stderr,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
101 return GL_FALSE;
102 }
103
104 /* Allocate the private area */
105 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
106 if ( !r128Screen ) return NULL;
107
108 /* parse information in __driConfigOptions */
109 driParseOptionInfo (&r128Screen->optionCache,
110 __driConfigOptions, __driNConfigOptions);
111
112 /* This is first since which regions we map depends on whether or
113 * not we are using a PCI card.
114 */
115 r128Screen->IsPCI = r128DRIPriv->IsPCI;
116 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
117
118 if (sPriv->drm_version.minor >= 3) {
119 drm_r128_getparam_t gp;
120 int ret;
121
122 gp.param = R128_PARAM_IRQ_NR;
123 gp.value = &r128Screen->irq;
124
125 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
126 &gp, sizeof(gp));
127 if (ret) {
128 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
129 FREE( r128Screen );
130 return NULL;
131 }
132 }
133
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 ) ) {
140 FREE( r128Screen );
141 return NULL;
142 }
143
144 r128Screen->buffers = drmMapBufs( sPriv->fd );
145 if ( !r128Screen->buffers ) {
146 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
147 FREE( r128Screen );
148 return NULL;
149 }
150
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 );
160 FREE( r128Screen );
161 return NULL;
162 }
163 }
164
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;
171 break;
172 case PCI_CHIP_RAGE128PF:
173 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
174 break;
175 case PCI_CHIP_RAGE128LE:
176 case PCI_CHIP_RAGE128LF:
177 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
178 break;
179 default:
180 r128Screen->chipset = R128_CARD_TYPE_R128;
181 break;
182 }
183
184 r128Screen->cpp = r128DRIPriv->bpp / 8;
185 r128Screen->AGPMode = r128DRIPriv->AGPMode;
186
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;
194
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;
201 } else {
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;
205 }
206
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;
212 } else {
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;
219 }
220
221 r128Screen->driScreen = sPriv;
222
223 i = 0;
224 r128Screen->extensions[i++] = &driFrameTrackingExtension.base;
225 if ( r128Screen->irq != 0 ) {
226 r128Screen->extensions[i++] = &driSwapControlExtension.base;
227 r128Screen->extensions[i++] = &driMediaStreamCounterExtension.base;
228 }
229 r128Screen->extensions[i++] = NULL;
230 sPriv->extensions = r128Screen->extensions;
231
232 return r128Screen;
233 }
234
235 /* Destroy the device specific screen private data struct.
236 */
237 static void
238 r128DestroyScreen( __DRIscreen *sPriv )
239 {
240 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
241
242 if ( !r128Screen )
243 return;
244
245 if ( !r128Screen->IsPCI ) {
246 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
247 r128Screen->agpTextures.size );
248 }
249 drmUnmapBufs( r128Screen->buffers );
250 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
251
252 /* free all option information */
253 driDestroyOptionInfo (&r128Screen->optionCache);
254
255 FREE( r128Screen );
256 sPriv->private = NULL;
257 }
258
259
260 /* Create and initialize the Mesa and driver specific pixmap buffer
261 * data.
262 */
263 static GLboolean
264 r128CreateBuffer( __DRIscreen *driScrnPriv,
265 __DRIdrawable *driDrawPriv,
266 const __GLcontextModes *mesaVis,
267 GLboolean isPixmap )
268 {
269 r128ScreenPtr screen = (r128ScreenPtr) driScrnPriv->private;
270
271 if (isPixmap) {
272 return GL_FALSE; /* not implemented */
273 }
274 else {
275 const GLboolean swDepth = GL_FALSE;
276 const GLboolean swAlpha = GL_FALSE;
277 const GLboolean swAccum = mesaVis->accumRedBits > 0;
278 const GLboolean swStencil = mesaVis->stencilBits > 0 &&
279 mesaVis->depthBits != 24;
280 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
281
282 {
283 driRenderbuffer *frontRb
284 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
285 NULL,
286 screen->cpp,
287 screen->frontOffset, screen->frontPitch,
288 driDrawPriv);
289 r128SetSpanFunctions(frontRb, mesaVis);
290 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
291 }
292
293 if (mesaVis->doubleBufferMode) {
294 driRenderbuffer *backRb
295 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
296 NULL,
297 screen->cpp,
298 screen->backOffset, screen->backPitch,
299 driDrawPriv);
300 r128SetSpanFunctions(backRb, mesaVis);
301 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
302 }
303
304 if (mesaVis->depthBits == 16) {
305 driRenderbuffer *depthRb
306 = driNewRenderbuffer(MESA_FORMAT_Z16,
307 NULL,
308 screen->cpp,
309 screen->depthOffset, screen->depthPitch,
310 driDrawPriv);
311 r128SetSpanFunctions(depthRb, mesaVis);
312 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
313 }
314 else if (mesaVis->depthBits == 24) {
315 driRenderbuffer *depthRb
316 = driNewRenderbuffer(MESA_FORMAT_S8_Z24,
317 NULL,
318 screen->cpp,
319 screen->depthOffset, screen->depthPitch,
320 driDrawPriv);
321 r128SetSpanFunctions(depthRb, mesaVis);
322 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
323 }
324
325 if (mesaVis->stencilBits > 0 && !swStencil) {
326 driRenderbuffer *stencilRb
327 = driNewRenderbuffer(MESA_FORMAT_S8,
328 NULL,
329 screen->cpp,
330 screen->depthOffset, screen->depthPitch,
331 driDrawPriv);
332 r128SetSpanFunctions(stencilRb, mesaVis);
333 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
334 }
335
336 _mesa_add_soft_renderbuffers(fb,
337 GL_FALSE, /* color */
338 swDepth,
339 swStencil,
340 swAccum,
341 swAlpha,
342 GL_FALSE /* aux */);
343 driDrawPriv->driverPrivate = (void *) fb;
344
345 return (driDrawPriv->driverPrivate != NULL);
346 }
347 }
348
349
350 static void
351 r128DestroyBuffer(__DRIdrawable *driDrawPriv)
352 {
353 _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
354 }
355
356
357 /* Copy the back color buffer to the front color buffer */
358 static void
359 r128SwapBuffers(__DRIdrawable *dPriv)
360 {
361 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
362 r128ContextPtr rmesa;
363 GLcontext *ctx;
364 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
365 ctx = rmesa->glCtx;
366 if (ctx->Visual.doubleBufferMode) {
367 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
368 if ( rmesa->doPageFlip ) {
369 r128PageFlip( dPriv );
370 }
371 else {
372 r128CopyBuffer( dPriv );
373 }
374 }
375 }
376 else {
377 /* XXX this shouldn't be an error but we can't handle it for now */
378 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
379 }
380 }
381
382
383 /* Initialize the driver specific screen private data.
384 */
385 static GLboolean
386 r128InitDriver( __DRIscreen *sPriv )
387 {
388 sPriv->private = (void *) r128CreateScreen( sPriv );
389
390 if ( !sPriv->private ) {
391 r128DestroyScreen( sPriv );
392 return GL_FALSE;
393 }
394
395 return GL_TRUE;
396 }
397
398 static const __DRIconfig **
399 r128FillInModes( __DRIscreen *psp,
400 unsigned pixel_bits, unsigned depth_bits,
401 unsigned stencil_bits, GLboolean have_back_buffer )
402 {
403 __DRIconfig **configs;
404 __GLcontextModes * m;
405 unsigned depth_buffer_factor;
406 unsigned back_buffer_factor;
407 GLenum fb_format;
408 GLenum fb_type;
409 int i;
410
411 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
412 * enough to add support. Basically, if a context is created with an
413 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
414 * will never be used.
415 */
416 static const GLenum back_buffer_modes[] = {
417 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
418 };
419
420 uint8_t depth_bits_array[2];
421 uint8_t stencil_bits_array[2];
422 uint8_t msaa_samples_array[1];
423
424 depth_bits_array[0] = depth_bits;
425 depth_bits_array[1] = depth_bits;
426
427 /* Just like with the accumulation buffer, always provide some modes
428 * with a stencil buffer. It will be a sw fallback, but some apps won't
429 * care about that.
430 */
431 stencil_bits_array[0] = 0;
432 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
433
434 msaa_samples_array[0] = 0;
435
436 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
437 back_buffer_factor = (have_back_buffer) ? 2 : 1;
438
439 if ( pixel_bits == 16 ) {
440 fb_format = GL_RGB;
441 fb_type = GL_UNSIGNED_SHORT_5_6_5;
442 }
443 else {
444 fb_format = GL_BGR;
445 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
446 }
447
448 configs = driCreateConfigs(fb_format, fb_type,
449 depth_bits_array, stencil_bits_array,
450 depth_buffer_factor, back_buffer_modes,
451 back_buffer_factor,
452 msaa_samples_array, 1, GL_TRUE);
453 if (configs == NULL) {
454 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
455 __LINE__);
456 return NULL;
457 }
458
459 /* Mark the visual as slow if there are "fake" stencil bits.
460 */
461 for (i = 0; configs[i]; i++) {
462 m = &configs[i]->modes;
463 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
464 m->visualRating = GLX_SLOW_CONFIG;
465 }
466 }
467
468 return (const __DRIconfig **) configs;
469 }
470
471
472 /**
473 * This is the driver specific part of the createNewScreen entry point.
474 *
475 * \todo maybe fold this into intelInitDriver
476 *
477 * \return the __GLcontextModes supported by this driver
478 */
479 static const __DRIconfig **
480 r128InitScreen(__DRIscreen *psp)
481 {
482 static const __DRIversion ddx_expected = { 4, 0, 0 };
483 static const __DRIversion dri_expected = { 4, 0, 0 };
484 static const __DRIversion drm_expected = { 2, 2, 0 };
485 R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
486
487 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
488 &psp->dri_version, & dri_expected,
489 &psp->ddx_version, & ddx_expected,
490 &psp->drm_version, & drm_expected ) )
491 return NULL;
492
493 if (!r128InitDriver(psp))
494 return NULL;
495
496 return r128FillInModes( psp,
497 dri_priv->bpp,
498 (dri_priv->bpp == 16) ? 16 : 24,
499 (dri_priv->bpp == 16) ? 0 : 8,
500 (dri_priv->backOffset != dri_priv->depthOffset) );
501 }
502
503 const struct __DriverAPIRec driDriverAPI = {
504 .InitScreen = r128InitScreen,
505 .DestroyScreen = r128DestroyScreen,
506 .CreateContext = r128CreateContext,
507 .DestroyContext = r128DestroyContext,
508 .CreateBuffer = r128CreateBuffer,
509 .DestroyBuffer = r128DestroyBuffer,
510 .SwapBuffers = r128SwapBuffers,
511 .MakeCurrent = r128MakeCurrent,
512 .UnbindContext = r128UnbindContext,
513 .GetSwapInfo = NULL,
514 .GetDrawableMSC = driDrawableGetMSC32,
515 .WaitForMSC = driWaitForMSC32,
516 .WaitForSBC = NULL,
517 .SwapBuffersMSC = NULL
518 };
519
520 /* This is the table of extensions that the loader will dlsym() for. */
521 PUBLIC const __DRIextension *__driDriverExtensions[] = {
522 &driCoreExtension.base,
523 &driLegacyExtension.base,
524 NULL
525 };