2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 #include "tdfx_context.h"
48 #define TILE_WIDTH 128
49 #define TILE_HEIGHT 32
51 #define CMDFIFO_PAGES 64
55 calcBufferStride (int xres
, int tiled
, int cpp
)
60 /* Calculate tile width stuff */
61 strideInTiles
= (xres
+TILE_WIDTH
-1)/TILE_WIDTH
;
63 return strideInTiles
*cpp
*TILE_WIDTH
;
67 } /* calcBufferStride */
71 calcBufferHeightInTiles (int yres
)
73 int heightInTiles
; /* Height of buffer in tiles */
75 /* Calculate tile height stuff */
76 heightInTiles
= yres
>> 5;
78 if (yres
& (TILE_HEIGHT
- 1))
83 } /* calcBufferHeightInTiles */
87 calcBufferSize (int xres
, int yres
, int tiled
, int cpp
)
89 int stride
, height
, bufSize
;
92 stride
= calcBufferStride(xres
, tiled
, cpp
);
93 height
= TILE_HEIGHT
* calcBufferHeightInTiles(yres
);
99 bufSize
= stride
* height
;
102 } /* calcBufferSize */
105 static void allocateMemory (const DRIDriverContext
*ctx
, TDFXDRIPtr pTDFX
)
107 int memRemaining
, fifoSize
, screenSizeInTiles
;
110 int pixmapCacheLinesMin
;
111 int cursorOffset
, cursorSize
;
113 pTDFX
->stride
= calcBufferStride(pTDFX
->width
, !0, pTDFX
->cpp
);
115 /* enough to do DVD */
116 pixmapCacheLinesMin
= ((720*480*pTDFX
->cpp
) +
117 pTDFX
->stride
- 1)/pTDFX
->stride
;
119 if (pTDFX
->deviceID
> PCI_CHIP_VOODOO3
) {
120 if ((pixmapCacheLinesMin
+ pTDFX
->height
) > 4095)
121 pixmapCacheLinesMin
= 4095 - pTDFX
->height
;
123 if ((pixmapCacheLinesMin
+ pTDFX
->height
) > 2047)
124 pixmapCacheLinesMin
= 2047 - pTDFX
->height
;
128 screenSizeInTiles
=calcBufferSize(pTDFX
->width
, pTDFX
->height
,
132 /* cpp==3 needs to bump up to 4 */
133 screenSizeInTiles
=calcBufferSize(pTDFX
->width
, pTDFX
->height
,
139 * cursor, fifo, fb, tex, bb, db
142 fbSize
= (pTDFX
->height
+ pixmapCacheLinesMin
) * pTDFX
->stride
;
144 memRemaining
=(pTDFX
->mem
- 1) &~ 0xFFF;
145 /* Note that a page is 4096 bytes, and a */
146 /* tile is 32 x 128 = 4096 bytes. So, */
147 /* page and tile boundaries are the same */
148 /* Place the depth offset first, forcing */
149 /* it to be on an *odd* page boundary. */
150 pTDFX
->depthOffset
= (memRemaining
- screenSizeInTiles
) &~ 0xFFF;
151 if ((pTDFX
->depthOffset
& (0x1 << 12)) == 0) {
152 pTDFX
->depthOffset
-= (0x1 << 12);
154 /* Now, place the back buffer, forcing it */
155 /* to be on an *even* page boundary. */
156 pTDFX
->backOffset
= (pTDFX
->depthOffset
- screenSizeInTiles
) &~ 0xFFF;
157 if (pTDFX
->backOffset
& (0x1 << 12)) {
158 pTDFX
->backOffset
-= (0x1 << 12);
160 /* Give the cmd fifo at least */
161 /* CMDFIFO_PAGES pages, but no more than */
162 /* 64. NOTE: Don't go higher than 64, as */
163 /* there is suspect code in Glide3 ! */
164 fifoSize
= ((64 <= CMDFIFO_PAGES
) ? 64 : CMDFIFO_PAGES
) << 12;
166 /* We give 4096 bytes to the cursor */
167 cursorSize
= 0/*4096*/;
170 pTDFX
->fifoOffset
= cursorOffset
+ cursorSize
;
171 pTDFX
->fifoSize
= fifoSize
;
172 /* Now, place the front buffer, forcing */
173 /* it to be on a page boundary too, just */
175 pTDFX
->fbOffset
= pTDFX
->fifoOffset
+ pTDFX
->fifoSize
;
176 pTDFX
->textureOffset
= pTDFX
->fbOffset
+ fbSize
;
177 if (pTDFX
->depthOffset
<= pTDFX
->textureOffset
||
178 pTDFX
->backOffset
<= pTDFX
->textureOffset
) {
180 * pTDFX->textureSize < 0 means that the DRI is disabled. pTDFX->backOffset
181 * is used to calculate the maximum amount of memory available for
182 * 2D offscreen use. With DRI disabled, set this to the top of memory.
185 pTDFX
->textureSize
= -1;
186 pTDFX
->backOffset
= pTDFX
->mem
;
187 pTDFX
->depthOffset
= -1;
189 "Not enough video memory available for textures and depth buffer\n"
190 "\tand/or back buffer. Disabling DRI. To use DRI try lower\n"
191 "\tresolution modes and/or a smaller virtual screen size\n");
193 pTDFX
->textureSize
= pTDFX
->backOffset
- pTDFX
->textureOffset
;
198 static int createScreen (DRIDriverContext
*ctx
, TDFXDRIPtr pTDFX
)
203 int width_bytes
= (ctx
->shared
.virtualWidth
* ctx
->cpp
);
204 int maxy
= ctx
->shared
.fbSize
/ width_bytes
;
207 if (maxy
<= ctx
->shared
.virtualHeight
* 3) {
209 "Static buffer allocation failed -- "
210 "need at least %d kB video memory (have %d kB)\n",
211 (ctx
->shared
.virtualWidth
* ctx
->shared
.virtualHeight
*
212 ctx
->cpp
* 3 + 1023) / 1024,
213 ctx
->shared
.fbSize
/ 1024);
218 ctx
->shared
.SAREASize
= SAREA_MAX
;
219 pTDFX
->regsSize
= ctx
->MMIOSize
;
221 /* Note that drmOpen will try to load the kernel module, if needed. */
222 ctx
->drmFD
= drmOpen("tdfx", NULL
);
223 if (ctx
->drmFD
< 0) {
224 fprintf(stderr
, "[drm] drmOpen failed\n");
228 if ((err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
)) < 0) {
229 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
230 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
234 if (drmAddMap( ctx
->drmFD
,
236 ctx
->shared
.SAREASize
,
239 &ctx
->shared
.hSAREA
) < 0)
241 fprintf(stderr
, "[drm] drmAddMap failed\n");
244 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
245 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
247 if (drmMap( ctx
->drmFD
,
249 ctx
->shared
.SAREASize
,
250 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
252 fprintf(stderr
, "[drm] drmMap failed\n");
255 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
256 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
257 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
259 /* Need to AddMap the framebuffer and mmio regions here:
261 if (drmAddMap( ctx
->drmFD
,
262 (drm_handle_t
)ctx
->FBStart
,
270 &ctx
->shared
.hFrameBuffer
) < 0)
272 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
276 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
277 ctx
->shared
.hFrameBuffer
);
280 if (drmAddMap(ctx
->drmFD
,
286 fprintf(stderr
, "[drm] drmAddMap mmio failed\n");
290 "[drm] register handle = 0x%08lx\n", pTDFX
->regs
);
293 /* Create a 'server' context so we can grab the lock for
294 * initialization ioctls.
296 if ((err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
)) != 0) {
297 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
301 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
303 /* Initialize the kernel data structures */
305 /* Initialize kernel gart memory manager */
306 allocateMemory(ctx
, pTDFX
);
308 /* Initialize the SAREA private data structure */
311 /* Quick hack to clear the front & back buffers. Could also use
312 * the clear ioctl to do this, but would need to setup hw state
317 /* This is the struct passed to tdfx_dri.so for its initialization */
318 ctx
->driverClientMsg
= malloc(sizeof(TDFXDRIRec
));
319 ctx
->driverClientMsgSize
= sizeof(TDFXDRIRec
);
320 memcpy(ctx
->driverClientMsg
, pTDFX
, ctx
->driverClientMsgSize
);
321 pTDFX
= (TDFXDRIPtr
)ctx
->driverClientMsg
;
323 /* Don't release the lock now - let the VT switch handler do it. */
330 * \brief Validate the fbdev mode.
332 * \param ctx display handle.
334 * \return one on success, or zero on failure.
336 * Saves some registers and returns 1.
338 * \sa tdfxValidateMode().
340 static int tdfxValidateMode( const DRIDriverContext
*ctx
)
347 * \brief Examine mode returned by fbdev.
349 * \param ctx display handle.
351 * \return one on success, or zero on failure.
353 * Restores registers that fbdev has clobbered and returns 1.
355 * \sa tdfxValidateMode().
357 static int tdfxPostValidateMode( const DRIDriverContext
*ctx
)
364 * \brief Initialize the framebuffer device mode
366 * \param ctx display handle.
368 * \return one on success, or zero on failure.
370 * Before exiting clears the framebuffer memory accessing it directly.
372 static int tdfxInitFBDev( DRIDriverContext
*ctx
)
374 TDFXDRIPtr pTDFX
= calloc(1, sizeof(TDFXDRIRec
));
377 int dummy
= ctx
->shared
.virtualWidth
;
379 switch (ctx
->bpp
/ 8) {
380 case 1: dummy
= (ctx
->shared
.virtualWidth
+ 127) & ~127; break;
381 case 2: dummy
= (ctx
->shared
.virtualWidth
+ 31) & ~31; break;
383 case 4: dummy
= (ctx
->shared
.virtualWidth
+ 15) & ~15; break;
386 ctx
->shared
.virtualWidth
= dummy
;
389 ctx
->driverPrivate
= (void *)pTDFX
;
391 pTDFX
->deviceID
= ctx
->chipset
;
392 pTDFX
->width
= ctx
->shared
.virtualWidth
;
393 pTDFX
->height
= ctx
->shared
.virtualHeight
;
394 pTDFX
->cpp
= ctx
->cpp
;
395 pTDFX
->mem
= ctx
->FBSize
; /* ->shared.fbSize? mem probe? */
396 pTDFX
->sarea_priv_offset
= sizeof(drm_sarea_t
);
398 if (!createScreen(ctx
, pTDFX
))
406 * \brief The screen is being closed, so clean up any state and free any
407 * resources used by the DRI.
409 * \param ctx display handle.
411 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
414 static void tdfxHaltFBDev( DRIDriverContext
*ctx
)
416 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
417 drmClose(ctx
->drmFD
);
419 if (ctx
->driverPrivate
) {
420 free(ctx
->driverPrivate
);
421 ctx
->driverPrivate
= 0;
427 * \brief Shutdown the drawing engine.
429 * \param ctx display handle
431 * Turns off the 3D engine & restores the graphics card
432 * to a state that fbdev understands.
434 static int tdfxEngineShutdown( const DRIDriverContext
*ctx
)
436 fprintf(stderr
, "%s: not implemented\n", __FUNCTION__
);
442 * \brief Restore the drawing engine.
444 * \param ctx display handle
446 * Resets the graphics card and sets initial values for several registers of
447 * the card's drawing engine.
451 static int tdfxEngineRestore( const DRIDriverContext
*ctx
)
453 fprintf(stderr
, "%s: not implemented\n", __FUNCTION__
);
459 * \brief Exported driver interface for Mini GLX.
463 struct DRIDriverRec __driDriver
= {
465 tdfxPostValidateMode
,