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.
29 #include "main/glheader.h"
30 #include "main/context.h"
31 #include "main/framebuffer.h"
32 #include "main/renderbuffer.h"
33 #include "main/simple_list.h"
36 #include "via_state.h"
39 #include "via_screen.h"
42 #include "GL/internal/dri_interface.h"
43 #include "drirenderbuffer.h"
47 PUBLIC
const char __driConfigOptions
[] =
49 DRI_CONF_SECTION_PERFORMANCE
50 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
52 DRI_CONF_SECTION_QUALITY
53 DRI_CONF_EXCESS_MIPMAP(false)
55 DRI_CONF_SECTION_DEBUG
56 DRI_CONF_NO_RAST(false)
59 static const GLuint __driNConfigOptions
= 3;
61 static drmBufMapPtr
via_create_empty_buffers(void)
65 retval
= (drmBufMapPtr
)MALLOC(sizeof(drmBufMap
));
66 if (retval
== NULL
) return NULL
;
67 memset(retval
, 0, sizeof(drmBufMap
));
69 retval
->list
= (drmBufPtr
)MALLOC(sizeof(drmBuf
) * VIA_DMA_BUF_NR
);
70 if (retval
->list
== NULL
) {
74 memset(retval
->list
, 0, sizeof(drmBuf
) * VIA_DMA_BUF_NR
);
78 static void via_free_empty_buffers( drmBufMapPtr bufs
)
80 if (bufs
&& bufs
->list
)
89 viaInitDriver(__DRIscreen
*sPriv
)
91 viaScreenPrivate
*viaScreen
;
92 VIADRIPtr gDRIPriv
= (VIADRIPtr
)sPriv
->pDevPriv
;
95 if (sPriv
->devPrivSize
!= sizeof(VIADRIRec
)) {
96 fprintf(stderr
,"\nERROR! sizeof(VIADRIRec) does not match passed size from device driver\n");
100 /* Allocate the private area */
101 viaScreen
= (viaScreenPrivate
*) CALLOC(sizeof(viaScreenPrivate
));
103 __driUtilMessage("viaInitDriver: alloc viaScreenPrivate struct failed");
107 /* parse information in __driConfigOptions */
108 driParseOptionInfo (&viaScreen
->optionCache
,
109 __driConfigOptions
, __driNConfigOptions
);
112 viaScreen
->driScrnPriv
= sPriv
;
113 sPriv
->private = (void *)viaScreen
;
115 viaScreen
->deviceID
= gDRIPriv
->deviceID
;
116 viaScreen
->width
= gDRIPriv
->width
;
117 viaScreen
->height
= gDRIPriv
->height
;
118 viaScreen
->mem
= gDRIPriv
->mem
;
119 viaScreen
->bitsPerPixel
= gDRIPriv
->bytesPerPixel
* 8;
120 viaScreen
->bytesPerPixel
= gDRIPriv
->bytesPerPixel
;
121 viaScreen
->fbOffset
= 0;
122 viaScreen
->fbSize
= gDRIPriv
->fbSize
;
123 viaScreen
->irqEnabled
= gDRIPriv
->irqEnabled
;
125 if (VIA_DEBUG
& DEBUG_DRI
) {
126 fprintf(stderr
, "deviceID = %08x\n", viaScreen
->deviceID
);
127 fprintf(stderr
, "width = %08x\n", viaScreen
->width
);
128 fprintf(stderr
, "height = %08x\n", viaScreen
->height
);
129 fprintf(stderr
, "cpp = %08x\n", viaScreen
->cpp
);
130 fprintf(stderr
, "fbOffset = %08x\n", viaScreen
->fbOffset
);
133 viaScreen
->bufs
= via_create_empty_buffers();
134 if (viaScreen
->bufs
== NULL
) {
135 __driUtilMessage("viaInitDriver: via_create_empty_buffers() failed");
140 if (drmMap(sPriv
->fd
,
141 gDRIPriv
->regs
.handle
,
143 &viaScreen
->reg
) != 0) {
145 sPriv
->private = NULL
;
146 __driUtilMessage("viaInitDriver: drmMap regs failed");
150 if (gDRIPriv
->agp
.size
) {
151 if (drmMap(sPriv
->fd
,
152 gDRIPriv
->agp
.handle
,
154 (drmAddress
*)&viaScreen
->agpLinearStart
) != 0) {
155 drmUnmap(viaScreen
->reg
, gDRIPriv
->regs
.size
);
157 sPriv
->private = NULL
;
158 __driUtilMessage("viaInitDriver: drmMap agp failed");
162 viaScreen
->agpBase
= drmAgpBase(sPriv
->fd
);
164 viaScreen
->agpLinearStart
= 0;
166 viaScreen
->sareaPrivOffset
= gDRIPriv
->sarea_priv_offset
;
169 viaScreen
->extensions
[i
++] = &driReadDrawableExtension
;
170 if ( viaScreen
->irqEnabled
) {
171 viaScreen
->extensions
[i
++] = &driSwapControlExtension
.base
;
172 viaScreen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
175 viaScreen
->extensions
[i
++] = NULL
;
176 sPriv
->extensions
= viaScreen
->extensions
;
182 viaDestroyScreen(__DRIscreen
*sPriv
)
184 viaScreenPrivate
*viaScreen
= (viaScreenPrivate
*)sPriv
->private;
185 VIADRIPtr gDRIPriv
= (VIADRIPtr
)sPriv
->pDevPriv
;
187 drmUnmap(viaScreen
->reg
, gDRIPriv
->regs
.size
);
188 if (gDRIPriv
->agp
.size
)
189 drmUnmap(viaScreen
->agpLinearStart
, gDRIPriv
->agp
.size
);
191 via_free_empty_buffers(viaScreen
->bufs
);
193 driDestroyOptionInfo(&viaScreen
->optionCache
);
196 sPriv
->private = NULL
;
201 viaCreateBuffer(__DRIscreen
*driScrnPriv
,
202 __DRIdrawable
*driDrawPriv
,
203 const struct gl_config
*mesaVis
,
207 viaScreenPrivate
*screen
= (viaScreenPrivate
*) driScrnPriv
->private;
210 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
211 mesaVis
->depthBits
!= 24);
212 GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
215 /* KW: This needs work, disabled for now:
218 driDrawPriv
->driverPrivate
= (void *)
219 _mesa_create_framebuffer(mesaVis
,
220 GL_FALSE
, /* software depth buffer? */
222 mesaVis
->accumRedBits
> 0,
223 GL_FALSE
/* s/w alpha planes */);
225 return (driDrawPriv
->driverPrivate
!= NULL
);
230 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
232 /* The front color, back color and depth renderbuffers are
233 * set up later in calculate_buffer_parameters().
234 * Only create/connect software-based buffers here.
238 /* This code _should_ be put to use. We have to move the
239 * viaRenderbuffer members out of the via_context structure.
240 * Those members should just be the renderbuffers hanging off the
241 * gl_framebuffer object.
243 /* XXX check/fix the offset/pitch parameters! */
245 driRenderbuffer
*frontRb
246 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
,
247 screen
->bytesPerPixel
,
248 0, screen
->width
, driDrawPriv
);
249 viaSetSpanFunctions(frontRb
, mesaVis
);
250 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
253 if (mesaVis
->doubleBufferMode
) {
254 driRenderbuffer
*backRb
255 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
,
256 screen
->bytesPerPixel
,
257 0, screen
->width
, driDrawPriv
);
258 viaSetSpanFunctions(backRb
, mesaVis
);
259 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
262 if (mesaVis
->depthBits
== 16) {
263 driRenderbuffer
*depthRb
264 = driNewRenderbuffer(MESA_FORMAT_Z16
, NULL
,
265 screen
->bytesPerPixel
,
266 0, screen
->width
, driDrawPriv
);
267 viaSetSpanFunctions(depthRb
, mesaVis
);
268 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
270 else if (mesaVis
->depthBits
== 24) {
271 driRenderbuffer
*depthRb
272 = driNewRenderbuffer(MESA_FORMAT_Z24_S8
, NULL
,
273 screen
->bytesPerPixel
,
274 0, screen
->width
, driDrawPriv
);
275 viaSetSpanFunctions(depthRb
, mesaVis
);
276 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
278 else if (mesaVis
->depthBits
== 32) {
279 driRenderbuffer
*depthRb
280 = driNewRenderbuffer(MESA_FORMAT_Z32
, NULL
,
281 screen
->bytesPerPixel
,
282 0, screen
->width
, driDrawPriv
);
283 viaSetSpanFunctions(depthRb
, mesaVis
);
284 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
287 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
288 driRenderbuffer
*stencilRb
289 = driNewRenderbuffer(MESA_FORMAT_S8
, NULL
,
290 screen
->bytesPerPixel
,
291 0, screen
->width
, driDrawPriv
);
292 viaSetSpanFunctions(stencilRb
, mesaVis
);
293 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
297 _mesa_add_soft_renderbuffers(fb
,
298 GL_FALSE
, /* color */
299 GL_FALSE
, /* depth */
302 GL_FALSE
, /* alpha */
304 driDrawPriv
->driverPrivate
= (void *) fb
;
306 return (driDrawPriv
->driverPrivate
!= NULL
);
312 viaDestroyBuffer(__DRIdrawable
*driDrawPriv
)
314 _mesa_reference_framebuffer((struct gl_framebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
317 static const __DRIconfig
**
318 viaFillInModes( __DRIscreen
*psp
,
319 unsigned pixel_bits
, GLboolean have_back_buffer
)
321 __DRIconfig
**configs
;
322 const unsigned back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
326 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
327 * enough to add support. Basically, if a context is created with an
328 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
329 * will never be used.
331 static const GLenum back_buffer_modes
[] = {
332 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
335 /* The 32-bit depth-buffer mode isn't supported yet, so don't actually
338 static const uint8_t depth_bits_array
[4] = { 0, 16, 24, 32 };
339 static const uint8_t stencil_bits_array
[4] = { 0, 0, 8, 0 };
340 uint8_t msaa_samples_array
[1] = { 0 };
341 const unsigned depth_buffer_factor
= 3;
343 if ( pixel_bits
== 16 ) {
345 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
349 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
352 configs
= driCreateConfigs(fb_format
, fb_type
,
353 depth_bits_array
, stencil_bits_array
,
354 depth_buffer_factor
, back_buffer_modes
,
356 msaa_samples_array
, 1, GL_TRUE
);
357 if (configs
== NULL
) {
358 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
363 return (const __DRIconfig
**) configs
;
368 * This is the driver specific part of the createNewScreen entry point.
370 * \todo maybe fold this into intelInitDriver
372 * \return the struct gl_config supported by this driver
374 static const __DRIconfig
**
375 viaInitScreen(__DRIscreen
*psp
)
377 static const __DRIversion ddx_expected
= { VIA_DRIDDX_VERSION_MAJOR
,
378 VIA_DRIDDX_VERSION_MINOR
,
379 VIA_DRIDDX_VERSION_PATCH
};
380 static const __DRIversion dri_expected
= { 4, 0, 0 };
381 static const __DRIversion drm_expected
= { 2, 3, 0 };
382 static const char *driver_name
= "Unichrome";
383 VIADRIPtr dri_priv
= (VIADRIPtr
) psp
->pDevPriv
;
385 if ( ! driCheckDriDdxDrmVersions2( driver_name
,
386 &psp
->dri_version
, & dri_expected
,
387 &psp
->ddx_version
, & ddx_expected
,
388 &psp
->drm_version
, & drm_expected
) )
391 if (!viaInitDriver(psp
))
394 return viaFillInModes( psp
, dri_priv
->bytesPerPixel
* 8, GL_TRUE
);
400 * Get information about previous buffer swaps.
403 getSwapInfo( __DRIdrawable
*dPriv
, __DRIswapInfo
* sInfo
)
405 struct via_context
*vmesa
;
407 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
408 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
409 || (sInfo
== NULL
) ) {
413 vmesa
= (struct via_context
*) dPriv
->driContextPriv
->driverPrivate
;
414 sInfo
->swap_count
= vmesa
->swap_count
;
415 sInfo
->swap_ust
= vmesa
->swap_ust
;
416 sInfo
->swap_missed_count
= vmesa
->swap_missed_count
;
418 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
419 ? driCalculateSwapUsage( dPriv
, 0, vmesa
->swap_missed_ust
)
425 const struct __DriverAPIRec driDriverAPI
= {
426 .InitScreen
= viaInitScreen
,
427 .DestroyScreen
= viaDestroyScreen
,
428 .CreateContext
= viaCreateContext
,
429 .DestroyContext
= viaDestroyContext
,
430 .CreateBuffer
= viaCreateBuffer
,
431 .DestroyBuffer
= viaDestroyBuffer
,
432 .SwapBuffers
= viaSwapBuffers
,
433 .MakeCurrent
= viaMakeCurrent
,
434 .UnbindContext
= viaUnbindContext
,
435 .GetSwapInfo
= getSwapInfo
,
436 .GetDrawableMSC
= driDrawableGetMSC32
,
437 .WaitForMSC
= driWaitForMSC32
,
439 .SwapBuffersMSC
= NULL
442 /* This is the table of extensions that the loader will dlsym() for. */
443 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
444 &driCoreExtension
.base
,
445 &driLegacyExtension
.base
,