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>
38 #include "sis_context.h"
44 #include "GL/internal/dri_interface.h"
46 const char __driConfigOptions
[] =
48 DRI_CONF_SECTION_DEBUG
49 DRI_CONF_OPT_BEGIN(agp_disable
,bool,false)
50 DRI_CONF_DESC(en
,"Disable AGP vertex dispatch")
52 DRI_CONF_OPT_BEGIN(fallback_force
,bool,false)
53 DRI_CONF_DESC(en
,"Force software fallback")
57 static const GLuint __driNConfigOptions
= 2;
59 #ifdef USE_NEW_INTERFACE
60 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
61 #endif /* USE_NEW_INTERFACE */
63 #ifdef USE_NEW_INTERFACE
64 static __GLcontextModes
*
65 sisFillInModes(int bpp
)
67 __GLcontextModes
*modes
;
70 unsigned depth_buffer_factor
;
71 unsigned back_buffer_factor
;
74 static const GLenum back_buffer_modes
[] = {
75 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
77 u_int8_t depth_bits_array
[4];
78 u_int8_t stencil_bits_array
[4];
80 depth_bits_array
[0] = 0;
81 stencil_bits_array
[0] = 0;
82 depth_bits_array
[1] = 16;
83 stencil_bits_array
[1] = 0;
84 depth_bits_array
[2] = 24;
85 stencil_bits_array
[2] = 8;
86 depth_bits_array
[3] = 32;
87 stencil_bits_array
[3] = 0;
89 depth_buffer_factor
= 4;
90 back_buffer_factor
= 2;
92 /* Last 4 is for GLX_TRUE_COLOR & GLX_DIRECT_COLOR, with/without accum */
93 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
97 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
100 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
103 modes
= (*create_context_modes
)(num_modes
, sizeof(__GLcontextModes
));
105 if (!driFillInModes(&m
, fb_format
, fb_type
, depth_bits_array
,
106 stencil_bits_array
, depth_buffer_factor
,
107 back_buffer_modes
, back_buffer_factor
,
109 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
, __LINE__
);
113 if (!driFillInModes(&m
, fb_format
, fb_type
, depth_bits_array
,
114 stencil_bits_array
, depth_buffer_factor
,
115 back_buffer_modes
, back_buffer_factor
,
117 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
, __LINE__
);
123 #endif /* USE_NEW_INTERFACE */
125 /* Create the device specific screen private data struct.
128 sisCreateScreen( __DRIscreenPrivate
*sPriv
)
130 sisScreenPtr sisScreen
;
131 SISDRIPtr sisDRIPriv
= (SISDRIPtr
)sPriv
->pDevPriv
;
133 #ifndef USE_NEW_INTERFACE
134 /* XXX Should this still be around for the old interface? */
135 if ( !driCheckDriDdxDrmVersions( sPriv
, "SiS", 4, 0, 0, 1, 1, 0 ) )
139 /* Allocate the private area */
140 sisScreen
= (sisScreenPtr
)CALLOC( sizeof(*sisScreen
) );
141 if ( sisScreen
== NULL
)
144 sisScreen
->screenX
= sisDRIPriv
->width
;
145 sisScreen
->screenY
= sisDRIPriv
->height
;
146 sisScreen
->cpp
= sisDRIPriv
->bytesPerPixel
;
147 sisScreen
->irqEnabled
= sisDRIPriv
->bytesPerPixel
;
148 sisScreen
->deviceID
= sisDRIPriv
->deviceID
;
149 sisScreen
->AGPCmdBufOffset
= sisDRIPriv
->AGPCmdBufOffset
;
150 sisScreen
->AGPCmdBufSize
= sisDRIPriv
->AGPCmdBufSize
;
151 sisScreen
->sarea_priv_offset
= sizeof(drm_sarea_t
);
153 sisScreen
->mmio
.handle
= sisDRIPriv
->regs
.handle
;
154 sisScreen
->mmio
.size
= sisDRIPriv
->regs
.size
;
155 if ( drmMap( sPriv
->fd
, sisScreen
->mmio
.handle
, sisScreen
->mmio
.size
,
156 &sisScreen
->mmio
.map
) )
162 if (sisDRIPriv
->agp
.size
) {
163 sisScreen
->agp
.handle
= sisDRIPriv
->agp
.handle
;
164 sisScreen
->agp
.size
= sisDRIPriv
->agp
.size
;
165 if ( drmMap( sPriv
->fd
, sisScreen
->agp
.handle
, sisScreen
->agp
.size
,
166 &sisScreen
->agp
.map
) )
168 sisScreen
->agp
.size
= 0;
172 sisScreen
->driScreen
= sPriv
;
174 /* parse information in __driConfigOptions */
175 driParseOptionInfo(&sisScreen
->optionCache
,
176 __driConfigOptions
, __driNConfigOptions
);
181 /* Destroy the device specific screen private data struct.
184 sisDestroyScreen( __DRIscreenPrivate
*sPriv
)
186 sisScreenPtr sisScreen
= (sisScreenPtr
)sPriv
->private;
188 if ( sisScreen
== NULL
)
191 if (sisScreen
->agp
.size
!= 0)
192 drmUnmap( sisScreen
->agp
.map
, sisScreen
->agp
.size
);
193 drmUnmap( sisScreen
->mmio
.map
, sisScreen
->mmio
.size
);
196 sPriv
->private = NULL
;
199 /* Create and initialize the Mesa and driver specific pixmap buffer
203 sisCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
204 __DRIdrawablePrivate
*driDrawPriv
,
205 const __GLcontextModes
*mesaVis
,
209 return GL_FALSE
; /* not implemented */
211 driDrawPriv
->driverPrivate
= (void *)_mesa_create_framebuffer(
213 GL_FALSE
, /* software depth buffer? */
214 mesaVis
->stencilBits
> 0,
215 mesaVis
->accumRedBits
> 0,
216 mesaVis
->alphaBits
> 0 ); /* XXX */
217 return (driDrawPriv
->driverPrivate
!= NULL
);
222 sisDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
224 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
227 __inline__
static void
228 sis_bitblt_copy_cmd (sisContextPtr smesa
, ENGPACKET
* pkt
)
230 GLint
*lpdwDest
, *lpdwSrc
;
233 lpdwSrc
= (GLint
*) pkt
;
234 lpdwDest
= (GLint
*) (GET_IOBase (smesa
) + REG_SRC_ADDR
);
236 mWait3DCmdQueue (10);
238 for (i
= 0; i
< 7; i
++)
239 *lpdwDest
++ = *lpdwSrc
++;
241 MMIO(REG_CMD0
, *(GLint
*)&pkt
->stdwCmd
);
242 MMIO(REG_CommandQueue
, -1);
245 static void sisCopyBuffer( __DRIdrawablePrivate
*dPriv
)
247 sisContextPtr smesa
= (sisContextPtr
)dPriv
->driContextPriv
->driverPrivate
;
249 ENGPACKET stEngPacket
;
251 while ((*smesa
->FrameCountPtr
) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH
)
256 stEngPacket
.dwSrcBaseAddr
= smesa
->backOffset
;
257 stEngPacket
.dwSrcPitch
= smesa
->backPitch
|
258 ((smesa
->bytesPerPixel
== 2) ? 0x80000000 : 0xc0000000);
259 stEngPacket
.dwDestBaseAddr
= 0;
260 stEngPacket
.wDestPitch
= smesa
->frontPitch
;
261 /* TODO: set maximum value? */
262 stEngPacket
.wDestHeight
= smesa
->virtualY
;
264 stEngPacket
.stdwCmd
.cRop
= 0xcc;
266 if (smesa
->blockWrite
)
267 stEngPacket
.stdwCmd
.cCmd0
= CMD0_PAT_FG_COLOR
;
269 stEngPacket
.stdwCmd
.cCmd0
= 0;
270 stEngPacket
.stdwCmd
.cCmd1
= CMD1_DIR_X_INC
| CMD1_DIR_Y_INC
;
272 for (i
= 0; i
< dPriv
->numClipRects
; i
++) {
273 drm_clip_rect_t
*box
= &dPriv
->pClipRects
[i
];
274 stEngPacket
.stdwSrcPos
.wY
= box
->y1
- dPriv
->y
;
275 stEngPacket
.stdwSrcPos
.wX
= box
->x1
- dPriv
->x
;
276 stEngPacket
.stdwDestPos
.wY
= box
->y1
;
277 stEngPacket
.stdwDestPos
.wX
= box
->x1
;
279 stEngPacket
.stdwDim
.wWidth
= (GLshort
) box
->x2
- box
->x1
;
280 stEngPacket
.stdwDim
.wHeight
= (GLshort
) box
->y2
- box
->y1
;
281 sis_bitblt_copy_cmd( smesa
, &stEngPacket
);
284 *(GLint
*)(smesa
->IOBase
+0x8a2c) = *smesa
->FrameCountPtr
;
285 (*smesa
->FrameCountPtr
)++;
291 /* Copy the back color buffer to the front color buffer */
293 sisSwapBuffers(__DRIdrawablePrivate
*dPriv
)
295 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
296 sisContextPtr smesa
= (sisContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
297 GLcontext
*ctx
= smesa
->glCtx
;
299 if (ctx
->Visual
.doubleBufferMode
) {
300 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
301 sisCopyBuffer( dPriv
);
304 /* XXX this shouldn't be an error but we can't handle it for now */
305 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
310 /* Initialize the driver specific screen private data.
313 sisInitDriver( __DRIscreenPrivate
*sPriv
)
315 sPriv
->private = (void *) sisCreateScreen( sPriv
);
317 if ( !sPriv
->private ) {
318 sisDestroyScreen( sPriv
);
325 static struct __DriverAPIRec sisAPI
= {
326 .InitDriver
= sisInitDriver
,
327 .DestroyScreen
= sisDestroyScreen
,
328 .CreateContext
= sisCreateContext
,
329 .DestroyContext
= sisDestroyContext
,
330 .CreateBuffer
= sisCreateBuffer
,
331 .DestroyBuffer
= sisDestroyBuffer
,
332 .SwapBuffers
= sisSwapBuffers
,
333 .MakeCurrent
= sisMakeCurrent
,
334 .UnbindContext
= sisUnbindContext
,
339 .SwapBuffersMSC
= NULL
344 * This is the bootstrap function for the driver.
345 * The __driCreateScreen name is the symbol that libGL.so fetches.
346 * Return: pointer to a __DRIscreenPrivate.
348 #if !defined(DRI_NEW_INTERFACE_ONLY)
349 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
350 int numConfigs
, __GLXvisualConfig
*config
)
352 __DRIscreenPrivate
*psp
;
353 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &sisAPI
);
356 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
359 * This is the bootstrap function for the driver. libGL supplies all of the
360 * requisite information about the system, and the driver initializes itself.
361 * This routine also fills in the linked list pointed to by \c driver_modes
362 * with the \c __GLcontextModes that the driver can support for windows or
365 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
368 #ifdef USE_NEW_INTERFACE
369 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
,
371 const __GLcontextModes
*modes
,
372 const __DRIversion
*ddx_version
,
373 const __DRIversion
*dri_version
,
374 const __DRIversion
*drm_version
,
375 const __DRIframebuffer
*frame_buffer
,
376 drmAddress pSAREA
, int fd
,
377 int internal_api_version
,
378 __GLcontextModes
**driver_modes
)
381 __DRIscreenPrivate
*psp
;
382 static const __DRIversion ddx_expected
= {0, 1, 0};
383 static const __DRIversion dri_expected
= {4, 0, 0};
384 static const __DRIversion drm_expected
= {1, 0, 0};
386 if (!driCheckDriDdxDrmVersions2("SiS", dri_version
, &dri_expected
,
387 ddx_version
, &ddx_expected
,
388 drm_version
, &drm_expected
)) {
392 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
393 ddx_version
, dri_version
, drm_version
,
394 frame_buffer
, pSAREA
, fd
,
395 internal_api_version
, &sisAPI
);
397 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
398 glXGetProcAddress((const GLubyte
*)"__glXCreateContextModes");
399 if (create_context_modes
!= NULL
) {
400 SISDRIPtr dri_priv
= (SISDRIPtr
)psp
->pDevPriv
;
401 *driver_modes
= sisFillInModes(dri_priv
->bytesPerPixel
* 8);
407 #endif /* USE_NEW_INTERFACE */