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
29 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
32 * Gareth Hughes <gareth@valinux.com>
37 #include "tdfx_context.h"
38 #include "tdfx_lock.h"
40 #include "tdfx_span.h"
41 #include "tdfx_tris.h"
43 #include "main/framebuffer.h"
44 #include "main/renderbuffer.h"
50 char *prevLockFile
= 0;
58 PUBLIC
const char __driConfigOptions
[] =
60 DRI_CONF_SECTION_DEBUG
61 DRI_CONF_NO_RAST(false)
65 static const __DRIextension
*tdfxExtensions
[] = {
66 &driReadDrawableExtension
,
70 static const GLuint __driNConfigOptions
= 1;
73 tdfxCreateScreen( __DRIscreen
*sPriv
)
75 tdfxScreenPrivate
*fxScreen
;
76 TDFXDRIPtr fxDRIPriv
= (TDFXDRIPtr
) sPriv
->pDevPriv
;
78 if (sPriv
->devPrivSize
!= sizeof(TDFXDRIRec
)) {
79 fprintf(stderr
,"\nERROR! sizeof(TDFXDRIRec) does not match passed size from device driver\n");
83 /* Allocate the private area */
84 fxScreen
= (tdfxScreenPrivate
*) CALLOC( sizeof(tdfxScreenPrivate
) );
88 /* parse information in __driConfigOptions */
89 driParseOptionInfo (&fxScreen
->optionCache
,
90 __driConfigOptions
, __driNConfigOptions
);
92 fxScreen
->driScrnPriv
= sPriv
;
93 sPriv
->private = (void *) fxScreen
;
95 fxScreen
->regs
.handle
= fxDRIPriv
->regs
;
96 fxScreen
->regs
.size
= fxDRIPriv
->regsSize
;
97 fxScreen
->deviceID
= fxDRIPriv
->deviceID
;
98 fxScreen
->width
= fxDRIPriv
->width
;
99 fxScreen
->height
= fxDRIPriv
->height
;
100 fxScreen
->mem
= fxDRIPriv
->mem
;
101 fxScreen
->cpp
= fxDRIPriv
->cpp
;
102 fxScreen
->stride
= fxDRIPriv
->stride
;
103 fxScreen
->fifoOffset
= fxDRIPriv
->fifoOffset
;
104 fxScreen
->fifoSize
= fxDRIPriv
->fifoSize
;
105 fxScreen
->fbOffset
= fxDRIPriv
->fbOffset
;
106 fxScreen
->backOffset
= fxDRIPriv
->backOffset
;
107 fxScreen
->depthOffset
= fxDRIPriv
->depthOffset
;
108 fxScreen
->textureOffset
= fxDRIPriv
->textureOffset
;
109 fxScreen
->textureSize
= fxDRIPriv
->textureSize
;
110 fxScreen
->sarea_priv_offset
= fxDRIPriv
->sarea_priv_offset
;
112 if ( drmMap( sPriv
->fd
, fxScreen
->regs
.handle
,
113 fxScreen
->regs
.size
, &fxScreen
->regs
.map
) ) {
117 sPriv
->extensions
= tdfxExtensions
;
124 tdfxDestroyScreen( __DRIscreen
*sPriv
)
126 tdfxScreenPrivate
*fxScreen
= (tdfxScreenPrivate
*) sPriv
->private;
131 drmUnmap( fxScreen
->regs
.map
, fxScreen
->regs
.size
);
133 /* free all option information */
134 driDestroyOptionInfo (&fxScreen
->optionCache
);
137 sPriv
->private = NULL
;
142 tdfxInitDriver( __DRIscreen
*sPriv
)
144 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
145 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)sPriv
);
148 if ( !tdfxCreateScreen( sPriv
) ) {
149 tdfxDestroyScreen( sPriv
);
158 tdfxCreateBuffer( __DRIscreen
*driScrnPriv
,
159 __DRIdrawable
*driDrawPriv
,
160 const __GLcontextModes
*mesaVis
,
163 tdfxScreenPrivate
*screen
= (tdfxScreenPrivate
*) driScrnPriv
->private;
166 return GL_FALSE
; /* not implemented */
169 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
172 driRenderbuffer
*frontRb
173 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
, screen
->cpp
,
174 screen
->fbOffset
, screen
->width
, driDrawPriv
);
175 tdfxSetSpanFunctions(frontRb
, mesaVis
);
176 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
179 if (mesaVis
->doubleBufferMode
) {
180 driRenderbuffer
*backRb
181 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
, screen
->cpp
,
182 screen
->backOffset
, screen
->width
,
184 tdfxSetSpanFunctions(backRb
, mesaVis
);
185 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
186 backRb
->backBuffer
= GL_TRUE
;
189 if (mesaVis
->depthBits
== 16) {
190 driRenderbuffer
*depthRb
191 = driNewRenderbuffer(MESA_FORMAT_Z16
, NULL
, screen
->cpp
,
192 screen
->depthOffset
, screen
->width
,
194 tdfxSetSpanFunctions(depthRb
, mesaVis
);
195 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
197 else if (mesaVis
->depthBits
== 24) {
198 driRenderbuffer
*depthRb
199 = driNewRenderbuffer(MESA_FORMAT_Z24_S8
, NULL
, screen
->cpp
,
200 screen
->depthOffset
, screen
->width
,
202 tdfxSetSpanFunctions(depthRb
, mesaVis
);
203 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
206 if (mesaVis
->stencilBits
> 0) {
207 driRenderbuffer
*stencilRb
208 = driNewRenderbuffer(MESA_FORMAT_S8
, NULL
, screen
->cpp
,
209 screen
->depthOffset
, screen
->width
,
211 tdfxSetSpanFunctions(stencilRb
, mesaVis
);
212 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
215 _mesa_add_soft_renderbuffers(fb
,
216 GL_FALSE
, /* color */
217 GL_FALSE
, /* depth */
218 GL_FALSE
, /*swStencil,*/
219 mesaVis
->accumRedBits
> 0,
220 GL_FALSE
, /* alpha */
222 driDrawPriv
->driverPrivate
= (void *) fb
;
224 return (driDrawPriv
->driverPrivate
!= NULL
);
230 tdfxDestroyBuffer(__DRIdrawable
*driDrawPriv
)
232 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
237 tdfxSwapBuffers( __DRIdrawable
*driDrawPriv
)
240 GET_CURRENT_CONTEXT(ctx
);
241 tdfxContextPtr fxMesa
= 0;
242 GLframebuffer
*mesaBuffer
;
244 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
245 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)driDrawPriv
);
248 mesaBuffer
= (GLframebuffer
*) driDrawPriv
->driverPrivate
;
249 if ( !mesaBuffer
->Visual
.doubleBufferMode
)
250 return; /* can't swap a single-buffered window */
252 /* If the current context's drawable matches the given drawable
253 * we have to do a glFinish (per the GLX spec).
256 __DRIdrawable
*curDrawPriv
;
257 fxMesa
= TDFX_CONTEXT(ctx
);
258 curDrawPriv
= fxMesa
->driContext
->driDrawablePriv
;
260 if ( curDrawPriv
== driDrawPriv
) {
261 /* swapping window bound to current context, flush first */
262 _mesa_notifySwapBuffers( ctx
);
263 LOCK_HARDWARE( fxMesa
);
266 /* find the fxMesa context previously bound to the window */
267 fxMesa
= (tdfxContextPtr
) driDrawPriv
->driContextPriv
->driverPrivate
;
270 LOCK_HARDWARE( fxMesa
);
271 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
273 printf("SwapBuf SetState 1\n");
275 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
282 static int prevStalls
= 0;
284 stalls
= fxMesa
->Glide
.grFifoGetStalls();
286 fprintf( stderr
, "%s:\n", __FUNCTION__
);
287 if ( stalls
!= prevStalls
) {
288 fprintf( stderr
, " %d stalls occurred\n",
289 stalls
- prevStalls
);
292 if ( fxMesa
&& fxMesa
->texSwaps
) {
293 fprintf( stderr
, " %d texture swaps occurred\n",
295 fxMesa
->texSwaps
= 0;
300 if (fxMesa
->scissoredClipRects
) {
301 /* restore clip rects without scissor box */
302 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
303 driDrawPriv
->w
, driDrawPriv
->h
,
304 driDrawPriv
->numClipRects
,
305 driDrawPriv
->pClipRects
);
308 fxMesa
->Glide
.grDRIBufferSwap( fxMesa
->Glide
.SwapInterval
);
310 if (fxMesa
->scissoredClipRects
) {
311 /* restore clip rects WITH scissor box */
312 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
313 driDrawPriv
->w
, driDrawPriv
->h
,
314 fxMesa
->numClipRects
, fxMesa
->pClipRects
);
323 fxMesa
->Glide
.grGet(GR_PENDING_BUFFERSWAPS
, 4, &result
);
324 } while ( result
> fxMesa
->maxPendingSwapBuffers
);
328 fxMesa
->stats
.swapBuffer
++;
331 if (ctx
->DriverCtx
!= fxMesa
) {
332 fxMesa
= TDFX_CONTEXT(ctx
);
333 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
335 printf("SwapBuf SetState 2\n");
337 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
339 UNLOCK_HARDWARE( fxMesa
);
343 static const __DRIconfig
**
344 tdfxFillInModes(__DRIscreen
*psp
,
347 unsigned stencil_bits
,
348 GLboolean have_back_buffer
)
350 unsigned deep
= (depth_bits
> 17);
352 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
353 * enough to add support. Basically, if a context is created with an
354 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
355 * will never be used.
358 static const GLenum db_modes
[2] = { GLX_NONE
, GLX_SWAP_UNDEFINED_OML
};
359 uint8_t depth_bits_array
[4];
360 uint8_t stencil_bits_array
[4];
361 uint8_t msaa_samples_array
[1];
363 depth_bits_array
[0] = 0;
364 depth_bits_array
[1] = 24;
365 stencil_bits_array
[0] = 0;
366 stencil_bits_array
[1] = 8;
368 depth_bits_array
[0] = depth_bits
;
369 depth_bits_array
[1] = 0;
370 depth_bits_array
[2] = depth_bits
;
371 depth_bits_array
[3] = 0;
372 stencil_bits_array
[0] = 0;
373 stencil_bits_array
[1] = 0;
374 stencil_bits_array
[2] = 8;
375 stencil_bits_array
[3] = 8;
378 msaa_samples_array
[0] = 0;
380 return (const __DRIconfig
**)
381 driCreateConfigs(deep
? GL_RGBA
: GL_RGB
,
382 deep
? GL_UNSIGNED_INT_8_8_8_8
:
383 GL_UNSIGNED_SHORT_5_6_5
,
388 msaa_samples_array
, 1);
392 * This is the driver specific part of the createNewScreen entry point.
394 * \todo maybe fold this into intelInitDriver
396 * \return the __GLcontextModes supported by this driver
398 static const __DRIconfig
**
399 tdfxInitScreen(__DRIscreen
*psp
)
401 static const __DRIversion ddx_expected
= { 1, 1, 0 };
402 static const __DRIversion dri_expected
= { 4, 0, 0 };
403 static const __DRIversion drm_expected
= { 1, 0, 0 };
405 /* divined from tdfx_dri.c, sketchy */
406 TDFXDRIPtr dri_priv
= (TDFXDRIPtr
) psp
->pDevPriv
;
408 /* XXX i wish it was like this */
409 /* bpp = dri_priv->bpp */
410 int bpp
= (dri_priv
->cpp
> 2) ? 24 : 16;
412 if ( ! driCheckDriDdxDrmVersions2( "tdfx",
413 &psp
->dri_version
, & dri_expected
,
414 &psp
->ddx_version
, & ddx_expected
,
415 &psp
->drm_version
, & drm_expected
) )
418 if (!tdfxInitDriver(psp
))
421 return tdfxFillInModes(psp
,
422 bpp
, (bpp
== 16) ? 16 : 24,
424 (dri_priv
->backOffset
!=dri_priv
->depthOffset
));
427 const struct __DriverAPIRec driDriverAPI
= {
428 .InitScreen
= tdfxInitScreen
,
429 .DestroyScreen
= tdfxDestroyScreen
,
430 .CreateContext
= tdfxCreateContext
,
431 .DestroyContext
= tdfxDestroyContext
,
432 .CreateBuffer
= tdfxCreateBuffer
,
433 .DestroyBuffer
= tdfxDestroyBuffer
,
434 .SwapBuffers
= tdfxSwapBuffers
,
435 .MakeCurrent
= tdfxMakeCurrent
,
436 .UnbindContext
= tdfxUnbindContext
,
438 .GetDrawableMSC
= NULL
,
441 .SwapBuffersMSC
= NULL
444 /* This is the table of extensions that the loader will dlsym() for. */
445 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
446 &driCoreExtension
.base
,
447 &driLegacyExtension
.base
,