2 /**************************************************************************
4 Copyright 2003 Eric Anholt
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:
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
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.
25 **************************************************************************/
29 * Eric Anholt <anholt@FreeBSD.org>
37 #include "framebuffer.h"
38 #include "renderbuffer.h"
40 #include "sis_context.h"
47 #include "GL/internal/dri_interface.h"
49 PUBLIC
const char __driConfigOptions
[] =
51 DRI_CONF_SECTION_DEBUG
52 DRI_CONF_OPT_BEGIN(agp_disable
,bool,false)
53 DRI_CONF_DESC(en
,"Disable AGP vertex dispatch")
55 DRI_CONF_OPT_BEGIN(fallback_force
,bool,false)
56 DRI_CONF_DESC(en
,"Force software fallback")
60 static const GLuint __driNConfigOptions
= 2;
62 #ifdef USE_NEW_INTERFACE
63 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
64 #endif /* USE_NEW_INTERFACE */
66 #ifdef USE_NEW_INTERFACE
67 static __GLcontextModes
*
68 sisFillInModes(int bpp
)
70 __GLcontextModes
*modes
;
73 unsigned depth_buffer_factor
;
74 unsigned back_buffer_factor
;
77 static const GLenum back_buffer_modes
[] = {
78 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
80 u_int8_t depth_bits_array
[4];
81 u_int8_t stencil_bits_array
[4];
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;
92 depth_buffer_factor
= 4;
93 back_buffer_factor
= 2;
95 /* Last 4 is for GLX_TRUE_COLOR & GLX_DIRECT_COLOR, with/without accum */
96 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
100 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
103 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
106 modes
= (*create_context_modes
)(num_modes
, sizeof(__GLcontextModes
));
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
,
112 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
, __LINE__
);
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
,
120 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
, __LINE__
);
126 #endif /* USE_NEW_INTERFACE */
128 /* Create the device specific screen private data struct.
131 sisCreateScreen( __DRIscreenPrivate
*sPriv
)
133 sisScreenPtr sisScreen
;
134 SISDRIPtr sisDRIPriv
= (SISDRIPtr
)sPriv
->pDevPriv
;
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 ) )
142 /* Allocate the private area */
143 sisScreen
= (sisScreenPtr
)CALLOC( sizeof(*sisScreen
) );
144 if ( sisScreen
== NULL
)
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
);
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
) )
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
) )
171 sisScreen
->agp
.size
= 0;
175 sisScreen
->driScreen
= sPriv
;
177 /* parse information in __driConfigOptions */
178 driParseOptionInfo(&sisScreen
->optionCache
,
179 __driConfigOptions
, __driNConfigOptions
);
184 /* Destroy the device specific screen private data struct.
187 sisDestroyScreen( __DRIscreenPrivate
*sPriv
)
189 sisScreenPtr sisScreen
= (sisScreenPtr
)sPriv
->private;
191 if ( sisScreen
== NULL
)
194 if (sisScreen
->agp
.size
!= 0)
195 drmUnmap( sisScreen
->agp
.map
, sisScreen
->agp
.size
);
196 drmUnmap( sisScreen
->mmio
.map
, sisScreen
->mmio
.size
);
199 sPriv
->private = NULL
;
203 /* Create and initialize the Mesa and driver specific pixmap buffer
207 sisCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
208 __DRIdrawablePrivate
*driDrawPriv
,
209 const __GLcontextModes
*mesaVis
,
212 sisScreenPtr screen
= (sisScreenPtr
) driScrnPriv
->private;
215 return GL_FALSE
; /* not implemented */
218 driDrawPriv
->driverPrivate
= (void *)_mesa_create_framebuffer(
220 GL_FALSE
, /* software depth buffer? */
221 mesaVis
->stencilBits
> 0,
222 mesaVis
->accumRedBits
> 0,
223 mesaVis
->alphaBits
> 0 ); /* XXX */
225 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
227 /* XXX double-check the Offset/Pitch parameters! */
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
);
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
);
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
);
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
);
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
);
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);
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 */
282 driDrawPriv
->driverPrivate
= (void *) fb
;
285 return (driDrawPriv
->driverPrivate
!= NULL
);
290 sisDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
292 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
295 __inline__
static void
296 sis_bitblt_copy_cmd (sisContextPtr smesa
, ENGPACKET
* pkt
)
298 GLint
*lpdwDest
, *lpdwSrc
;
301 lpdwSrc
= (GLint
*) pkt
;
302 lpdwDest
= (GLint
*) (GET_IOBase (smesa
) + REG_SRC_ADDR
);
304 mWait3DCmdQueue (10);
306 for (i
= 0; i
< 7; i
++)
307 *lpdwDest
++ = *lpdwSrc
++;
309 MMIO(REG_CMD0
, *(GLint
*)&pkt
->stdwCmd
);
310 MMIO(REG_CommandQueue
, -1);
313 static void sisCopyBuffer( __DRIdrawablePrivate
*dPriv
)
315 sisContextPtr smesa
= (sisContextPtr
)dPriv
->driContextPriv
->driverPrivate
;
317 ENGPACKET stEngPacket
;
319 memset(&stEngPacket
, 0, sizeof(ENGPACKET
));
321 while ((*smesa
->FrameCountPtr
) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH
)
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
;
334 stEngPacket
.stdwCmd
.cRop
= 0xcc;
336 if (smesa
->blockWrite
)
337 stEngPacket
.stdwCmd
.cCmd0
= CMD0_PAT_FG_COLOR
;
339 stEngPacket
.stdwCmd
.cCmd0
= 0;
340 stEngPacket
.stdwCmd
.cCmd1
= CMD1_DIR_X_INC
| CMD1_DIR_Y_INC
;
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
;
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
);
354 *(GLint
*)(smesa
->IOBase
+0x8a2c) = *smesa
->FrameCountPtr
;
355 (*smesa
->FrameCountPtr
)++;
361 /* Copy the back color buffer to the front color buffer */
363 sisSwapBuffers(__DRIdrawablePrivate
*dPriv
)
365 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
366 sisContextPtr smesa
= (sisContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
367 GLcontext
*ctx
= smesa
->glCtx
;
369 if (ctx
->Visual
.doubleBufferMode
) {
370 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
371 sisCopyBuffer( dPriv
);
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__
);
380 /* Initialize the driver specific screen private data.
383 sisInitDriver( __DRIscreenPrivate
*sPriv
)
385 sPriv
->private = (void *) sisCreateScreen( sPriv
);
387 if ( !sPriv
->private ) {
388 sisDestroyScreen( sPriv
);
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
,
409 .SwapBuffersMSC
= NULL
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.
418 #if !defined(DRI_NEW_INTERFACE_ONLY)
419 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
420 int numConfigs
, __GLXvisualConfig
*config
)
422 __DRIscreenPrivate
*psp
;
423 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &sisAPI
);
426 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
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
435 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
438 #ifdef USE_NEW_INTERFACE
440 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
,
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
)
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};
457 if (!driCheckDriDdxDrmVersions2("SiS", 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
, &sisAPI
);
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);
478 #endif /* USE_NEW_INTERFACE */