2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
31 #include "framebuffer.h"
32 #include "renderbuffer.h"
34 #include "simple_list.h"
37 #include "via_state.h"
41 #include "via_ioctl.h"
42 #include "via_screen.h"
46 #include "GL/internal/dri_interface.h"
48 /* Radeon configuration
52 const char __driConfigOptions
[] =
54 DRI_CONF_SECTION_PERFORMANCE
55 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS
)
56 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
58 DRI_CONF_SECTION_DEBUG
59 DRI_CONF_NO_RAST(false)
62 static const GLuint __driNConfigOptions
= 3;
65 #ifdef USE_NEW_INTERFACE
66 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
67 #endif /* USE_NEW_INTERFACE */
69 static int getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
);
71 static drmBufMapPtr
via_create_empty_buffers(void)
75 retval
= (drmBufMapPtr
)MALLOC(sizeof(drmBufMap
));
76 if (retval
== NULL
) return NULL
;
77 memset(retval
, 0, sizeof(drmBufMap
));
79 retval
->list
= (drmBufPtr
)MALLOC(sizeof(drmBuf
) * VIA_DMA_BUF_NR
);
80 if (retval
->list
== NULL
) {
84 memset(retval
->list
, 0, sizeof(drmBuf
) * VIA_DMA_BUF_NR
);
88 static void via_free_empty_buffers( drmBufMapPtr bufs
)
90 if (bufs
&& bufs
->list
)
99 viaInitDriver(__DRIscreenPrivate
*sPriv
)
101 viaScreenPrivate
*viaScreen
;
102 VIADRIPtr gDRIPriv
= (VIADRIPtr
)sPriv
->pDevPriv
;
105 /* Allocate the private area */
106 viaScreen
= (viaScreenPrivate
*) CALLOC(sizeof(viaScreenPrivate
));
108 __driUtilMessage("viaInitDriver: alloc viaScreenPrivate struct failed");
112 /* parse information in __driConfigOptions */
113 driParseOptionInfo (&viaScreen
->optionCache
,
114 __driConfigOptions
, __driNConfigOptions
);
117 viaScreen
->driScrnPriv
= sPriv
;
118 sPriv
->private = (void *)viaScreen
;
120 viaScreen
->deviceID
= gDRIPriv
->deviceID
;
121 viaScreen
->width
= gDRIPriv
->width
;
122 viaScreen
->height
= gDRIPriv
->height
;
123 viaScreen
->mem
= gDRIPriv
->mem
;
124 viaScreen
->bitsPerPixel
= gDRIPriv
->bytesPerPixel
<< 3;
125 viaScreen
->bytesPerPixel
= gDRIPriv
->bytesPerPixel
;
126 viaScreen
->fbOffset
= 0;
127 viaScreen
->fbSize
= gDRIPriv
->fbSize
;
128 viaScreen
->irqEnabled
= gDRIPriv
->irqEnabled
;
129 viaScreen
->irqEnabled
= 1;
131 if (VIA_DEBUG
& DEBUG_DRI
) {
132 fprintf(stderr
, "deviceID = %08x\n", viaScreen
->deviceID
);
133 fprintf(stderr
, "width = %08x\n", viaScreen
->width
);
134 fprintf(stderr
, "height = %08x\n", viaScreen
->height
);
135 fprintf(stderr
, "cpp = %08x\n", viaScreen
->cpp
);
136 fprintf(stderr
, "fbOffset = %08x\n", viaScreen
->fbOffset
);
139 viaScreen
->bufs
= via_create_empty_buffers();
140 if (viaScreen
->bufs
== NULL
) {
141 __driUtilMessage("viaInitDriver: via_create_empty_buffers() failed");
146 if (drmMap(sPriv
->fd
,
147 gDRIPriv
->regs
.handle
,
149 (drmAddress
*)&viaScreen
->reg
) != 0) {
151 sPriv
->private = NULL
;
152 __driUtilMessage("viaInitDriver: drmMap regs failed");
156 if (gDRIPriv
->agp
.size
) {
157 if (drmMap(sPriv
->fd
,
158 gDRIPriv
->agp
.handle
,
160 (drmAddress
*)&viaScreen
->agpLinearStart
) != 0) {
162 drmUnmap(viaScreen
->reg
, gDRIPriv
->agp
.size
);
163 sPriv
->private = NULL
;
164 __driUtilMessage("viaInitDriver: drmMap agp failed");
167 viaScreen
->agpBase
= (GLuint
*)gDRIPriv
->agp
.handle
;
169 viaScreen
->agpLinearStart
= 0;
171 viaScreen
->sareaPrivOffset
= gDRIPriv
->sarea_priv_offset
;
175 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
176 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
177 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress(
178 (const GLubyte
*) "__glXScrEnableExtension" );
179 void * const psc
= sPriv
->psc
->screenConfigs
;
181 if ( glx_enable_extension
!= NULL
) {
182 if ( viaScreen
->irqEnabled
) {
183 (*glx_enable_extension
)( psc
, "GLX_SGI_swap_control" );
184 (*glx_enable_extension
)( psc
, "GLX_SGI_video_sync" );
185 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_control" );
188 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
190 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
191 (*glx_enable_extension
)( psc
, "GLX_SGIX_fbconfig" );
192 (*glx_enable_extension
)( psc
, "GLX_OML_swap_method" );
202 viaDestroyScreen(__DRIscreenPrivate
*sPriv
)
204 viaScreenPrivate
*viaScreen
= (viaScreenPrivate
*)sPriv
->private;
205 VIADRIPtr gDRIPriv
= (VIADRIPtr
)sPriv
->pDevPriv
;
207 drmUnmap(viaScreen
->reg
, gDRIPriv
->regs
.size
);
208 if (gDRIPriv
->agp
.size
)
209 drmUnmap(viaScreen
->agpLinearStart
, gDRIPriv
->agp
.size
);
211 via_free_empty_buffers(viaScreen
->bufs
);
214 sPriv
->private = NULL
;
219 viaCreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
220 __DRIdrawablePrivate
*driDrawPriv
,
221 const __GLcontextModes
*mesaVis
,
224 viaScreenPrivate
*screen
= (viaScreenPrivate
*) driScrnPriv
->private;
226 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
227 mesaVis
->depthBits
!= 24);
231 /* KW: This needs work, disabled for now:
234 driDrawPriv
->driverPrivate
= (void *)
235 _mesa_create_framebuffer(mesaVis
,
236 GL_FALSE
, /* software depth buffer? */
238 mesaVis
->accumRedBits
> 0,
239 GL_FALSE
/* s/w alpha planes */);
241 return (driDrawPriv
->driverPrivate
!= NULL
);
247 driDrawPriv
->driverPrivate
= (void *)
248 _mesa_create_framebuffer(mesaVis
,
249 GL_FALSE
, /* software depth buffer? */
251 mesaVis
->accumRedBits
> 0,
252 GL_FALSE
/* s/w alpha planes */);
254 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
256 /* XXX check/fix the offset/pitch parameters! */
258 driRenderbuffer
*frontRb
259 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
261 viaSetSpanFunctions(frontRb
, mesaVis
);
262 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
265 if (mesaVis
->doubleBufferMode
) {
266 driRenderbuffer
*backRb
267 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
269 viaSetSpanFunctions(backRb
, mesaVis
);
270 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
273 if (mesaVis
->depthBits
== 16) {
274 driRenderbuffer
*depthRb
275 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, screen
->cpp
,
277 viaSetSpanFunctions(depthRb
, mesaVis
);
278 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
280 else if (mesaVis
->depthBits
== 24) {
281 driRenderbuffer
*depthRb
282 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, screen
->cpp
,
284 viaSetSpanFunctions(depthRb
, mesaVis
);
285 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
287 else if (mesaVis
->depthBits
== 32) {
288 driRenderbuffer
*depthRb
289 = driNewRenderbuffer(GL_DEPTH_COMPONENT32
, screen
->cpp
,
291 viaSetSpanFunctions(depthRb
, mesaVis
);
292 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
296 if (mesaVis->stencilBits > 0 && !swStencil) {
297 driRenderbuffer *stencilRb
298 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, screen->cpp,
299 screen->depthOffset, screen->depthPitch);
300 viaSetSpanFunctions(stencilRb, mesaVis);
301 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
305 _mesa_add_soft_renderbuffers(fb
,
306 GL_FALSE
, /* color */
307 GL_FALSE
, /* depth */
309 mesaVis
->accumRedBits
> 0,
310 GL_FALSE
, /* alpha */
312 driDrawPriv
->driverPrivate
= (void *) fb
;
314 return (driDrawPriv
->driverPrivate
!= NULL
);
320 viaDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
322 _mesa_destroy_framebuffer((GLframebuffer
*)(driDrawPriv
->driverPrivate
));
327 static struct __DriverAPIRec viaAPI
= {
328 .InitDriver
= viaInitDriver
,
329 .DestroyScreen
= viaDestroyScreen
,
330 .CreateContext
= viaCreateContext
,
331 .DestroyContext
= viaDestroyContext
,
332 .CreateBuffer
= viaCreateBuffer
,
333 .DestroyBuffer
= viaDestroyBuffer
,
334 .SwapBuffers
= viaSwapBuffers
,
335 .MakeCurrent
= viaMakeCurrent
,
336 .UnbindContext
= viaUnbindContext
,
337 .GetSwapInfo
= getSwapInfo
,
338 .GetMSC
= driGetMSC32
,
339 .WaitForMSC
= driWaitForMSC32
,
341 .SwapBuffersMSC
= NULL
346 * This is the bootstrap function for the driver.
347 * The __driCreateScreen name is the symbol that libGL.so fetches.
348 * Return: pointer to a __DRIscreenPrivate.
350 #if !defined(DRI_NEW_INTERFACE_ONLY)
351 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
352 int numConfigs
, __GLXvisualConfig
*config
)
354 __DRIscreenPrivate
*psp
;
355 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &viaAPI
);
358 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
361 #ifdef USE_NEW_INTERFACE
362 static __GLcontextModes
*
363 viaFillInModes( unsigned pixel_bits
, GLboolean have_back_buffer
)
365 __GLcontextModes
* modes
;
366 __GLcontextModes
* m
;
368 const unsigned back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
372 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
373 * enough to add support. Basically, if a context is created with an
374 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
375 * will never be used.
377 static const GLenum back_buffer_modes
[] = {
378 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
381 /* The 32-bit depth-buffer mode isn't supported yet, so don't actually
384 static const u_int8_t depth_bits_array
[4] = { 0, 16, 24, 32 };
385 static const u_int8_t stencil_bits_array
[4] = { 0, 0, 8, 0 };
386 const unsigned depth_buffer_factor
= 3;
389 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
391 if ( pixel_bits
== 16 ) {
393 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
397 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
400 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
402 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
403 depth_bits_array
, stencil_bits_array
,
405 back_buffer_modes
, back_buffer_factor
,
407 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
408 __func__
, __LINE__
);
412 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
413 depth_bits_array
, stencil_bits_array
,
415 back_buffer_modes
, back_buffer_factor
,
416 GLX_DIRECT_COLOR
) ) {
417 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
418 __func__
, __LINE__
);
424 #endif /* USE_NEW_INTERFACE */
428 * This is the bootstrap function for the driver. libGL supplies all of the
429 * requisite information about the system, and the driver initializes itself.
430 * This routine also fills in the linked list pointed to by \c driver_modes
431 * with the \c __GLcontextModes that the driver can support for windows or
434 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
437 #ifdef USE_NEW_INTERFACE
439 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
,
441 const __GLcontextModes
* modes
,
442 const __DRIversion
* ddx_version
,
443 const __DRIversion
* dri_version
,
444 const __DRIversion
* drm_version
,
445 const __DRIframebuffer
* frame_buffer
,
446 drmAddress pSAREA
, int fd
,
447 int internal_api_version
,
448 __GLcontextModes
** driver_modes
)
451 __DRIscreenPrivate
*psp
;
452 static const __DRIversion ddx_expected
= { 4, 0, 0 };
453 static const __DRIversion dri_expected
= { 4, 0, 0 };
454 static const __DRIversion drm_expected
= { 2, 3, 0 };
456 if ( ! driCheckDriDdxDrmVersions2( "Unichrome",
457 dri_version
, & dri_expected
,
458 ddx_version
, & ddx_expected
,
459 drm_version
, & drm_expected
) ) {
463 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
464 ddx_version
, dri_version
, drm_version
,
465 frame_buffer
, pSAREA
, fd
,
466 internal_api_version
, &viaAPI
);
468 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
469 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
470 if ( create_context_modes
!= NULL
) {
471 VIADRIPtr dri_priv
= (VIADRIPtr
) psp
->pDevPriv
;
472 *driver_modes
= viaFillInModes( dri_priv
->bytesPerPixel
* 8,
477 fprintf(stderr
, "%s - succeeded\n", __FUNCTION__
);
480 #endif /* USE_NEW_INTERFACE */
484 * Get information about previous buffer swaps.
487 getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
)
489 struct via_context
*vmesa
;
491 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
492 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
493 || (sInfo
== NULL
) ) {
497 vmesa
= (struct via_context
*) dPriv
->driContextPriv
->driverPrivate
;
498 sInfo
->swap_count
= vmesa
->swap_count
;
499 sInfo
->swap_ust
= vmesa
->swap_ust
;
500 sInfo
->swap_missed_count
= vmesa
->swap_missed_count
;
502 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
503 ? driCalculateSwapUsage( dPriv
, 0, vmesa
->swap_missed_ust
)