1 /* -*- mode: c; c-basic-offset: 3 -*-
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
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 (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
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 NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_screen.c,v 1.3 2002/02/22 21:45:03 dawes Exp $ */
30 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
33 * Gareth Hughes <gareth@valinux.com>
38 #include "tdfx_context.h"
39 #include "tdfx_lock.h"
41 #include "tdfx_tris.h"
45 char *prevLockFile
= 0;
51 /* | DEBUG_ALWAYS_SYNC */
52 /* | DEBUG_VERBOSE_API */
53 /* | DEBUG_VERBOSE_MSG */
54 /* | DEBUG_VERBOSE_LRU */
55 /* | DEBUG_VERBOSE_DRI */
56 /* | DEBUG_VERBOSE_IOCTL */
57 /* | DEBUG_VERBOSE_2D */
64 tdfxCreateScreen( __DRIscreenPrivate
*sPriv
)
66 tdfxScreenPrivate
*fxScreen
;
67 TDFXDRIPtr fxDRIPriv
= (TDFXDRIPtr
) sPriv
->pDevPriv
;
69 /* Allocate the private area */
70 fxScreen
= (tdfxScreenPrivate
*) CALLOC( sizeof(tdfxScreenPrivate
) );
74 fxScreen
->driScrnPriv
= sPriv
;
75 sPriv
->private = (void *) fxScreen
;
77 fxScreen
->regs
.handle
= fxDRIPriv
->regs
;
78 fxScreen
->regs
.size
= fxDRIPriv
->regsSize
;
79 fxScreen
->deviceID
= fxDRIPriv
->deviceID
;
80 fxScreen
->width
= fxDRIPriv
->width
;
81 fxScreen
->height
= fxDRIPriv
->height
;
82 fxScreen
->mem
= fxDRIPriv
->mem
;
83 fxScreen
->cpp
= fxDRIPriv
->cpp
;
84 fxScreen
->stride
= fxDRIPriv
->stride
;
85 fxScreen
->fifoOffset
= fxDRIPriv
->fifoOffset
;
86 fxScreen
->fifoSize
= fxDRIPriv
->fifoSize
;
87 fxScreen
->fbOffset
= fxDRIPriv
->fbOffset
;
88 fxScreen
->backOffset
= fxDRIPriv
->backOffset
;
89 fxScreen
->depthOffset
= fxDRIPriv
->depthOffset
;
90 fxScreen
->textureOffset
= fxDRIPriv
->textureOffset
;
91 fxScreen
->textureSize
= fxDRIPriv
->textureSize
;
92 fxScreen
->sarea_priv_offset
= fxDRIPriv
->sarea_priv_offset
;
94 if ( drmMap( sPriv
->fd
, fxScreen
->regs
.handle
,
95 fxScreen
->regs
.size
, &fxScreen
->regs
.map
) ) {
104 tdfxDestroyScreen( __DRIscreenPrivate
*sPriv
)
106 tdfxScreenPrivate
*fxScreen
= (tdfxScreenPrivate
*) sPriv
->private;
109 drmUnmap( fxScreen
->regs
.map
, fxScreen
->regs
.size
);
112 sPriv
->private = NULL
;
118 tdfxInitDriver( __DRIscreenPrivate
*sPriv
)
120 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
121 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)sPriv
);
124 if ( !tdfxCreateScreen( sPriv
) ) {
125 tdfxDestroyScreen( sPriv
);
134 tdfxCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
135 __DRIdrawablePrivate
*driDrawPriv
,
136 const __GLcontextModes
*mesaVis
,
140 return GL_FALSE
; /* not implemented */
143 driDrawPriv
->driverPrivate
= (void *)
144 _mesa_create_framebuffer( mesaVis
,
145 GL_FALSE
, /* software depth buffer? */
146 mesaVis
->stencilBits
> 0,
147 mesaVis
->accumRedBits
> 0,
148 GL_FALSE
/* software alpha channel? */ );
149 return (driDrawPriv
->driverPrivate
!= NULL
);
155 tdfxDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
157 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
162 tdfxSwapBuffers( __DRIdrawablePrivate
*driDrawPriv
)
165 GET_CURRENT_CONTEXT(ctx
);
166 tdfxContextPtr fxMesa
= 0;
167 GLframebuffer
*mesaBuffer
;
169 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
170 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)driDrawPriv
);
173 mesaBuffer
= (GLframebuffer
*) driDrawPriv
->driverPrivate
;
174 if ( !mesaBuffer
->Visual
.doubleBufferMode
)
175 return; /* can't swap a single-buffered window */
177 /* If the current context's drawable matches the given drawable
178 * we have to do a glFinish (per the GLX spec).
181 __DRIdrawablePrivate
*curDrawPriv
;
182 fxMesa
= TDFX_CONTEXT(ctx
);
183 curDrawPriv
= fxMesa
->driContext
->driDrawablePriv
;
185 if ( curDrawPriv
== driDrawPriv
) {
186 /* swapping window bound to current context, flush first */
187 _mesa_notifySwapBuffers( ctx
);
188 LOCK_HARDWARE( fxMesa
);
191 /* find the fxMesa context previously bound to the window */
192 fxMesa
= (tdfxContextPtr
) driDrawPriv
->driContextPriv
->driverPrivate
;
195 LOCK_HARDWARE( fxMesa
);
196 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
197 printf("SwapBuf SetState 1\n");
198 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
205 static int prevStalls
= 0;
207 stalls
= fxMesa
->Glide
.grFifoGetStalls();
209 fprintf( stderr
, "%s:\n", __FUNCTION__
);
210 if ( stalls
!= prevStalls
) {
211 fprintf( stderr
, " %d stalls occurred\n",
212 stalls
- prevStalls
);
215 if ( fxMesa
&& fxMesa
->texSwaps
) {
216 fprintf( stderr
, " %d texture swaps occurred\n",
218 fxMesa
->texSwaps
= 0;
223 if (fxMesa
->scissoredClipRects
) {
224 /* restore clip rects without scissor box */
225 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
226 driDrawPriv
->w
, driDrawPriv
->h
,
227 driDrawPriv
->numClipRects
,
228 driDrawPriv
->pClipRects
);
231 fxMesa
->Glide
.grDRIBufferSwap( fxMesa
->Glide
.SwapInterval
);
233 if (fxMesa
->scissoredClipRects
) {
234 /* restore clip rects WITH scissor box */
235 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
236 driDrawPriv
->w
, driDrawPriv
->h
,
237 fxMesa
->numClipRects
, fxMesa
->pClipRects
);
246 fxMesa
->Glide
.grGet(GR_PENDING_BUFFERSWAPS
, 4, &result
);
247 } while ( result
> fxMesa
->maxPendingSwapBuffers
);
251 fxMesa
->stats
.swapBuffer
++;
254 if (ctx
->DriverCtx
!= fxMesa
) {
255 fxMesa
= TDFX_CONTEXT(ctx
);
256 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
257 printf("SwapBuf SetState 2\n");
258 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
260 UNLOCK_HARDWARE( fxMesa
);
265 static const struct __DriverAPIRec tdfxAPI
= {
266 .InitDriver
= tdfxInitDriver
,
267 .DestroyScreen
= tdfxDestroyScreen
,
268 .CreateContext
= tdfxCreateContext
,
269 .DestroyContext
= tdfxDestroyContext
,
270 .CreateBuffer
= tdfxCreateBuffer
,
271 .DestroyBuffer
= tdfxDestroyBuffer
,
272 .SwapBuffers
= tdfxSwapBuffers
,
273 .MakeCurrent
= tdfxMakeCurrent
,
274 .UnbindContext
= tdfxUnbindContext
,
279 .SwapBuffersMSC
= NULL
282 #ifdef USE_NEW_INTERFACE
284 * new interface code, derived from radeon_screen.c
285 * XXX this may still be wrong
287 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
289 static __GLcontextModes
*tdfxFillInModes(unsigned pixel_bits
,
291 unsigned stencil_bits
,
292 GLboolean have_back_buffer
)
294 __GLcontextModes
*modes
;
297 unsigned vis
[2] = { GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
};
298 unsigned deep
= (depth_bits
> 17);
299 unsigned i
, db
, depth
, accum
, stencil
;
301 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
302 * enough to add support. Basically, if a context is created with an
303 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
304 * will never be used.
307 num_modes
= (depth_bits
== 16) ? 32 : 16;
309 modes
= (*create_context_modes
)(num_modes
, sizeof(__GLcontextModes
));
312 for (i
= 0; i
<= 1; i
++) {
313 for (db
= 0; db
<= 1; db
++) {
314 for (depth
= 0; depth
<= 1; depth
++) {
315 for (accum
= 0; accum
<= 1; accum
++) {
316 for (stencil
= 0; stencil
<= !deep
; stencil
++) {
317 if (deep
) stencil
= depth
;
318 m
->redBits
= deep
? 8 : 5;
319 m
->greenBits
= deep
? 8 : 6;
320 m
->blueBits
= deep
? 8 : 5;
321 m
->alphaBits
= deep
? 8 : 0;
322 m
->redMask
= deep
?0xFF000000 :0x0000F800;
323 m
->greenMask
= deep
?0x00FF0000 :0x000007E0;
324 m
->blueMask
= deep
?0x0000FF00 :0x0000001F;
325 m
->alphaMask
= deep
? 0x000000FF : 0;
326 m
->rgbBits
= m
->redBits
+ m
->greenBits
+
327 m
->blueBits
+ m
->alphaBits
;
328 m
->accumRedBits
= accum
? 16 : 0;
329 m
->accumGreenBits
= accum
? 16 : 0;
330 m
->accumBlueBits
= accum
? 16 : 0;
331 m
->accumAlphaBits
= accum
? 16 : 0;
332 m
->stencilBits
= stencil
? 8 : 0;
335 : (depth
? 0 : depth_bits
);
336 m
->visualType
= i
? GLX_TRUE_COLOR
338 m
->renderType
= GLX_RGBA_BIT
;
339 m
->drawableType
= GLX_WINDOW_BIT
;
340 m
->rgbMode
= GL_TRUE
;
341 m
->doubleBufferMode
= db
? GL_TRUE
: GL_FALSE
;
343 m
->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
344 m
->visualRating
= ((stencil
&& !deep
) || accum
)
348 if (deep
) stencil
= 0;
359 * This is the bootstrap function for the driver. libGL supplies all of the
360 * requisite information about the system, and the driver initializes itself.
361 * This routine also fills in the linked list pointed to by \c driver_modes
362 * with the \c __GLcontextModes that the driver can support for windows or
365 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
368 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
369 const __GLcontextModes
* modes
,
370 const __DRIversion
* ddx_version
,
371 const __DRIversion
* dri_version
,
372 const __DRIversion
* drm_version
,
373 const __DRIframebuffer
* frame_buffer
,
374 drmAddress pSAREA
, int fd
,
375 int internal_api_version
,
376 __GLcontextModes
** driver_modes
)
378 __DRIscreenPrivate
*psp
;
379 static const __DRIversion ddx_expected
= { 1, 0, 0 };
380 static const __DRIversion dri_expected
= { 4, 0, 0 };
381 static const __DRIversion drm_expected
= { 1, 0, 0 };
383 if ( ! driCheckDriDdxDrmVersions2( "tdfx",
384 dri_version
, & dri_expected
,
385 ddx_version
, & ddx_expected
,
386 drm_version
, & drm_expected
) ) {
390 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
391 ddx_version
, dri_version
, drm_version
,
392 frame_buffer
, pSAREA
, fd
,
393 internal_api_version
, &tdfxAPI
);
395 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
396 glXGetProcAddress((const GLubyte
*)"__glXCreateContextModes");
398 if (create_context_modes
!= NULL
) {
399 /* divined from tdfx_dri.c, sketchy */
400 TDFXDRIPtr dri_priv
= (TDFXDRIPtr
) psp
->pDevPriv
;
401 int bpp
= (dri_priv
->cpp
> 2) ? 24 : 16;
403 /* XXX i wish it was like this */
404 /* bpp = dri_priv->bpp */
406 *driver_modes
= tdfxFillInModes(bpp
, (bpp
== 16) ? 16 : 24,
408 (dri_priv
->backOffset
!=dri_priv
->depthOffset
));
413 #endif /* USE_NEW_INTERFACE */
417 * This is the bootstrap function for the driver.
418 * The __driCreateScreen name is the symbol that libGL.so fetches.
419 * Return: pointer to a __DRIscreenPrivate.
421 #if !defined(DRI_NEW_INTERFACE_ONLY)
423 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
424 int numConfigs
, __GLXvisualConfig
*config
)
426 __DRIscreenPrivate
*psp
;
427 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &tdfxAPI
);
431 void *__driCreateScreen(struct DRIDriverRec
*driver
,
432 struct DRIDriverContextRec
*driverContext
)
434 __DRIscreenPrivate
*psp
;
435 psp
= __driUtilCreateScreen(driver
, driverContext
, &tdfxAPI
);
439 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */