merge latest DRI sis driver changes from the DRI trunk
[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
38 #include "sis_context.h"
39 #include "sis_dri.h"
40 #include "sis_lock.h"
41
42 /* Create the device specific screen private data struct.
43 */
44 static sisScreenPtr
45 sisCreateScreen( __DRIscreenPrivate *sPriv )
46 {
47 sisScreenPtr sisScreen;
48 SISDRIPtr sisDRIPriv = (SISDRIPtr)sPriv->pDevPriv;
49
50 if ( !driCheckDriDdxDrmVersions( sPriv, "SiS", 4, 0, 0, 1, 1, 0 ) )
51 return NULL;
52
53 /* Allocate the private area */
54 sisScreen = (sisScreenPtr)CALLOC( sizeof(*sisScreen) );
55 if ( sisScreen == NULL )
56 return NULL;
57
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);
66
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 ) )
71 {
72 FREE( sisScreen );
73 return NULL;
74 }
75
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 ) )
81 {
82 sisScreen->agp.size = 0;
83 }
84 }
85
86 sisScreen->driScreen = sPriv;
87
88 /* parse information in __driConfigOptions */
89 driParseOptionInfo(&sisScreen->optionCache);
90
91 return sisScreen;
92 }
93
94 /* Destroy the device specific screen private data struct.
95 */
96 static void
97 sisDestroyScreen( __DRIscreenPrivate *sPriv )
98 {
99 sisScreenPtr sisScreen = (sisScreenPtr)sPriv->private;
100
101 if ( sisScreen == NULL )
102 return;
103
104 if (sisScreen->agp.size != 0)
105 drmUnmap( sisScreen->agp.map, sisScreen->agp.size );
106 drmUnmap( sisScreen->mmio.map, sisScreen->mmio.size );
107
108 FREE( sisScreen );
109 sPriv->private = NULL;
110 }
111
112 /* Create and initialize the Mesa and driver specific pixmap buffer
113 * data.
114 */
115 static GLboolean
116 sisCreateBuffer( __DRIscreenPrivate *driScrnPriv,
117 __DRIdrawablePrivate *driDrawPriv,
118 const __GLcontextModes *mesaVis,
119 GLboolean isPixmap )
120 {
121 if (isPixmap)
122 return GL_FALSE; /* not implemented */
123
124 driDrawPriv->driverPrivate = (void *)_mesa_create_framebuffer(
125 mesaVis,
126 GL_FALSE, /* software depth buffer? */
127 mesaVis->stencilBits > 0,
128 mesaVis->accumRedBits > 0,
129 mesaVis->alphaBits > 0 ); /* XXX */
130 return (driDrawPriv->driverPrivate != NULL);
131 }
132
133
134 static void
135 sisDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
136 {
137 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
138 }
139
140 __inline__ static void
141 sis_bitblt_copy_cmd (sisContextPtr smesa, ENGPACKET * pkt)
142 {
143 GLint *lpdwDest, *lpdwSrc;
144 int i;
145
146 lpdwSrc = (GLint *) pkt;
147 lpdwDest = (GLint *) (GET_IOBase (smesa) + REG_SRC_ADDR);
148
149 mWait3DCmdQueue (10);
150
151 for (i = 0; i < 7; i++)
152 *lpdwDest++ = *lpdwSrc++;
153
154 MMIO(REG_CMD0, *(GLint *)&pkt->stdwCmd);
155 MMIO(REG_CommandQueue, -1);
156 }
157
158 static void sisCopyBuffer( __DRIdrawablePrivate *dPriv )
159 {
160 sisContextPtr smesa = (sisContextPtr)dPriv->driContextPriv->driverPrivate;
161 int i;
162 ENGPACKET stEngPacket;
163
164 while ((*smesa->FrameCountPtr) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH)
165 usleep(1);
166
167 LOCK_HARDWARE();
168
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;
176
177 stEngPacket.stdwCmd.cRop = 0xcc;
178
179 if (smesa->blockWrite)
180 stEngPacket.stdwCmd.cCmd0 = CMD0_PAT_FG_COLOR;
181 else
182 stEngPacket.stdwCmd.cCmd0 = 0;
183 stEngPacket.stdwCmd.cCmd1 = CMD1_DIR_X_INC | CMD1_DIR_Y_INC;
184
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;
191
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 );
195 }
196
197 *(GLint *)(smesa->IOBase+0x8a2c) = *smesa->FrameCountPtr;
198 (*smesa->FrameCountPtr)++;
199
200 UNLOCK_HARDWARE ();
201 }
202
203
204 /* Copy the back color buffer to the front color buffer */
205 static void
206 sisSwapBuffers(__DRIdrawablePrivate *dPriv)
207 {
208 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
209 sisContextPtr smesa = (sisContextPtr) dPriv->driContextPriv->driverPrivate;
210 GLcontext *ctx = smesa->glCtx;
211
212 if (ctx->Visual.doubleBufferMode) {
213 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
214 sisCopyBuffer( dPriv );
215 }
216 } else {
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__);
219 }
220 }
221
222
223 /* Initialize the driver specific screen private data.
224 */
225 static GLboolean
226 sisInitDriver( __DRIscreenPrivate *sPriv )
227 {
228 sPriv->private = (void *) sisCreateScreen( sPriv );
229
230 if ( !sPriv->private ) {
231 sisDestroyScreen( sPriv );
232 return GL_FALSE;
233 }
234
235 return GL_TRUE;
236 }
237
238 /* Fullscreen mode change stub
239 */
240 static GLboolean
241 sisOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
242 {
243 return GL_TRUE;
244 }
245
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,
258 .GetSwapInfo = NULL,
259 .GetMSC = NULL,
260 .WaitForMSC = NULL,
261 .WaitForSBC = NULL,
262 .SwapBuffersMSC = NULL
263
264 };
265
266 /*
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.
270 */
271 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
272 int numConfigs, __GLXvisualConfig *config)
273 {
274 __DRIscreenPrivate *psp;
275 psp = __driUtilCreateScreen( dpy, scrn, psc, numConfigs, config, &sisAPI );
276 return (void *)psp;
277 }