Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / unichrome / via_screen.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
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:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
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.
23 */
24
25 #include <stdio.h>
26
27 #include "dri_util.h"
28 #include "utils.h"
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"
34 #include "vblank.h"
35
36 #include "via_state.h"
37 #include "via_tex.h"
38 #include "via_span.h"
39 #include "via_screen.h"
40 #include "via_dri.h"
41
42 #include "GL/internal/dri_interface.h"
43 #include "drirenderbuffer.h"
44
45 #include "xmlpool.h"
46
47 PUBLIC const char __driConfigOptions[] =
48 DRI_CONF_BEGIN
49 DRI_CONF_SECTION_PERFORMANCE
50 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
51 DRI_CONF_SECTION_END
52 DRI_CONF_SECTION_QUALITY
53 DRI_CONF_EXCESS_MIPMAP(false)
54 DRI_CONF_SECTION_END
55 DRI_CONF_SECTION_DEBUG
56 DRI_CONF_NO_RAST(false)
57 DRI_CONF_SECTION_END
58 DRI_CONF_END;
59 static const GLuint __driNConfigOptions = 3;
60
61 static drmBufMapPtr via_create_empty_buffers(void)
62 {
63 drmBufMapPtr retval;
64
65 retval = (drmBufMapPtr)MALLOC(sizeof(drmBufMap));
66 if (retval == NULL) return NULL;
67 memset(retval, 0, sizeof(drmBufMap));
68
69 retval->list = (drmBufPtr)MALLOC(sizeof(drmBuf) * VIA_DMA_BUF_NR);
70 if (retval->list == NULL) {
71 FREE(retval);
72 return NULL;
73 }
74 memset(retval->list, 0, sizeof(drmBuf) * VIA_DMA_BUF_NR);
75 return retval;
76 }
77
78 static void via_free_empty_buffers( drmBufMapPtr bufs )
79 {
80 if (bufs && bufs->list)
81 FREE(bufs->list);
82
83 if (bufs)
84 FREE(bufs);
85 }
86
87
88 static GLboolean
89 viaInitDriver(__DRIscreen *sPriv)
90 {
91 viaScreenPrivate *viaScreen;
92 VIADRIPtr gDRIPriv = (VIADRIPtr)sPriv->pDevPriv;
93 int i;
94
95 if (sPriv->devPrivSize != sizeof(VIADRIRec)) {
96 fprintf(stderr,"\nERROR! sizeof(VIADRIRec) does not match passed size from device driver\n");
97 return GL_FALSE;
98 }
99
100 /* Allocate the private area */
101 viaScreen = (viaScreenPrivate *) CALLOC(sizeof(viaScreenPrivate));
102 if (!viaScreen) {
103 __driUtilMessage("viaInitDriver: alloc viaScreenPrivate struct failed");
104 return GL_FALSE;
105 }
106
107 /* parse information in __driConfigOptions */
108 driParseOptionInfo (&viaScreen->optionCache,
109 __driConfigOptions, __driNConfigOptions);
110
111
112 viaScreen->driScrnPriv = sPriv;
113 sPriv->private = (void *)viaScreen;
114
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;
124
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);
131 }
132
133 viaScreen->bufs = via_create_empty_buffers();
134 if (viaScreen->bufs == NULL) {
135 __driUtilMessage("viaInitDriver: via_create_empty_buffers() failed");
136 FREE(viaScreen);
137 return GL_FALSE;
138 }
139
140 if (drmMap(sPriv->fd,
141 gDRIPriv->regs.handle,
142 gDRIPriv->regs.size,
143 &viaScreen->reg) != 0) {
144 FREE(viaScreen);
145 sPriv->private = NULL;
146 __driUtilMessage("viaInitDriver: drmMap regs failed");
147 return GL_FALSE;
148 }
149
150 if (gDRIPriv->agp.size) {
151 if (drmMap(sPriv->fd,
152 gDRIPriv->agp.handle,
153 gDRIPriv->agp.size,
154 (drmAddress *)&viaScreen->agpLinearStart) != 0) {
155 drmUnmap(viaScreen->reg, gDRIPriv->regs.size);
156 FREE(viaScreen);
157 sPriv->private = NULL;
158 __driUtilMessage("viaInitDriver: drmMap agp failed");
159 return GL_FALSE;
160 }
161
162 viaScreen->agpBase = drmAgpBase(sPriv->fd);
163 } else
164 viaScreen->agpLinearStart = 0;
165
166 viaScreen->sareaPrivOffset = gDRIPriv->sarea_priv_offset;
167
168 i = 0;
169 viaScreen->extensions[i++] = &driFrameTrackingExtension.base;
170 viaScreen->extensions[i++] = &driReadDrawableExtension;
171 if ( viaScreen->irqEnabled ) {
172 viaScreen->extensions[i++] = &driSwapControlExtension.base;
173 viaScreen->extensions[i++] = &driMediaStreamCounterExtension.base;
174 }
175
176 viaScreen->extensions[i++] = NULL;
177 sPriv->extensions = viaScreen->extensions;
178
179 return GL_TRUE;
180 }
181
182 static void
183 viaDestroyScreen(__DRIscreen *sPriv)
184 {
185 viaScreenPrivate *viaScreen = (viaScreenPrivate *)sPriv->private;
186 VIADRIPtr gDRIPriv = (VIADRIPtr)sPriv->pDevPriv;
187
188 drmUnmap(viaScreen->reg, gDRIPriv->regs.size);
189 if (gDRIPriv->agp.size)
190 drmUnmap(viaScreen->agpLinearStart, gDRIPriv->agp.size);
191
192 via_free_empty_buffers(viaScreen->bufs);
193
194 driDestroyOptionInfo(&viaScreen->optionCache);
195
196 FREE(viaScreen);
197 sPriv->private = NULL;
198 }
199
200
201 static GLboolean
202 viaCreateBuffer(__DRIscreen *driScrnPriv,
203 __DRIdrawable *driDrawPriv,
204 const __GLcontextModes *mesaVis,
205 GLboolean isPixmap)
206 {
207 #if 0
208 viaScreenPrivate *screen = (viaScreenPrivate *) driScrnPriv->private;
209 #endif
210
211 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
212 mesaVis->depthBits != 24);
213 GLboolean swAccum = mesaVis->accumRedBits > 0;
214
215 if (isPixmap) {
216 /* KW: This needs work, disabled for now:
217 */
218 #if 0
219 driDrawPriv->driverPrivate = (void *)
220 _mesa_create_framebuffer(mesaVis,
221 GL_FALSE, /* software depth buffer? */
222 swStencil,
223 mesaVis->accumRedBits > 0,
224 GL_FALSE /* s/w alpha planes */);
225
226 return (driDrawPriv->driverPrivate != NULL);
227 #endif
228 return GL_FALSE;
229 }
230 else {
231 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
232
233 /* The front color, back color and depth renderbuffers are
234 * set up later in calculate_buffer_parameters().
235 * Only create/connect software-based buffers here.
236 */
237
238 #if 000
239 /* This code _should_ be put to use. We have to move the
240 * viaRenderbuffer members out of the via_context structure.
241 * Those members should just be the renderbuffers hanging off the
242 * gl_framebuffer object.
243 */
244 /* XXX check/fix the offset/pitch parameters! */
245 {
246 driRenderbuffer *frontRb
247 = driNewRenderbuffer(MESA_FORMAT_ARGB8888, NULL,
248 screen->bytesPerPixel,
249 0, screen->width, driDrawPriv);
250 viaSetSpanFunctions(frontRb, mesaVis);
251 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
252 }
253
254 if (mesaVis->doubleBufferMode) {
255 driRenderbuffer *backRb
256 = driNewRenderbuffer(MESA_FORMAT_ARGB8888, NULL,
257 screen->bytesPerPixel,
258 0, screen->width, driDrawPriv);
259 viaSetSpanFunctions(backRb, mesaVis);
260 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
261 }
262
263 if (mesaVis->depthBits == 16) {
264 driRenderbuffer *depthRb
265 = driNewRenderbuffer(MESA_FORMAT_Z16, NULL,
266 screen->bytesPerPixel,
267 0, screen->width, driDrawPriv);
268 viaSetSpanFunctions(depthRb, mesaVis);
269 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
270 }
271 else if (mesaVis->depthBits == 24) {
272 driRenderbuffer *depthRb
273 = driNewRenderbuffer(MESA_FORMAT_Z24_S8, NULL,
274 screen->bytesPerPixel,
275 0, screen->width, driDrawPriv);
276 viaSetSpanFunctions(depthRb, mesaVis);
277 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
278 }
279 else if (mesaVis->depthBits == 32) {
280 driRenderbuffer *depthRb
281 = driNewRenderbuffer(MESA_FORMAT_Z32, NULL,
282 screen->bytesPerPixel,
283 0, screen->width, driDrawPriv);
284 viaSetSpanFunctions(depthRb, mesaVis);
285 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
286 }
287
288 if (mesaVis->stencilBits > 0 && !swStencil) {
289 driRenderbuffer *stencilRb
290 = driNewRenderbuffer(MESA_FORMAT_S8, NULL,
291 screen->bytesPerPixel,
292 0, screen->width, driDrawPriv);
293 viaSetSpanFunctions(stencilRb, mesaVis);
294 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
295 }
296 #endif
297
298 _mesa_add_soft_renderbuffers(fb,
299 GL_FALSE, /* color */
300 GL_FALSE, /* depth */
301 swStencil,
302 swAccum,
303 GL_FALSE, /* alpha */
304 GL_FALSE /* aux */);
305 driDrawPriv->driverPrivate = (void *) fb;
306
307 return (driDrawPriv->driverPrivate != NULL);
308 }
309 }
310
311
312 static void
313 viaDestroyBuffer(__DRIdrawable *driDrawPriv)
314 {
315 _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
316 }
317
318 static const __DRIconfig **
319 viaFillInModes( __DRIscreen *psp,
320 unsigned pixel_bits, GLboolean have_back_buffer )
321 {
322 __DRIconfig **configs;
323 const unsigned back_buffer_factor = (have_back_buffer) ? 2 : 1;
324 GLenum fb_format;
325 GLenum fb_type;
326
327 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
328 * enough to add support. Basically, if a context is created with an
329 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
330 * will never be used.
331 */
332 static const GLenum back_buffer_modes[] = {
333 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
334 };
335
336 /* The 32-bit depth-buffer mode isn't supported yet, so don't actually
337 * enable it.
338 */
339 static const uint8_t depth_bits_array[4] = { 0, 16, 24, 32 };
340 static const uint8_t stencil_bits_array[4] = { 0, 0, 8, 0 };
341 uint8_t msaa_samples_array[1] = { 0 };
342 const unsigned depth_buffer_factor = 3;
343
344 if ( pixel_bits == 16 ) {
345 fb_format = GL_RGB;
346 fb_type = GL_UNSIGNED_SHORT_5_6_5;
347 }
348 else {
349 fb_format = GL_BGRA;
350 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
351 }
352
353 configs = driCreateConfigs(fb_format, fb_type,
354 depth_bits_array, stencil_bits_array,
355 depth_buffer_factor, back_buffer_modes,
356 back_buffer_factor,
357 msaa_samples_array, 1);
358 if (configs == NULL) {
359 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
360 __LINE__);
361 return NULL;
362 }
363
364 return (const __DRIconfig **) configs;
365 }
366
367
368 /**
369 * This is the driver specific part of the createNewScreen entry point.
370 *
371 * \todo maybe fold this into intelInitDriver
372 *
373 * \return the __GLcontextModes supported by this driver
374 */
375 static const __DRIconfig **
376 viaInitScreen(__DRIscreen *psp)
377 {
378 static const __DRIversion ddx_expected = { VIA_DRIDDX_VERSION_MAJOR,
379 VIA_DRIDDX_VERSION_MINOR,
380 VIA_DRIDDX_VERSION_PATCH };
381 static const __DRIversion dri_expected = { 4, 0, 0 };
382 static const __DRIversion drm_expected = { 2, 3, 0 };
383 static const char *driver_name = "Unichrome";
384 VIADRIPtr dri_priv = (VIADRIPtr) psp->pDevPriv;
385
386 if ( ! driCheckDriDdxDrmVersions2( driver_name,
387 &psp->dri_version, & dri_expected,
388 &psp->ddx_version, & ddx_expected,
389 &psp->drm_version, & drm_expected) )
390 return NULL;
391
392 if (!viaInitDriver(psp))
393 return NULL;
394
395 return viaFillInModes( psp, dri_priv->bytesPerPixel * 8, GL_TRUE );
396
397 }
398
399
400 /**
401 * Get information about previous buffer swaps.
402 */
403 static int
404 getSwapInfo( __DRIdrawable *dPriv, __DRIswapInfo * sInfo )
405 {
406 struct via_context *vmesa;
407
408 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
409 || (dPriv->driContextPriv->driverPrivate == NULL)
410 || (sInfo == NULL) ) {
411 return -1;
412 }
413
414 vmesa = (struct via_context *) dPriv->driContextPriv->driverPrivate;
415 sInfo->swap_count = vmesa->swap_count;
416 sInfo->swap_ust = vmesa->swap_ust;
417 sInfo->swap_missed_count = vmesa->swap_missed_count;
418
419 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
420 ? driCalculateSwapUsage( dPriv, 0, vmesa->swap_missed_ust )
421 : 0.0;
422
423 return 0;
424 }
425
426 const struct __DriverAPIRec driDriverAPI = {
427 .InitScreen = viaInitScreen,
428 .DestroyScreen = viaDestroyScreen,
429 .CreateContext = viaCreateContext,
430 .DestroyContext = viaDestroyContext,
431 .CreateBuffer = viaCreateBuffer,
432 .DestroyBuffer = viaDestroyBuffer,
433 .SwapBuffers = viaSwapBuffers,
434 .MakeCurrent = viaMakeCurrent,
435 .UnbindContext = viaUnbindContext,
436 .GetSwapInfo = getSwapInfo,
437 .GetDrawableMSC = driDrawableGetMSC32,
438 .WaitForMSC = driWaitForMSC32,
439 .WaitForSBC = NULL,
440 .SwapBuffersMSC = NULL
441 };
442
443 /* This is the table of extensions that the loader will dlsym() for. */
444 PUBLIC const __DRIextension *__driDriverExtensions[] = {
445 &driCoreExtension.base,
446 &driLegacyExtension.base,
447 NULL
448 };