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"
47 #include "drirenderbuffer.h"
51 const char __driConfigOptions
[] =
53 DRI_CONF_SECTION_PERFORMANCE
54 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
56 DRI_CONF_SECTION_QUALITY
57 DRI_CONF_EXCESS_MIPMAP(false)
59 DRI_CONF_SECTION_DEBUG
60 DRI_CONF_NO_RAST(false)
63 static const GLuint __driNConfigOptions
= 3;
65 extern const struct dri_extension card_extensions
[];
67 static int getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
);
69 static drmBufMapPtr
via_create_empty_buffers(void)
73 retval
= (drmBufMapPtr
)MALLOC(sizeof(drmBufMap
));
74 if (retval
== NULL
) return NULL
;
75 memset(retval
, 0, sizeof(drmBufMap
));
77 retval
->list
= (drmBufPtr
)MALLOC(sizeof(drmBuf
) * VIA_DMA_BUF_NR
);
78 if (retval
->list
== NULL
) {
82 memset(retval
->list
, 0, sizeof(drmBuf
) * VIA_DMA_BUF_NR
);
86 static void via_free_empty_buffers( drmBufMapPtr bufs
)
88 if (bufs
&& bufs
->list
)
97 viaInitDriver(__DRIscreenPrivate
*sPriv
)
99 viaScreenPrivate
*viaScreen
;
100 VIADRIPtr gDRIPriv
= (VIADRIPtr
)sPriv
->pDevPriv
;
103 if (sPriv
->devPrivSize
!= sizeof(VIADRIRec
)) {
104 fprintf(stderr
,"\nERROR! sizeof(VIADRIRec) does not match passed size from device driver\n");
108 /* Allocate the private area */
109 viaScreen
= (viaScreenPrivate
*) CALLOC(sizeof(viaScreenPrivate
));
111 __driUtilMessage("viaInitDriver: alloc viaScreenPrivate struct failed");
115 /* parse information in __driConfigOptions */
116 driParseOptionInfo (&viaScreen
->optionCache
,
117 __driConfigOptions
, __driNConfigOptions
);
120 viaScreen
->driScrnPriv
= sPriv
;
121 sPriv
->private = (void *)viaScreen
;
123 viaScreen
->deviceID
= gDRIPriv
->deviceID
;
124 viaScreen
->width
= gDRIPriv
->width
;
125 viaScreen
->height
= gDRIPriv
->height
;
126 viaScreen
->mem
= gDRIPriv
->mem
;
127 viaScreen
->bitsPerPixel
= gDRIPriv
->bytesPerPixel
* 8;
128 viaScreen
->bytesPerPixel
= gDRIPriv
->bytesPerPixel
;
129 viaScreen
->fbOffset
= 0;
130 viaScreen
->fbSize
= gDRIPriv
->fbSize
;
131 viaScreen
->irqEnabled
= gDRIPriv
->irqEnabled
;
133 if (VIA_DEBUG
& DEBUG_DRI
) {
134 fprintf(stderr
, "deviceID = %08x\n", viaScreen
->deviceID
);
135 fprintf(stderr
, "width = %08x\n", viaScreen
->width
);
136 fprintf(stderr
, "height = %08x\n", viaScreen
->height
);
137 fprintf(stderr
, "cpp = %08x\n", viaScreen
->cpp
);
138 fprintf(stderr
, "fbOffset = %08x\n", viaScreen
->fbOffset
);
141 viaScreen
->bufs
= via_create_empty_buffers();
142 if (viaScreen
->bufs
== NULL
) {
143 __driUtilMessage("viaInitDriver: via_create_empty_buffers() failed");
148 if (drmMap(sPriv
->fd
,
149 gDRIPriv
->regs
.handle
,
151 &viaScreen
->reg
) != 0) {
153 sPriv
->private = NULL
;
154 __driUtilMessage("viaInitDriver: drmMap regs failed");
158 if (gDRIPriv
->agp
.size
) {
159 if (drmMap(sPriv
->fd
,
160 gDRIPriv
->agp
.handle
,
162 (drmAddress
*)&viaScreen
->agpLinearStart
) != 0) {
163 drmUnmap(viaScreen
->reg
, gDRIPriv
->regs
.size
);
165 sPriv
->private = NULL
;
166 __driUtilMessage("viaInitDriver: drmMap agp failed");
170 viaScreen
->agpBase
= drmAgpBase(sPriv
->fd
);
172 viaScreen
->agpLinearStart
= 0;
174 viaScreen
->sareaPrivOffset
= gDRIPriv
->sarea_priv_offset
;
177 viaScreen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
178 viaScreen
->extensions
[i
++] = &driReadDrawableExtension
;
179 if ( viaScreen
->irqEnabled
) {
180 viaScreen
->extensions
[i
++] = &driSwapControlExtension
.base
;
181 viaScreen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
184 viaScreen
->extensions
[i
++] = NULL
;
185 sPriv
->extensions
= viaScreen
->extensions
;
191 viaDestroyScreen(__DRIscreenPrivate
*sPriv
)
193 viaScreenPrivate
*viaScreen
= (viaScreenPrivate
*)sPriv
->private;
194 VIADRIPtr gDRIPriv
= (VIADRIPtr
)sPriv
->pDevPriv
;
196 drmUnmap(viaScreen
->reg
, gDRIPriv
->regs
.size
);
197 if (gDRIPriv
->agp
.size
)
198 drmUnmap(viaScreen
->agpLinearStart
, gDRIPriv
->agp
.size
);
200 via_free_empty_buffers(viaScreen
->bufs
);
202 driDestroyOptionInfo(&viaScreen
->optionCache
);
205 sPriv
->private = NULL
;
210 viaCreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
211 __DRIdrawablePrivate
*driDrawPriv
,
212 const __GLcontextModes
*mesaVis
,
215 viaScreenPrivate
*screen
= (viaScreenPrivate
*) driScrnPriv
->private;
217 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
218 mesaVis
->depthBits
!= 24);
219 GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
222 /* KW: This needs work, disabled for now:
225 driDrawPriv
->driverPrivate
= (void *)
226 _mesa_create_framebuffer(mesaVis
,
227 GL_FALSE
, /* software depth buffer? */
229 mesaVis
->accumRedBits
> 0,
230 GL_FALSE
/* s/w alpha planes */);
232 return (driDrawPriv
->driverPrivate
!= NULL
);
237 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
239 /* The front color, back color and depth renderbuffers are
240 * set up later in calculate_buffer_parameters().
241 * Only create/connect software-based buffers here.
245 /* This code _should_ be put to use. We have to move the
246 * viaRenderbuffer members out of the via_context structure.
247 * Those members should just be the renderbuffers hanging off the
248 * gl_framebuffer object.
250 /* XXX check/fix the offset/pitch parameters! */
252 driRenderbuffer
*frontRb
253 = driNewRenderbuffer(GL_RGBA
, NULL
,
254 screen
->bytesPerPixel
,
255 0, screen
->width
, driDrawPriv
);
256 viaSetSpanFunctions(frontRb
, mesaVis
);
257 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
260 if (mesaVis
->doubleBufferMode
) {
261 driRenderbuffer
*backRb
262 = driNewRenderbuffer(GL_RGBA
, NULL
,
263 screen
->bytesPerPixel
,
264 0, screen
->width
, driDrawPriv
);
265 viaSetSpanFunctions(backRb
, mesaVis
);
266 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
269 if (mesaVis
->depthBits
== 16) {
270 driRenderbuffer
*depthRb
271 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, NULL
,
272 screen
->bytesPerPixel
,
273 0, screen
->width
, driDrawPriv
);
274 viaSetSpanFunctions(depthRb
, mesaVis
);
275 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
277 else if (mesaVis
->depthBits
== 24) {
278 driRenderbuffer
*depthRb
279 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, NULL
,
280 screen
->bytesPerPixel
,
281 0, screen
->width
, driDrawPriv
);
282 viaSetSpanFunctions(depthRb
, mesaVis
);
283 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
285 else if (mesaVis
->depthBits
== 32) {
286 driRenderbuffer
*depthRb
287 = driNewRenderbuffer(GL_DEPTH_COMPONENT32
, NULL
,
288 screen
->bytesPerPixel
,
289 0, screen
->width
, driDrawPriv
);
290 viaSetSpanFunctions(depthRb
, mesaVis
);
291 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
294 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
295 driRenderbuffer
*stencilRb
296 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
, NULL
,
297 screen
->bytesPerPixel
,
298 0, screen
->width
, driDrawPriv
);
299 viaSetSpanFunctions(stencilRb
, mesaVis
);
300 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
304 _mesa_add_soft_renderbuffers(fb
,
305 GL_FALSE
, /* color */
306 GL_FALSE
, /* depth */
309 GL_FALSE
, /* alpha */
311 driDrawPriv
->driverPrivate
= (void *) fb
;
313 return (driDrawPriv
->driverPrivate
!= NULL
);
319 viaDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
321 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
326 static struct __DriverAPIRec viaAPI
= {
327 .DestroyScreen
= viaDestroyScreen
,
328 .CreateContext
= viaCreateContext
,
329 .DestroyContext
= viaDestroyContext
,
330 .CreateBuffer
= viaCreateBuffer
,
331 .DestroyBuffer
= viaDestroyBuffer
,
332 .SwapBuffers
= viaSwapBuffers
,
333 .MakeCurrent
= viaMakeCurrent
,
334 .UnbindContext
= viaUnbindContext
,
335 .GetSwapInfo
= getSwapInfo
,
336 .GetMSC
= driGetMSC32
,
337 .WaitForMSC
= driWaitForMSC32
,
339 .SwapBuffersMSC
= NULL
343 static __GLcontextModes
*
344 viaFillInModes( unsigned pixel_bits
, GLboolean have_back_buffer
)
346 __GLcontextModes
* modes
;
347 __GLcontextModes
* m
;
349 const unsigned back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
353 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
354 * enough to add support. Basically, if a context is created with an
355 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
356 * will never be used.
358 static const GLenum back_buffer_modes
[] = {
359 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
362 /* The 32-bit depth-buffer mode isn't supported yet, so don't actually
365 static const u_int8_t depth_bits_array
[4] = { 0, 16, 24, 32 };
366 static const u_int8_t stencil_bits_array
[4] = { 0, 0, 8, 0 };
367 const unsigned depth_buffer_factor
= 3;
370 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
372 if ( pixel_bits
== 16 ) {
374 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
378 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
381 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
383 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
384 depth_bits_array
, stencil_bits_array
,
386 back_buffer_modes
, back_buffer_factor
,
388 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
389 __func__
, __LINE__
);
393 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
394 depth_bits_array
, stencil_bits_array
,
396 back_buffer_modes
, back_buffer_factor
,
397 GLX_DIRECT_COLOR
) ) {
398 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
399 __func__
, __LINE__
);
408 * This is the driver specific part of the createNewScreen entry point.
410 * \todo maybe fold this into intelInitDriver
412 * \return the __GLcontextModes supported by this driver
414 __GLcontextModes
*__driDriverInitScreen(__DRIscreenPrivate
*psp
)
416 static const __DRIversion ddx_expected
= { VIA_DRIDDX_VERSION_MAJOR
,
417 VIA_DRIDDX_VERSION_MINOR
,
418 VIA_DRIDDX_VERSION_PATCH
};
419 static const __DRIversion dri_expected
= { 4, 0, 0 };
420 static const __DRIversion drm_expected
= { 2, 3, 0 };
421 static const char *driver_name
= "Unichrome";
422 VIADRIPtr dri_priv
= (VIADRIPtr
) psp
->pDevPriv
;
424 if ( ! driCheckDriDdxDrmVersions2( driver_name
,
425 &psp
->dri_version
, & dri_expected
,
426 &psp
->ddx_version
, & ddx_expected
,
427 &psp
->drm_version
, & drm_expected
) )
430 psp
->DriverAPI
= viaAPI
;
432 /* Calling driInitExtensions here, with a NULL context pointer,
433 * does not actually enable the extensions. It just makes sure
434 * that all the dispatch offsets for all the extensions that
435 * *might* be enables are known. This is needed because the
436 * dispatch offsets need to be known when _mesa_context_create is
437 * called, but we can't enable the extensions until we have a
440 * Hello chicken. Hello egg. How are you two today?
442 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
444 if (!viaInitDriver(psp
))
447 return viaFillInModes( dri_priv
->bytesPerPixel
* 8, GL_TRUE
);
453 * Get information about previous buffer swaps.
456 getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
)
458 struct via_context
*vmesa
;
460 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
461 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
462 || (sInfo
== NULL
) ) {
466 vmesa
= (struct via_context
*) dPriv
->driContextPriv
->driverPrivate
;
467 sInfo
->swap_count
= vmesa
->swap_count
;
468 sInfo
->swap_ust
= vmesa
->swap_ust
;
469 sInfo
->swap_missed_count
= vmesa
->swap_missed_count
;
471 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
472 ? driCalculateSwapUsage( dPriv
, 0, vmesa
->swap_missed_ust
)