Zero out the ENGPACKET allocated on the stack, to avoid sending uninitialized
[mesa.git] / src / mesa / drivers / dri / sis / sis_screen.c
1 /* $XFree86$ */
2 /**************************************************************************
3
4 Copyright 2003 Eric Anholt
5 All Rights Reserved.
6
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 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
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
16 Software.
17
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 NON-INFRINGEMENT. IN NO EVENT SHALL
21 ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 **************************************************************************/
26
27 /*
28 * Authors:
29 * Eric Anholt <anholt@FreeBSD.org>
30 */
31
32 #include "dri_util.h"
33
34 #include "context.h"
35 #include "utils.h"
36 #include "imports.h"
37 #include "framebuffer.h"
38 #include "renderbuffer.h"
39
40 #include "sis_context.h"
41 #include "sis_dri.h"
42 #include "sis_lock.h"
43 #include "sis_span.h"
44
45 #include "xmlpool.h"
46
47 #include "GL/internal/dri_interface.h"
48
49 PUBLIC const char __driConfigOptions[] =
50 DRI_CONF_BEGIN
51 DRI_CONF_SECTION_DEBUG
52 DRI_CONF_OPT_BEGIN(agp_disable,bool,false)
53 DRI_CONF_DESC(en,"Disable AGP vertex dispatch")
54 DRI_CONF_OPT_END
55 DRI_CONF_OPT_BEGIN(fallback_force,bool,false)
56 DRI_CONF_DESC(en,"Force software fallback")
57 DRI_CONF_OPT_END
58 DRI_CONF_SECTION_END
59 DRI_CONF_END;
60 static const GLuint __driNConfigOptions = 2;
61
62 #ifdef USE_NEW_INTERFACE
63 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
64 #endif /* USE_NEW_INTERFACE */
65
66 #ifdef USE_NEW_INTERFACE
67 static __GLcontextModes *
68 sisFillInModes(int bpp)
69 {
70 __GLcontextModes *modes;
71 __GLcontextModes *m;
72 unsigned num_modes;
73 unsigned depth_buffer_factor;
74 unsigned back_buffer_factor;
75 GLenum fb_format;
76 GLenum fb_type;
77 static const GLenum back_buffer_modes[] = {
78 GLX_NONE, GLX_SWAP_UNDEFINED_OML
79 };
80 u_int8_t depth_bits_array[4];
81 u_int8_t stencil_bits_array[4];
82
83 depth_bits_array[0] = 0;
84 stencil_bits_array[0] = 0;
85 depth_bits_array[1] = 16;
86 stencil_bits_array[1] = 0;
87 depth_bits_array[2] = 24;
88 stencil_bits_array[2] = 8;
89 depth_bits_array[3] = 32;
90 stencil_bits_array[3] = 0;
91
92 depth_buffer_factor = 4;
93 back_buffer_factor = 2;
94
95 /* Last 4 is for GLX_TRUE_COLOR & GLX_DIRECT_COLOR, with/without accum */
96 num_modes = depth_buffer_factor * back_buffer_factor * 4;
97
98 if (bpp == 16) {
99 fb_format = GL_RGB;
100 fb_type = GL_UNSIGNED_SHORT_5_6_5;
101 } else {
102 fb_format = GL_BGRA;
103 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
104 }
105
106 modes = (*create_context_modes)(num_modes, sizeof(__GLcontextModes));
107 m = modes;
108 if (!driFillInModes(&m, fb_format, fb_type, depth_bits_array,
109 stencil_bits_array, depth_buffer_factor,
110 back_buffer_modes, back_buffer_factor,
111 GLX_TRUE_COLOR)) {
112 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, __LINE__);
113 return NULL;
114 }
115
116 if (!driFillInModes(&m, fb_format, fb_type, depth_bits_array,
117 stencil_bits_array, depth_buffer_factor,
118 back_buffer_modes, back_buffer_factor,
119 GLX_DIRECT_COLOR)) {
120 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, __LINE__);
121 return NULL;
122 }
123
124 return modes;
125 }
126 #endif /* USE_NEW_INTERFACE */
127
128 /* Create the device specific screen private data struct.
129 */
130 static sisScreenPtr
131 sisCreateScreen( __DRIscreenPrivate *sPriv )
132 {
133 sisScreenPtr sisScreen;
134 SISDRIPtr sisDRIPriv = (SISDRIPtr)sPriv->pDevPriv;
135
136 #ifndef USE_NEW_INTERFACE
137 /* XXX Should this still be around for the old interface? */
138 if ( !driCheckDriDdxDrmVersions( sPriv, "SiS", 4, 0, 0, 1, 1, 0 ) )
139 return NULL;
140 #endif
141
142 /* Allocate the private area */
143 sisScreen = (sisScreenPtr)CALLOC( sizeof(*sisScreen) );
144 if ( sisScreen == NULL )
145 return NULL;
146
147 sisScreen->screenX = sisDRIPriv->width;
148 sisScreen->screenY = sisDRIPriv->height;
149 sisScreen->cpp = sisDRIPriv->bytesPerPixel;
150 sisScreen->irqEnabled = sisDRIPriv->bytesPerPixel;
151 sisScreen->deviceID = sisDRIPriv->deviceID;
152 sisScreen->AGPCmdBufOffset = sisDRIPriv->AGPCmdBufOffset;
153 sisScreen->AGPCmdBufSize = sisDRIPriv->AGPCmdBufSize;
154 sisScreen->sarea_priv_offset = sizeof(drm_sarea_t);
155
156 sisScreen->mmio.handle = sisDRIPriv->regs.handle;
157 sisScreen->mmio.size = sisDRIPriv->regs.size;
158 if ( drmMap( sPriv->fd, sisScreen->mmio.handle, sisScreen->mmio.size,
159 &sisScreen->mmio.map ) )
160 {
161 FREE( sisScreen );
162 return NULL;
163 }
164
165 if (sisDRIPriv->agp.size) {
166 sisScreen->agp.handle = sisDRIPriv->agp.handle;
167 sisScreen->agp.size = sisDRIPriv->agp.size;
168 if ( drmMap( sPriv->fd, sisScreen->agp.handle, sisScreen->agp.size,
169 &sisScreen->agp.map ) )
170 {
171 sisScreen->agp.size = 0;
172 }
173 }
174
175 sisScreen->driScreen = sPriv;
176
177 /* parse information in __driConfigOptions */
178 driParseOptionInfo(&sisScreen->optionCache,
179 __driConfigOptions, __driNConfigOptions);
180
181 return sisScreen;
182 }
183
184 /* Destroy the device specific screen private data struct.
185 */
186 static void
187 sisDestroyScreen( __DRIscreenPrivate *sPriv )
188 {
189 sisScreenPtr sisScreen = (sisScreenPtr)sPriv->private;
190
191 if ( sisScreen == NULL )
192 return;
193
194 if (sisScreen->agp.size != 0)
195 drmUnmap( sisScreen->agp.map, sisScreen->agp.size );
196 drmUnmap( sisScreen->mmio.map, sisScreen->mmio.size );
197
198 FREE( sisScreen );
199 sPriv->private = NULL;
200 }
201
202
203 /* Create and initialize the Mesa and driver specific pixmap buffer
204 * data.
205 */
206 static GLboolean
207 sisCreateBuffer( __DRIscreenPrivate *driScrnPriv,
208 __DRIdrawablePrivate *driDrawPriv,
209 const __GLcontextModes *mesaVis,
210 GLboolean isPixmap )
211 {
212 sisScreenPtr screen = (sisScreenPtr) driScrnPriv->private;
213
214 if (isPixmap)
215 return GL_FALSE; /* not implemented */
216
217 #if 0
218 driDrawPriv->driverPrivate = (void *)_mesa_create_framebuffer(
219 mesaVis,
220 GL_FALSE, /* software depth buffer? */
221 mesaVis->stencilBits > 0,
222 mesaVis->accumRedBits > 0,
223 mesaVis->alphaBits > 0 ); /* XXX */
224 #else
225 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
226
227 /* XXX double-check the Offset/Pitch parameters! */
228 {
229 driRenderbuffer *frontRb
230 = driNewRenderbuffer(GL_RGBA, screen->cpp,
231 0, driScrnPriv->fbStride);
232 sisSetSpanFunctions(frontRb, mesaVis);
233 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
234 }
235
236 if (mesaVis->doubleBufferMode) {
237 driRenderbuffer *backRb
238 = driNewRenderbuffer(GL_RGBA, screen->cpp,
239 0, driScrnPriv->fbStride);
240 sisSetSpanFunctions(backRb, mesaVis);
241 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
242 }
243
244 if (mesaVis->depthBits == 16) {
245 driRenderbuffer *depthRb
246 = driNewRenderbuffer(GL_DEPTH_COMPONENT16, screen->cpp,
247 0, driScrnPriv->fbStride);
248 sisSetSpanFunctions(depthRb, mesaVis);
249 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
250 }
251 else if (mesaVis->depthBits == 24) {
252 driRenderbuffer *depthRb
253 = driNewRenderbuffer(GL_DEPTH_COMPONENT24, screen->cpp,
254 0, driScrnPriv->fbStride);
255 sisSetSpanFunctions(depthRb, mesaVis);
256 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
257 }
258 else if (mesaVis->depthBits == 32) {
259 driRenderbuffer *depthRb
260 = driNewRenderbuffer(GL_DEPTH_COMPONENT32, screen->cpp,
261 0, driScrnPriv->fbStride);
262 sisSetSpanFunctions(depthRb, mesaVis);
263 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
264 }
265
266 /* no h/w stencil?
267 if (mesaVis->stencilBits > 0) {
268 driRenderbuffer *stencilRb
269 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT);
270 sisSetSpanFunctions(stencilRb, mesaVis);
271 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
272 }
273 */
274
275 _mesa_add_soft_renderbuffers(fb,
276 GL_FALSE, /* color */
277 GL_FALSE, /* depth */
278 mesaVis->stencilBits > 0,
279 mesaVis->accumRedBits > 0,
280 GL_FALSE, /* alpha */
281 GL_FALSE /* aux */);
282 driDrawPriv->driverPrivate = (void *) fb;
283 #endif
284
285 return (driDrawPriv->driverPrivate != NULL);
286 }
287
288
289 static void
290 sisDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
291 {
292 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
293 }
294
295 __inline__ static void
296 sis_bitblt_copy_cmd (sisContextPtr smesa, ENGPACKET * pkt)
297 {
298 GLint *lpdwDest, *lpdwSrc;
299 int i;
300
301 lpdwSrc = (GLint *) pkt;
302 lpdwDest = (GLint *) (GET_IOBase (smesa) + REG_SRC_ADDR);
303
304 mWait3DCmdQueue (10);
305
306 for (i = 0; i < 7; i++)
307 *lpdwDest++ = *lpdwSrc++;
308
309 MMIO(REG_CMD0, *(GLint *)&pkt->stdwCmd);
310 MMIO(REG_CommandQueue, -1);
311 }
312
313 static void sisCopyBuffer( __DRIdrawablePrivate *dPriv )
314 {
315 sisContextPtr smesa = (sisContextPtr)dPriv->driContextPriv->driverPrivate;
316 int i;
317 ENGPACKET stEngPacket;
318
319 memset(&stEngPacket, 0, sizeof(ENGPACKET));
320
321 while ((*smesa->FrameCountPtr) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH)
322 ;
323
324 LOCK_HARDWARE();
325
326 stEngPacket.dwSrcBaseAddr = smesa->backOffset;
327 stEngPacket.dwSrcPitch = smesa->backPitch |
328 ((smesa->bytesPerPixel == 2) ? 0x80000000 : 0xc0000000);
329 stEngPacket.dwDestBaseAddr = 0;
330 stEngPacket.wDestPitch = smesa->frontPitch;
331 /* TODO: set maximum value? */
332 stEngPacket.wDestHeight = smesa->virtualY;
333
334 stEngPacket.stdwCmd.cRop = 0xcc;
335
336 if (smesa->blockWrite)
337 stEngPacket.stdwCmd.cCmd0 = CMD0_PAT_FG_COLOR;
338 else
339 stEngPacket.stdwCmd.cCmd0 = 0;
340 stEngPacket.stdwCmd.cCmd1 = CMD1_DIR_X_INC | CMD1_DIR_Y_INC;
341
342 for (i = 0; i < dPriv->numClipRects; i++) {
343 drm_clip_rect_t *box = &dPriv->pClipRects[i];
344 stEngPacket.stdwSrcPos.wY = box->y1 - dPriv->y;
345 stEngPacket.stdwSrcPos.wX = box->x1 - dPriv->x;
346 stEngPacket.stdwDestPos.wY = box->y1;
347 stEngPacket.stdwDestPos.wX = box->x1;
348
349 stEngPacket.stdwDim.wWidth = (GLshort) box->x2 - box->x1;
350 stEngPacket.stdwDim.wHeight = (GLshort) box->y2 - box->y1;
351 sis_bitblt_copy_cmd( smesa, &stEngPacket );
352 }
353
354 *(GLint *)(smesa->IOBase+0x8a2c) = *smesa->FrameCountPtr;
355 (*smesa->FrameCountPtr)++;
356
357 UNLOCK_HARDWARE ();
358 }
359
360
361 /* Copy the back color buffer to the front color buffer */
362 static void
363 sisSwapBuffers(__DRIdrawablePrivate *dPriv)
364 {
365 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
366 sisContextPtr smesa = (sisContextPtr) dPriv->driContextPriv->driverPrivate;
367 GLcontext *ctx = smesa->glCtx;
368
369 if (ctx->Visual.doubleBufferMode) {
370 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
371 sisCopyBuffer( dPriv );
372 }
373 } else {
374 /* XXX this shouldn't be an error but we can't handle it for now */
375 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
376 }
377 }
378
379
380 /* Initialize the driver specific screen private data.
381 */
382 static GLboolean
383 sisInitDriver( __DRIscreenPrivate *sPriv )
384 {
385 sPriv->private = (void *) sisCreateScreen( sPriv );
386
387 if ( !sPriv->private ) {
388 sisDestroyScreen( sPriv );
389 return GL_FALSE;
390 }
391
392 return GL_TRUE;
393 }
394
395 static struct __DriverAPIRec sisAPI = {
396 .InitDriver = sisInitDriver,
397 .DestroyScreen = sisDestroyScreen,
398 .CreateContext = sisCreateContext,
399 .DestroyContext = sisDestroyContext,
400 .CreateBuffer = sisCreateBuffer,
401 .DestroyBuffer = sisDestroyBuffer,
402 .SwapBuffers = sisSwapBuffers,
403 .MakeCurrent = sisMakeCurrent,
404 .UnbindContext = sisUnbindContext,
405 .GetSwapInfo = NULL,
406 .GetMSC = NULL,
407 .WaitForMSC = NULL,
408 .WaitForSBC = NULL,
409 .SwapBuffersMSC = NULL
410
411 };
412
413 /*
414 * This is the bootstrap function for the driver.
415 * The __driCreateScreen name is the symbol that libGL.so fetches.
416 * Return: pointer to a __DRIscreenPrivate.
417 */
418 #if !defined(DRI_NEW_INTERFACE_ONLY)
419 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
420 int numConfigs, __GLXvisualConfig *config)
421 {
422 __DRIscreenPrivate *psp;
423 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &sisAPI);
424 return (void *)psp;
425 }
426 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
427
428 /**
429 * This is the bootstrap function for the driver. libGL supplies all of the
430 * requisite information about the system, and the driver initializes itself.
431 * This routine also fills in the linked list pointed to by \c driver_modes
432 * with the \c __GLcontextModes that the driver can support for windows or
433 * pbuffers.
434 *
435 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
436 * failure.
437 */
438 #ifdef USE_NEW_INTERFACE
439 PUBLIC
440 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn,
441 __DRIscreen *psc,
442 const __GLcontextModes *modes,
443 const __DRIversion *ddx_version,
444 const __DRIversion *dri_version,
445 const __DRIversion *drm_version,
446 const __DRIframebuffer *frame_buffer,
447 drmAddress pSAREA, int fd,
448 int internal_api_version,
449 __GLcontextModes **driver_modes )
450
451 {
452 __DRIscreenPrivate *psp;
453 static const __DRIversion ddx_expected = {0, 1, 0};
454 static const __DRIversion dri_expected = {4, 0, 0};
455 static const __DRIversion drm_expected = {1, 0, 0};
456
457 if (!driCheckDriDdxDrmVersions2("SiS", dri_version, &dri_expected,
458 ddx_version, &ddx_expected,
459 drm_version, &drm_expected)) {
460 return NULL;
461 }
462
463 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
464 ddx_version, dri_version, drm_version,
465 frame_buffer, pSAREA, fd,
466 internal_api_version, &sisAPI);
467 if (psp != NULL) {
468 create_context_modes = (PFNGLXCREATECONTEXTMODES)
469 glXGetProcAddress((const GLubyte *)"__glXCreateContextModes");
470 if (create_context_modes != NULL) {
471 SISDRIPtr dri_priv = (SISDRIPtr)psp->pDevPriv;
472 *driver_modes = sisFillInModes(dri_priv->bytesPerPixel * 8);
473 }
474 }
475
476 return (void *)psp;
477 }
478 #endif /* USE_NEW_INTERFACE */