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_span.h"
42 #include "tdfx_tris.h"
44 #include "framebuffer.h"
45 #include "renderbuffer.h"
51 char *prevLockFile
= 0;
59 PUBLIC
const char __driConfigOptions
[] =
61 DRI_CONF_SECTION_DEBUG
62 DRI_CONF_NO_RAST(false)
66 static const GLuint __driNConfigOptions
= 1;
68 extern const struct dri_extension card_extensions
[];
69 extern const struct dri_extension napalm_extensions
[];
72 tdfxCreateScreen( __DRIscreenPrivate
*sPriv
)
74 tdfxScreenPrivate
*fxScreen
;
75 TDFXDRIPtr fxDRIPriv
= (TDFXDRIPtr
) sPriv
->pDevPriv
;
76 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
77 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->getProcAddress("glxEnableExtension"));
78 void *const psc
= sPriv
->psc
->screenConfigs
;
80 if (sPriv
->devPrivSize
!= sizeof(TDFXDRIRec
)) {
81 fprintf(stderr
,"\nERROR! sizeof(TDFXDRIRec) does not match passed size from device driver\n");
85 /* Allocate the private area */
86 fxScreen
= (tdfxScreenPrivate
*) CALLOC( sizeof(tdfxScreenPrivate
) );
90 /* parse information in __driConfigOptions */
91 driParseOptionInfo (&fxScreen
->optionCache
,
92 __driConfigOptions
, __driNConfigOptions
);
94 fxScreen
->driScrnPriv
= sPriv
;
95 sPriv
->private = (void *) fxScreen
;
97 fxScreen
->regs
.handle
= fxDRIPriv
->regs
;
98 fxScreen
->regs
.size
= fxDRIPriv
->regsSize
;
99 fxScreen
->deviceID
= fxDRIPriv
->deviceID
;
100 fxScreen
->width
= fxDRIPriv
->width
;
101 fxScreen
->height
= fxDRIPriv
->height
;
102 fxScreen
->mem
= fxDRIPriv
->mem
;
103 fxScreen
->cpp
= fxDRIPriv
->cpp
;
104 fxScreen
->stride
= fxDRIPriv
->stride
;
105 fxScreen
->fifoOffset
= fxDRIPriv
->fifoOffset
;
106 fxScreen
->fifoSize
= fxDRIPriv
->fifoSize
;
107 fxScreen
->fbOffset
= fxDRIPriv
->fbOffset
;
108 fxScreen
->backOffset
= fxDRIPriv
->backOffset
;
109 fxScreen
->depthOffset
= fxDRIPriv
->depthOffset
;
110 fxScreen
->textureOffset
= fxDRIPriv
->textureOffset
;
111 fxScreen
->textureSize
= fxDRIPriv
->textureSize
;
112 fxScreen
->sarea_priv_offset
= fxDRIPriv
->sarea_priv_offset
;
114 if ( drmMap( sPriv
->fd
, fxScreen
->regs
.handle
,
115 fxScreen
->regs
.size
, &fxScreen
->regs
.map
) ) {
119 if (glx_enable_extension
!= NULL
) {
120 (*glx_enable_extension
)(psc
, "GLX_SGI_make_current_read");
128 tdfxDestroyScreen( __DRIscreenPrivate
*sPriv
)
130 tdfxScreenPrivate
*fxScreen
= (tdfxScreenPrivate
*) sPriv
->private;
135 drmUnmap( fxScreen
->regs
.map
, fxScreen
->regs
.size
);
137 /* free all option information */
138 driDestroyOptionInfo (&fxScreen
->optionCache
);
141 sPriv
->private = NULL
;
146 tdfxInitDriver( __DRIscreenPrivate
*sPriv
)
148 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
149 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)sPriv
);
152 if ( !tdfxCreateScreen( sPriv
) ) {
153 tdfxDestroyScreen( sPriv
);
162 tdfxCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
163 __DRIdrawablePrivate
*driDrawPriv
,
164 const __GLcontextModes
*mesaVis
,
167 tdfxScreenPrivate
*screen
= (tdfxScreenPrivate
*) driScrnPriv
->private;
170 return GL_FALSE
; /* not implemented */
173 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
176 driRenderbuffer
*frontRb
177 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
178 screen
->fbOffset
, screen
->width
, driDrawPriv
);
179 tdfxSetSpanFunctions(frontRb
, mesaVis
);
180 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
183 if (mesaVis
->doubleBufferMode
) {
184 driRenderbuffer
*backRb
185 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
186 screen
->backOffset
, screen
->width
,
188 tdfxSetSpanFunctions(backRb
, mesaVis
);
189 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
190 backRb
->backBuffer
= GL_TRUE
;
193 if (mesaVis
->depthBits
== 16) {
194 driRenderbuffer
*depthRb
195 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, NULL
, screen
->cpp
,
196 screen
->depthOffset
, screen
->width
,
198 tdfxSetSpanFunctions(depthRb
, mesaVis
);
199 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
201 else if (mesaVis
->depthBits
== 24) {
202 driRenderbuffer
*depthRb
203 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, NULL
, screen
->cpp
,
204 screen
->depthOffset
, screen
->width
,
206 tdfxSetSpanFunctions(depthRb
, mesaVis
);
207 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
210 if (mesaVis
->stencilBits
> 0) {
211 driRenderbuffer
*stencilRb
212 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
, NULL
, screen
->cpp
,
213 screen
->depthOffset
, screen
->width
,
215 tdfxSetSpanFunctions(stencilRb
, mesaVis
);
216 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
219 _mesa_add_soft_renderbuffers(fb
,
220 GL_FALSE
, /* color */
221 GL_FALSE
, /* depth */
222 GL_FALSE
, /*swStencil,*/
223 mesaVis
->accumRedBits
> 0,
224 GL_FALSE
, /* alpha */
226 driDrawPriv
->driverPrivate
= (void *) fb
;
228 return (driDrawPriv
->driverPrivate
!= NULL
);
234 tdfxDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
236 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
241 tdfxSwapBuffers( __DRIdrawablePrivate
*driDrawPriv
)
244 GET_CURRENT_CONTEXT(ctx
);
245 tdfxContextPtr fxMesa
= 0;
246 GLframebuffer
*mesaBuffer
;
248 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
249 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)driDrawPriv
);
252 mesaBuffer
= (GLframebuffer
*) driDrawPriv
->driverPrivate
;
253 if ( !mesaBuffer
->Visual
.doubleBufferMode
)
254 return; /* can't swap a single-buffered window */
256 /* If the current context's drawable matches the given drawable
257 * we have to do a glFinish (per the GLX spec).
260 __DRIdrawablePrivate
*curDrawPriv
;
261 fxMesa
= TDFX_CONTEXT(ctx
);
262 curDrawPriv
= fxMesa
->driContext
->driDrawablePriv
;
264 if ( curDrawPriv
== driDrawPriv
) {
265 /* swapping window bound to current context, flush first */
266 _mesa_notifySwapBuffers( ctx
);
267 LOCK_HARDWARE( fxMesa
);
270 /* find the fxMesa context previously bound to the window */
271 fxMesa
= (tdfxContextPtr
) driDrawPriv
->driContextPriv
->driverPrivate
;
274 LOCK_HARDWARE( fxMesa
);
275 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
277 printf("SwapBuf SetState 1\n");
279 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
286 static int prevStalls
= 0;
288 stalls
= fxMesa
->Glide
.grFifoGetStalls();
290 fprintf( stderr
, "%s:\n", __FUNCTION__
);
291 if ( stalls
!= prevStalls
) {
292 fprintf( stderr
, " %d stalls occurred\n",
293 stalls
- prevStalls
);
296 if ( fxMesa
&& fxMesa
->texSwaps
) {
297 fprintf( stderr
, " %d texture swaps occurred\n",
299 fxMesa
->texSwaps
= 0;
304 if (fxMesa
->scissoredClipRects
) {
305 /* restore clip rects without scissor box */
306 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
307 driDrawPriv
->w
, driDrawPriv
->h
,
308 driDrawPriv
->numClipRects
,
309 driDrawPriv
->pClipRects
);
312 fxMesa
->Glide
.grDRIBufferSwap( fxMesa
->Glide
.SwapInterval
);
314 if (fxMesa
->scissoredClipRects
) {
315 /* restore clip rects WITH scissor box */
316 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
317 driDrawPriv
->w
, driDrawPriv
->h
,
318 fxMesa
->numClipRects
, fxMesa
->pClipRects
);
327 fxMesa
->Glide
.grGet(GR_PENDING_BUFFERSWAPS
, 4, &result
);
328 } while ( result
> fxMesa
->maxPendingSwapBuffers
);
332 fxMesa
->stats
.swapBuffer
++;
335 if (ctx
->DriverCtx
!= fxMesa
) {
336 fxMesa
= TDFX_CONTEXT(ctx
);
337 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
339 printf("SwapBuf SetState 2\n");
341 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
343 UNLOCK_HARDWARE( fxMesa
);
348 static const struct __DriverAPIRec tdfxAPI
= {
349 .InitDriver
= tdfxInitDriver
,
350 .DestroyScreen
= tdfxDestroyScreen
,
351 .CreateContext
= tdfxCreateContext
,
352 .DestroyContext
= tdfxDestroyContext
,
353 .CreateBuffer
= tdfxCreateBuffer
,
354 .DestroyBuffer
= tdfxDestroyBuffer
,
355 .SwapBuffers
= tdfxSwapBuffers
,
356 .MakeCurrent
= tdfxMakeCurrent
,
357 .UnbindContext
= tdfxUnbindContext
,
362 .SwapBuffersMSC
= NULL
366 static __GLcontextModes
*tdfxFillInModes(unsigned pixel_bits
,
368 unsigned stencil_bits
,
369 GLboolean have_back_buffer
)
371 __GLcontextModes
*modes
;
374 unsigned vis
[2] = { GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
};
375 unsigned deep
= (depth_bits
> 17);
376 unsigned i
, db
, depth
, accum
, stencil
;
378 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
379 * enough to add support. Basically, if a context is created with an
380 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
381 * will never be used.
384 num_modes
= (depth_bits
== 16) ? 32 : 16;
386 modes
= (*dri_interface
->createContextModes
)(num_modes
, sizeof(__GLcontextModes
));
389 for (i
= 0; i
<= 1; i
++) {
390 for (db
= 0; db
<= 1; db
++) {
391 for (depth
= 0; depth
<= 1; depth
++) {
392 for (accum
= 0; accum
<= 1; accum
++) {
393 for (stencil
= 0; stencil
<= !deep
; stencil
++) {
394 if (deep
) stencil
= depth
;
395 m
->redBits
= deep
? 8 : 5;
396 m
->greenBits
= deep
? 8 : 6;
397 m
->blueBits
= deep
? 8 : 5;
398 m
->alphaBits
= deep
? 8 : 0;
399 m
->redMask
= deep
?0xFF000000 :0x0000F800;
400 m
->greenMask
= deep
?0x00FF0000 :0x000007E0;
401 m
->blueMask
= deep
?0x0000FF00 :0x0000001F;
402 m
->alphaMask
= deep
? 0x000000FF : 0;
403 m
->rgbBits
= m
->redBits
+ m
->greenBits
+
404 m
->blueBits
+ m
->alphaBits
;
405 m
->accumRedBits
= accum
? 16 : 0;
406 m
->accumGreenBits
= accum
? 16 : 0;
407 m
->accumBlueBits
= accum
? 16 : 0;
408 m
->accumAlphaBits
= (accum
&& deep
) ? 16 : 0;
409 m
->stencilBits
= stencil
? 8 : 0;
412 : (depth
? 0 : depth_bits
);
413 m
->visualType
= vis
[i
];
414 m
->renderType
= GLX_RGBA_BIT
;
415 m
->drawableType
= GLX_WINDOW_BIT
;
416 m
->rgbMode
= GL_TRUE
;
417 m
->doubleBufferMode
= db
? GL_TRUE
: GL_FALSE
;
419 m
->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
420 m
->visualRating
= ((stencil
&& !deep
) || accum
)
424 if (deep
) stencil
= 0;
435 * This is the bootstrap function for the driver. libGL supplies all of the
436 * requisite information about the system, and the driver initializes itself.
437 * This routine also fills in the linked list pointed to by \c driver_modes
438 * with the \c __GLcontextModes that the driver can support for windows or
441 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
445 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
446 const __GLcontextModes
* modes
,
447 const __DRIversion
* ddx_version
,
448 const __DRIversion
* dri_version
,
449 const __DRIversion
* drm_version
,
450 const __DRIframebuffer
* frame_buffer
,
451 drmAddress pSAREA
, int fd
,
452 int internal_api_version
,
453 const __DRIinterfaceMethods
* interface
,
454 __GLcontextModes
** driver_modes
)
456 __DRIscreenPrivate
*psp
;
457 static const __DRIversion ddx_expected
= { 1, 1, 0 };
458 static const __DRIversion dri_expected
= { 4, 0, 0 };
459 static const __DRIversion drm_expected
= { 1, 0, 0 };
461 dri_interface
= interface
;
463 if ( ! driCheckDriDdxDrmVersions2( "tdfx",
464 dri_version
, & dri_expected
,
465 ddx_version
, & ddx_expected
,
466 drm_version
, & drm_expected
) ) {
470 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
471 ddx_version
, dri_version
, drm_version
,
472 frame_buffer
, pSAREA
, fd
,
473 internal_api_version
, &tdfxAPI
);
476 /* divined from tdfx_dri.c, sketchy */
477 TDFXDRIPtr dri_priv
= (TDFXDRIPtr
) psp
->pDevPriv
;
478 int bpp
= (dri_priv
->cpp
> 2) ? 24 : 16;
480 /* XXX i wish it was like this */
481 /* bpp = dri_priv->bpp */
483 *driver_modes
= tdfxFillInModes(bpp
, (bpp
== 16) ? 16 : 24,
485 (dri_priv
->backOffset
!=dri_priv
->depthOffset
));
487 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
488 * enable the extensions. It just makes sure that all the dispatch offsets for all
489 * the extensions that *might* be enables are known. This is needed because the
490 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
491 * enable the extensions until we have a context pointer.
493 * Hello chicken. Hello egg. How are you two today?
495 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
496 driInitExtensions( NULL
, napalm_extensions
, GL_FALSE
);