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"
39 #include "tdfx_span.h"
41 #include "main/framebuffer.h"
42 #include "main/renderbuffer.h"
48 char *prevLockFile
= 0;
56 PUBLIC
const char __driConfigOptions
[] =
58 DRI_CONF_SECTION_DEBUG
59 DRI_CONF_NO_RAST(false)
63 static const __DRIextension
*tdfxExtensions
[] = {
64 &driReadDrawableExtension
,
68 static const GLuint __driNConfigOptions
= 1;
71 tdfxCreateScreen( __DRIscreen
*sPriv
)
73 tdfxScreenPrivate
*fxScreen
;
74 TDFXDRIPtr fxDRIPriv
= (TDFXDRIPtr
) sPriv
->pDevPriv
;
76 if (sPriv
->devPrivSize
!= sizeof(TDFXDRIRec
)) {
77 fprintf(stderr
,"\nERROR! sizeof(TDFXDRIRec) does not match passed size from device driver\n");
81 /* Allocate the private area */
82 fxScreen
= (tdfxScreenPrivate
*) CALLOC( sizeof(tdfxScreenPrivate
) );
86 /* parse information in __driConfigOptions */
87 driParseOptionInfo (&fxScreen
->optionCache
,
88 __driConfigOptions
, __driNConfigOptions
);
90 fxScreen
->driScrnPriv
= sPriv
;
91 sPriv
->private = (void *) fxScreen
;
93 fxScreen
->regs
.handle
= fxDRIPriv
->regs
;
94 fxScreen
->regs
.size
= fxDRIPriv
->regsSize
;
95 fxScreen
->deviceID
= fxDRIPriv
->deviceID
;
96 fxScreen
->width
= fxDRIPriv
->width
;
97 fxScreen
->height
= fxDRIPriv
->height
;
98 fxScreen
->mem
= fxDRIPriv
->mem
;
99 fxScreen
->cpp
= fxDRIPriv
->cpp
;
100 fxScreen
->stride
= fxDRIPriv
->stride
;
101 fxScreen
->fifoOffset
= fxDRIPriv
->fifoOffset
;
102 fxScreen
->fifoSize
= fxDRIPriv
->fifoSize
;
103 fxScreen
->fbOffset
= fxDRIPriv
->fbOffset
;
104 fxScreen
->backOffset
= fxDRIPriv
->backOffset
;
105 fxScreen
->depthOffset
= fxDRIPriv
->depthOffset
;
106 fxScreen
->textureOffset
= fxDRIPriv
->textureOffset
;
107 fxScreen
->textureSize
= fxDRIPriv
->textureSize
;
108 fxScreen
->sarea_priv_offset
= fxDRIPriv
->sarea_priv_offset
;
110 if ( drmMap( sPriv
->fd
, fxScreen
->regs
.handle
,
111 fxScreen
->regs
.size
, &fxScreen
->regs
.map
) ) {
115 sPriv
->extensions
= tdfxExtensions
;
122 tdfxDestroyScreen( __DRIscreen
*sPriv
)
124 tdfxScreenPrivate
*fxScreen
= (tdfxScreenPrivate
*) sPriv
->private;
129 drmUnmap( fxScreen
->regs
.map
, fxScreen
->regs
.size
);
131 /* free all option information */
132 driDestroyOptionInfo (&fxScreen
->optionCache
);
135 sPriv
->private = NULL
;
140 tdfxInitDriver( __DRIscreen
*sPriv
)
142 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
143 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)sPriv
);
146 if ( !tdfxCreateScreen( sPriv
) ) {
147 tdfxDestroyScreen( sPriv
);
156 tdfxCreateBuffer( __DRIscreen
*driScrnPriv
,
157 __DRIdrawable
*driDrawPriv
,
158 const __GLcontextModes
*mesaVis
,
161 tdfxScreenPrivate
*screen
= (tdfxScreenPrivate
*) driScrnPriv
->private;
164 return GL_FALSE
; /* not implemented */
167 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
170 driRenderbuffer
*frontRb
171 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
, screen
->cpp
,
172 screen
->fbOffset
, screen
->width
, driDrawPriv
);
173 tdfxSetSpanFunctions(frontRb
, mesaVis
);
174 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
177 if (mesaVis
->doubleBufferMode
) {
178 driRenderbuffer
*backRb
179 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
, screen
->cpp
,
180 screen
->backOffset
, screen
->width
,
182 tdfxSetSpanFunctions(backRb
, mesaVis
);
183 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
184 backRb
->backBuffer
= GL_TRUE
;
187 if (mesaVis
->depthBits
== 16) {
188 driRenderbuffer
*depthRb
189 = driNewRenderbuffer(MESA_FORMAT_Z16
, NULL
, screen
->cpp
,
190 screen
->depthOffset
, screen
->width
,
192 tdfxSetSpanFunctions(depthRb
, mesaVis
);
193 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
195 else if (mesaVis
->depthBits
== 24) {
196 driRenderbuffer
*depthRb
197 = driNewRenderbuffer(MESA_FORMAT_Z24_S8
, NULL
, screen
->cpp
,
198 screen
->depthOffset
, screen
->width
,
200 tdfxSetSpanFunctions(depthRb
, mesaVis
);
201 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
204 if (mesaVis
->stencilBits
> 0) {
205 driRenderbuffer
*stencilRb
206 = driNewRenderbuffer(MESA_FORMAT_S8
, NULL
, screen
->cpp
,
207 screen
->depthOffset
, screen
->width
,
209 tdfxSetSpanFunctions(stencilRb
, mesaVis
);
210 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
213 _mesa_add_soft_renderbuffers(fb
,
214 GL_FALSE
, /* color */
215 GL_FALSE
, /* depth */
216 GL_FALSE
, /*swStencil,*/
217 mesaVis
->accumRedBits
> 0,
218 GL_FALSE
, /* alpha */
220 driDrawPriv
->driverPrivate
= (void *) fb
;
222 return (driDrawPriv
->driverPrivate
!= NULL
);
228 tdfxDestroyBuffer(__DRIdrawable
*driDrawPriv
)
230 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
235 tdfxSwapBuffers( __DRIdrawable
*driDrawPriv
)
238 GET_CURRENT_CONTEXT(ctx
);
239 tdfxContextPtr fxMesa
= 0;
240 GLframebuffer
*mesaBuffer
;
242 if ( TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
243 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *)driDrawPriv
);
246 mesaBuffer
= (GLframebuffer
*) driDrawPriv
->driverPrivate
;
247 if ( !mesaBuffer
->Visual
.doubleBufferMode
)
248 return; /* can't swap a single-buffered window */
250 /* If the current context's drawable matches the given drawable
251 * we have to do a glFinish (per the GLX spec).
254 __DRIdrawable
*curDrawPriv
;
255 fxMesa
= TDFX_CONTEXT(ctx
);
256 curDrawPriv
= fxMesa
->driContext
->driDrawablePriv
;
258 if ( curDrawPriv
== driDrawPriv
) {
259 /* swapping window bound to current context, flush first */
260 _mesa_notifySwapBuffers( ctx
);
261 LOCK_HARDWARE( fxMesa
);
264 /* find the fxMesa context previously bound to the window */
265 fxMesa
= (tdfxContextPtr
) driDrawPriv
->driContextPriv
->driverPrivate
;
268 LOCK_HARDWARE( fxMesa
);
269 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
271 printf("SwapBuf SetState 1\n");
273 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
280 static int prevStalls
= 0;
282 stalls
= fxMesa
->Glide
.grFifoGetStalls();
284 fprintf( stderr
, "%s:\n", __FUNCTION__
);
285 if ( stalls
!= prevStalls
) {
286 fprintf( stderr
, " %d stalls occurred\n",
287 stalls
- prevStalls
);
290 if ( fxMesa
&& fxMesa
->texSwaps
) {
291 fprintf( stderr
, " %d texture swaps occurred\n",
293 fxMesa
->texSwaps
= 0;
298 if (fxMesa
->scissoredClipRects
) {
299 /* restore clip rects without scissor box */
300 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
301 driDrawPriv
->w
, driDrawPriv
->h
,
302 driDrawPriv
->numClipRects
,
303 driDrawPriv
->pClipRects
);
306 fxMesa
->Glide
.grDRIBufferSwap( fxMesa
->Glide
.SwapInterval
);
308 if (fxMesa
->scissoredClipRects
) {
309 /* restore clip rects WITH scissor box */
310 fxMesa
->Glide
.grDRIPosition( driDrawPriv
->x
, driDrawPriv
->y
,
311 driDrawPriv
->w
, driDrawPriv
->h
,
312 fxMesa
->numClipRects
, fxMesa
->pClipRects
);
321 fxMesa
->Glide
.grGet(GR_PENDING_BUFFERSWAPS
, 4, &result
);
322 } while ( result
> fxMesa
->maxPendingSwapBuffers
);
326 fxMesa
->stats
.swapBuffer
++;
329 if (ctx
->DriverCtx
!= fxMesa
) {
330 fxMesa
= TDFX_CONTEXT(ctx
);
331 fxMesa
->Glide
.grSstSelect( fxMesa
->Glide
.Board
);
333 printf("SwapBuf SetState 2\n");
335 fxMesa
->Glide
.grGlideSetState(fxMesa
->Glide
.State
);
337 UNLOCK_HARDWARE( fxMesa
);
341 static const __DRIconfig
**
342 tdfxFillInModes(__DRIscreen
*psp
,
345 unsigned stencil_bits
,
346 GLboolean have_back_buffer
)
348 unsigned deep
= (depth_bits
> 17);
350 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
351 * enough to add support. Basically, if a context is created with an
352 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
353 * will never be used.
356 static const GLenum db_modes
[2] = { GLX_NONE
, GLX_SWAP_UNDEFINED_OML
};
357 uint8_t depth_bits_array
[4];
358 uint8_t stencil_bits_array
[4];
359 uint8_t msaa_samples_array
[1];
361 depth_bits_array
[0] = 0;
362 depth_bits_array
[1] = 24;
363 stencil_bits_array
[0] = 0;
364 stencil_bits_array
[1] = 8;
366 depth_bits_array
[0] = depth_bits
;
367 depth_bits_array
[1] = 0;
368 depth_bits_array
[2] = depth_bits
;
369 depth_bits_array
[3] = 0;
370 stencil_bits_array
[0] = 0;
371 stencil_bits_array
[1] = 0;
372 stencil_bits_array
[2] = 8;
373 stencil_bits_array
[3] = 8;
376 msaa_samples_array
[0] = 0;
378 return (const __DRIconfig
**)
379 driCreateConfigs(deep
? GL_RGBA
: GL_RGB
,
380 deep
? GL_UNSIGNED_INT_8_8_8_8
:
381 GL_UNSIGNED_SHORT_5_6_5
,
386 msaa_samples_array
, 1,
391 * This is the driver specific part of the createNewScreen entry point.
393 * \todo maybe fold this into intelInitDriver
395 * \return the __GLcontextModes supported by this driver
397 static const __DRIconfig
**
398 tdfxInitScreen(__DRIscreen
*psp
)
400 static const __DRIversion ddx_expected
= { 1, 1, 0 };
401 static const __DRIversion dri_expected
= { 4, 0, 0 };
402 static const __DRIversion drm_expected
= { 1, 0, 0 };
404 /* divined from tdfx_dri.c, sketchy */
405 TDFXDRIPtr dri_priv
= (TDFXDRIPtr
) psp
->pDevPriv
;
407 /* XXX i wish it was like this */
408 /* bpp = dri_priv->bpp */
409 int bpp
= (dri_priv
->cpp
> 2) ? 24 : 16;
411 if ( ! driCheckDriDdxDrmVersions2( "tdfx",
412 &psp
->dri_version
, & dri_expected
,
413 &psp
->ddx_version
, & ddx_expected
,
414 &psp
->drm_version
, & drm_expected
) )
417 if (!tdfxInitDriver(psp
))
420 return tdfxFillInModes(psp
,
421 bpp
, (bpp
== 16) ? 16 : 24,
423 (dri_priv
->backOffset
!=dri_priv
->depthOffset
));
426 const struct __DriverAPIRec driDriverAPI
= {
427 .InitScreen
= tdfxInitScreen
,
428 .DestroyScreen
= tdfxDestroyScreen
,
429 .CreateContext
= tdfxCreateContext
,
430 .DestroyContext
= tdfxDestroyContext
,
431 .CreateBuffer
= tdfxCreateBuffer
,
432 .DestroyBuffer
= tdfxDestroyBuffer
,
433 .SwapBuffers
= tdfxSwapBuffers
,
434 .MakeCurrent
= tdfxMakeCurrent
,
435 .UnbindContext
= tdfxUnbindContext
,
437 .GetDrawableMSC
= NULL
,
440 .SwapBuffersMSC
= NULL
443 /* This is the table of extensions that the loader will dlsym() for. */
444 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
445 &driCoreExtension
.base
,
446 &driLegacyExtension
.base
,