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"
42 /* Create the device specific screen private data struct.
45 sisCreateScreen( __DRIscreenPrivate
*sPriv
)
47 sisScreenPtr sisScreen
;
48 SISDRIPtr sisDRIPriv
= (SISDRIPtr
)sPriv
->pDevPriv
;
50 if ( !driCheckDriDdxDrmVersions( sPriv
, "SiS", 4, 0, 0, 1, 1, 0 ) )
53 /* Allocate the private area */
54 sisScreen
= (sisScreenPtr
)CALLOC( sizeof(*sisScreen
) );
55 if ( sisScreen
== NULL
)
58 sisScreen
->screenX
= sisDRIPriv
->width
;
59 sisScreen
->screenY
= sisDRIPriv
->height
;
60 sisScreen
->cpp
= sisDRIPriv
->bytesPerPixel
;
61 sisScreen
->irqEnabled
= sisDRIPriv
->bytesPerPixel
;
62 sisScreen
->deviceID
= sisDRIPriv
->deviceID
;
63 sisScreen
->AGPCmdBufOffset
= sisDRIPriv
->AGPCmdBufOffset
;
64 sisScreen
->AGPCmdBufSize
= sisDRIPriv
->AGPCmdBufSize
;
65 sisScreen
->sarea_priv_offset
= sizeof(XF86DRISAREARec
);
67 sisScreen
->mmio
.handle
= sisDRIPriv
->regs
.handle
;
68 sisScreen
->mmio
.size
= sisDRIPriv
->regs
.size
;
69 if ( drmMap( sPriv
->fd
, sisScreen
->mmio
.handle
, sisScreen
->mmio
.size
,
70 &sisScreen
->mmio
.map
) )
76 if (sisDRIPriv
->agp
.size
) {
77 sisScreen
->agp
.handle
= sisDRIPriv
->agp
.handle
;
78 sisScreen
->agp
.size
= sisDRIPriv
->agp
.size
;
79 if ( drmMap( sPriv
->fd
, sisScreen
->agp
.handle
, sisScreen
->agp
.size
,
80 &sisScreen
->agp
.map
) )
82 sisScreen
->agp
.size
= 0;
86 sisScreen
->driScreen
= sPriv
;
88 /* parse information in __driConfigOptions */
89 driParseOptionInfo(&sisScreen
->optionCache
);
94 /* Destroy the device specific screen private data struct.
97 sisDestroyScreen( __DRIscreenPrivate
*sPriv
)
99 sisScreenPtr sisScreen
= (sisScreenPtr
)sPriv
->private;
101 if ( sisScreen
== NULL
)
104 if (sisScreen
->agp
.size
!= 0)
105 drmUnmap( sisScreen
->agp
.map
, sisScreen
->agp
.size
);
106 drmUnmap( sisScreen
->mmio
.map
, sisScreen
->mmio
.size
);
109 sPriv
->private = NULL
;
112 /* Create and initialize the Mesa and driver specific pixmap buffer
116 sisCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
117 __DRIdrawablePrivate
*driDrawPriv
,
118 const __GLcontextModes
*mesaVis
,
122 return GL_FALSE
; /* not implemented */
124 driDrawPriv
->driverPrivate
= (void *)_mesa_create_framebuffer(
126 GL_FALSE
, /* software depth buffer? */
127 mesaVis
->stencilBits
> 0,
128 mesaVis
->accumRedBits
> 0,
129 mesaVis
->alphaBits
> 0 ); /* XXX */
130 return (driDrawPriv
->driverPrivate
!= NULL
);
135 sisDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
137 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
140 __inline__
static void
141 sis_bitblt_copy_cmd (sisContextPtr smesa
, ENGPACKET
* pkt
)
143 GLint
*lpdwDest
, *lpdwSrc
;
146 lpdwSrc
= (GLint
*) pkt
;
147 lpdwDest
= (GLint
*) (GET_IOBase (smesa
) + REG_SRC_ADDR
);
149 mWait3DCmdQueue (10);
151 for (i
= 0; i
< 7; i
++)
152 *lpdwDest
++ = *lpdwSrc
++;
154 MMIO(REG_CMD0
, *(GLint
*)&pkt
->stdwCmd
);
155 MMIO(REG_CommandQueue
, -1);
158 static void sisCopyBuffer( __DRIdrawablePrivate
*dPriv
)
160 sisContextPtr smesa
= (sisContextPtr
)dPriv
->driContextPriv
->driverPrivate
;
162 ENGPACKET stEngPacket
;
164 while ((*smesa
->FrameCountPtr
) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH
)
169 stEngPacket
.dwSrcBaseAddr
= smesa
->backOffset
;
170 stEngPacket
.dwSrcPitch
= smesa
->backPitch
|
171 ((smesa
->bytesPerPixel
== 2) ? 0x80000000 : 0xc0000000);
172 stEngPacket
.dwDestBaseAddr
= 0;
173 stEngPacket
.wDestPitch
= smesa
->frontPitch
;
174 /* TODO: set maximum value? */
175 stEngPacket
.wDestHeight
= smesa
->virtualY
;
177 stEngPacket
.stdwCmd
.cRop
= 0xcc;
179 if (smesa
->blockWrite
)
180 stEngPacket
.stdwCmd
.cCmd0
= CMD0_PAT_FG_COLOR
;
182 stEngPacket
.stdwCmd
.cCmd0
= 0;
183 stEngPacket
.stdwCmd
.cCmd1
= CMD1_DIR_X_INC
| CMD1_DIR_Y_INC
;
185 for (i
= 0; i
< dPriv
->numClipRects
; i
++) {
186 XF86DRIClipRectPtr box
= &dPriv
->pClipRects
[i
];
187 stEngPacket
.stdwSrcPos
.wY
= box
->y1
- dPriv
->y
;
188 stEngPacket
.stdwSrcPos
.wX
= box
->x1
- dPriv
->x
;
189 stEngPacket
.stdwDestPos
.wY
= box
->y1
;
190 stEngPacket
.stdwDestPos
.wX
= box
->x1
;
192 stEngPacket
.stdwDim
.wWidth
= (GLshort
) box
->x2
- box
->x1
;
193 stEngPacket
.stdwDim
.wHeight
= (GLshort
) box
->y2
- box
->y1
;
194 sis_bitblt_copy_cmd( smesa
, &stEngPacket
);
197 *(GLint
*)(smesa
->IOBase
+0x8a2c) = *smesa
->FrameCountPtr
;
198 (*smesa
->FrameCountPtr
)++;
204 /* Copy the back color buffer to the front color buffer */
206 sisSwapBuffers(__DRIdrawablePrivate
*dPriv
)
208 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
209 sisContextPtr smesa
= (sisContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
210 GLcontext
*ctx
= smesa
->glCtx
;
212 if (ctx
->Visual
.doubleBufferMode
) {
213 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
214 sisCopyBuffer( dPriv
);
217 /* XXX this shouldn't be an error but we can't handle it for now */
218 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
223 /* Initialize the driver specific screen private data.
226 sisInitDriver( __DRIscreenPrivate
*sPriv
)
228 sPriv
->private = (void *) sisCreateScreen( sPriv
);
230 if ( !sPriv
->private ) {
231 sisDestroyScreen( sPriv
);
238 /* Fullscreen mode change stub
241 sisOpenCloseFullScreen( __DRIcontextPrivate
*driContextPriv
)
246 static struct __DriverAPIRec sisAPI
= {
247 .InitDriver
= sisInitDriver
,
248 .DestroyScreen
= sisDestroyScreen
,
249 .CreateContext
= sisCreateContext
,
250 .DestroyContext
= sisDestroyContext
,
251 .CreateBuffer
= sisCreateBuffer
,
252 .DestroyBuffer
= sisDestroyBuffer
,
253 .SwapBuffers
= sisSwapBuffers
,
254 .MakeCurrent
= sisMakeCurrent
,
255 .UnbindContext
= sisUnbindContext
,
256 .OpenFullScreen
= sisOpenCloseFullScreen
,
257 .CloseFullScreen
= sisOpenCloseFullScreen
,
262 .SwapBuffersMSC
= NULL
267 * This is the bootstrap function for the driver.
268 * The __driCreateScreen name is the symbol that libGL.so fetches.
269 * Return: pointer to a __DRIscreenPrivate.
271 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
272 int numConfigs
, __GLXvisualConfig
*config
)
274 __DRIscreenPrivate
*psp
;
275 psp
= __driUtilCreateScreen( dpy
, scrn
, psc
, numConfigs
, config
, &sisAPI
);