patch to import Jon Smirl's work from Bitkeeper
[mesa.git] / src / mesa / drivers / dri / r128 / r128_screen.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v 1.8 2002/12/16 16:18:53 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 *
34 */
35
36 #include "r128_dri.h"
37
38 #include "r128_context.h"
39 #include "r128_ioctl.h"
40 #include "r128_tris.h"
41 #include "r128_vb.h"
42
43 #include "context.h"
44 #include "imports.h"
45
46 #include "utils.h"
47 #include "vblank.h"
48
49 #ifndef _SOLO
50 #include "glxextensions.h"
51 #endif
52
53 #if 1
54 /* Including xf86PciInfo.h introduces a bunch of errors...
55 */
56 #define PCI_CHIP_RAGE128LE 0x4C45
57 #define PCI_CHIP_RAGE128LF 0x4C46
58 #define PCI_CHIP_RAGE128PD 0x5044
59 #define PCI_CHIP_RAGE128PF 0x5046
60 #define PCI_CHIP_RAGE128PR 0x5052
61 #define PCI_CHIP_RAGE128RE 0x5245
62 #define PCI_CHIP_RAGE128RF 0x5246
63 #define PCI_CHIP_RAGE128RK 0x524B
64 #define PCI_CHIP_RAGE128RL 0x524C
65 #endif
66
67
68 /* Create the device specific screen private data struct.
69 */
70 static r128ScreenPtr
71 r128CreateScreen( __DRIscreenPrivate *sPriv )
72 {
73 r128ScreenPtr r128Screen;
74 R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
75
76 if ( ! driCheckDriDdxDrmVersions( sPriv, "Rage128", 4, 0, 4, 0, 2, 2 ) )
77 return NULL;
78
79 /* Allocate the private area */
80 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
81 if ( !r128Screen ) return NULL;
82
83 /* This is first since which regions we map depends on whether or
84 * not we are using a PCI card.
85 */
86 r128Screen->IsPCI = r128DRIPriv->IsPCI;
87 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
88
89 if (sPriv->drmMinor >= 3) {
90 drmR128GetParam gp;
91 int ret;
92
93 gp.param = R128_PARAM_IRQ_NR;
94 gp.value = &r128Screen->irq;
95
96 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
97 &gp, sizeof(gp));
98 if (ret) {
99 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
100 FREE( r128Screen );
101 return NULL;
102 }
103 }
104
105 r128Screen->mmio.handle = r128DRIPriv->registerHandle;
106 r128Screen->mmio.size = r128DRIPriv->registerSize;
107 if ( drmMap( sPriv->fd,
108 r128Screen->mmio.handle,
109 r128Screen->mmio.size,
110 (drmAddressPtr)&r128Screen->mmio.map ) ) {
111 FREE( r128Screen );
112 return NULL;
113 }
114
115 r128Screen->buffers = drmMapBufs( sPriv->fd );
116 if ( !r128Screen->buffers ) {
117 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
118 FREE( r128Screen );
119 return NULL;
120 }
121
122 if ( !r128Screen->IsPCI ) {
123 r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
124 r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
125 if ( drmMap( sPriv->fd,
126 r128Screen->agpTextures.handle,
127 r128Screen->agpTextures.size,
128 (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
129 drmUnmapBufs( r128Screen->buffers );
130 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
131 FREE( r128Screen );
132 return NULL;
133 }
134 }
135
136 switch ( r128DRIPriv->deviceID ) {
137 case PCI_CHIP_RAGE128RE:
138 case PCI_CHIP_RAGE128RF:
139 case PCI_CHIP_RAGE128RK:
140 case PCI_CHIP_RAGE128RL:
141 r128Screen->chipset = R128_CARD_TYPE_R128;
142 break;
143 case PCI_CHIP_RAGE128PD:
144 case PCI_CHIP_RAGE128PF:
145 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
146 break;
147 case PCI_CHIP_RAGE128LE:
148 case PCI_CHIP_RAGE128LF:
149 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
150 break;
151 default:
152 r128Screen->chipset = R128_CARD_TYPE_R128;
153 break;
154 }
155
156 r128Screen->cpp = r128DRIPriv->bpp / 8;
157 r128Screen->AGPMode = r128DRIPriv->AGPMode;
158
159 r128Screen->frontOffset = r128DRIPriv->frontOffset;
160 r128Screen->frontPitch = r128DRIPriv->frontPitch;
161 r128Screen->backOffset = r128DRIPriv->backOffset;
162 r128Screen->backPitch = r128DRIPriv->backPitch;
163 r128Screen->depthOffset = r128DRIPriv->depthOffset;
164 r128Screen->depthPitch = r128DRIPriv->depthPitch;
165 r128Screen->spanOffset = r128DRIPriv->spanOffset;
166
167 r128Screen->texOffset[R128_CARD_HEAP] = r128DRIPriv->textureOffset;
168 r128Screen->texSize[R128_CARD_HEAP] = r128DRIPriv->textureSize;
169 r128Screen->logTexGranularity[R128_CARD_HEAP] = r128DRIPriv->log2TexGran;
170
171 if ( r128Screen->IsPCI ) {
172 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
173 r128Screen->texOffset[R128_AGP_HEAP] = 0;
174 r128Screen->texSize[R128_AGP_HEAP] = 0;
175 r128Screen->logTexGranularity[R128_AGP_HEAP] = 0;
176 } else {
177 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
178 r128Screen->texOffset[R128_AGP_HEAP] =
179 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
180 r128Screen->texSize[R128_AGP_HEAP] = r128DRIPriv->agpTexMapSize;
181 r128Screen->logTexGranularity[R128_AGP_HEAP] =
182 r128DRIPriv->log2AGPTexGran;
183 }
184
185 r128Screen->driScreen = sPriv;
186
187 return r128Screen;
188 }
189
190 /* Destroy the device specific screen private data struct.
191 */
192 static void
193 r128DestroyScreen( __DRIscreenPrivate *sPriv )
194 {
195 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
196
197 if ( !r128Screen )
198 return;
199
200 if ( !r128Screen->IsPCI ) {
201 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
202 r128Screen->agpTextures.size );
203 }
204 drmUnmapBufs( r128Screen->buffers );
205 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
206
207 FREE( r128Screen );
208 sPriv->private = NULL;
209 }
210
211
212 /* Initialize the fullscreen mode.
213 */
214 static GLboolean
215 r128OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
216 {
217 return GL_TRUE;
218 }
219
220
221 /* Create and initialize the Mesa and driver specific pixmap buffer
222 * data.
223 */
224 static GLboolean
225 r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
226 __DRIdrawablePrivate *driDrawPriv,
227 const __GLcontextModes *mesaVis,
228 GLboolean isPixmap )
229 {
230 if (isPixmap) {
231 return GL_FALSE; /* not implemented */
232 }
233 else {
234 driDrawPriv->driverPrivate = (void *)
235 _mesa_create_framebuffer( mesaVis,
236 GL_FALSE, /* software depth buffer? */
237 mesaVis->stencilBits > 0,
238 mesaVis->accumRedBits > 0,
239 mesaVis->alphaBits > 0 );
240 return (driDrawPriv->driverPrivate != NULL);
241 }
242 }
243
244
245 static void
246 r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
247 {
248 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
249 }
250
251
252 /* Copy the back color buffer to the front color buffer */
253 static void
254 r128SwapBuffers(__DRIdrawablePrivate *dPriv)
255 {
256 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
257 r128ContextPtr rmesa;
258 GLcontext *ctx;
259 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
260 ctx = rmesa->glCtx;
261 if (ctx->Visual.doubleBufferMode) {
262 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
263 if ( rmesa->doPageFlip ) {
264 r128PageFlip( dPriv );
265 }
266 else {
267 r128CopyBuffer( dPriv );
268 }
269 }
270 }
271 else {
272 /* XXX this shouldn't be an error but we can't handle it for now */
273 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
274 }
275 }
276
277
278 /* Initialize the driver specific screen private data.
279 */
280 static GLboolean
281 r128InitDriver( __DRIscreenPrivate *sPriv )
282 {
283 sPriv->private = (void *) r128CreateScreen( sPriv );
284
285 if ( !sPriv->private ) {
286 r128DestroyScreen( sPriv );
287 return GL_FALSE;
288 }
289
290 return GL_TRUE;
291 }
292
293
294 #ifndef _SOLO
295 /* This function is called by libGL.so as soon as libGL.so is loaded.
296 * This is where we register new extension functions with the dispatcher.
297 */
298 void __driRegisterExtensions( void )
299 {
300 PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
301
302 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
303 glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
304 glXGetProcAddress( "__glXEnableExtension" );
305
306 if ( glx_enable_extension != NULL ) {
307 glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
308 glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
309 glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
310 }
311 }
312 }
313 #endif
314
315 static struct __DriverAPIRec r128API = {
316 .InitDriver = r128InitDriver,
317 .DestroyScreen = r128DestroyScreen,
318 .CreateContext = r128CreateContext,
319 .DestroyContext = r128DestroyContext,
320 .CreateBuffer = r128CreateBuffer,
321 .DestroyBuffer = r128DestroyBuffer,
322 .SwapBuffers = r128SwapBuffers,
323 .MakeCurrent = r128MakeCurrent,
324 .UnbindContext = r128UnbindContext,
325 .OpenFullScreen = r128OpenCloseFullScreen,
326 .CloseFullScreen = r128OpenCloseFullScreen,
327 .GetSwapInfo = NULL,
328 .GetMSC = driGetMSC32,
329 .WaitForMSC = driWaitForMSC32,
330 .WaitForSBC = NULL,
331 .SwapBuffersMSC = NULL
332
333 };
334
335
336 /*
337 * This is the bootstrap function for the driver.
338 * The __driCreateScreen name is the symbol that libGL.so fetches.
339 * Return: pointer to a __DRIscreenPrivate.
340 */
341 #ifndef _SOLO
342 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
343 int numConfigs, __GLXvisualConfig *config)
344 {
345 __DRIscreenPrivate *psp;
346 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r128API);
347 return (void *) psp;
348 }
349 #else
350 void *__driCreateScreen(struct DRIDriverRec *driver,
351 struct DRIDriverContextRec *driverContext)
352 {
353 __DRIscreenPrivate *psp;
354 psp = __driUtilCreateScreen(driver, driverContext, &r128API);
355 return (void *) psp;
356 }
357 #endif