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,