Open/Close FullScreen die. unichrome and savage implemented, code is ifdef'd out
[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 #include "xmlpool.h"
43
44 const char __driConfigOptions[] =
45 DRI_CONF_BEGIN
46 DRI_CONF_SECTION_DEBUG
47 DRI_CONF_OPT_BEGIN(agp_disable,bool,false)
48 DRI_CONF_DESC(en,"Disable AGP vertex dispatch")
49 DRI_CONF_OPT_END
50 DRI_CONF_OPT_BEGIN(fallback_force,bool,false)
51 DRI_CONF_DESC(en,"Force software fallback")
52 DRI_CONF_OPT_END
53 DRI_CONF_SECTION_END
54 DRI_CONF_END;
55 static const GLuint __driNConfigOptions = 2;
56
57 /* Create the device specific screen private data struct.
58 */
59 static sisScreenPtr
60 sisCreateScreen( __DRIscreenPrivate *sPriv )
61 {
62 sisScreenPtr sisScreen;
63 SISDRIPtr sisDRIPriv = (SISDRIPtr)sPriv->pDevPriv;
64
65 if ( !driCheckDriDdxDrmVersions( sPriv, "SiS", 4, 0, 0, 1, 1, 0 ) )
66 return NULL;
67
68 /* Allocate the private area */
69 sisScreen = (sisScreenPtr)CALLOC( sizeof(*sisScreen) );
70 if ( sisScreen == NULL )
71 return NULL;
72
73 sisScreen->screenX = sisDRIPriv->width;
74 sisScreen->screenY = sisDRIPriv->height;
75 sisScreen->cpp = sisDRIPriv->bytesPerPixel;
76 sisScreen->irqEnabled = sisDRIPriv->bytesPerPixel;
77 sisScreen->deviceID = sisDRIPriv->deviceID;
78 sisScreen->AGPCmdBufOffset = sisDRIPriv->AGPCmdBufOffset;
79 sisScreen->AGPCmdBufSize = sisDRIPriv->AGPCmdBufSize;
80 sisScreen->sarea_priv_offset = sizeof(drm_sarea_t);
81
82 sisScreen->mmio.handle = sisDRIPriv->regs.handle;
83 sisScreen->mmio.size = sisDRIPriv->regs.size;
84 if ( drmMap( sPriv->fd, sisScreen->mmio.handle, sisScreen->mmio.size,
85 &sisScreen->mmio.map ) )
86 {
87 FREE( sisScreen );
88 return NULL;
89 }
90
91 if (sisDRIPriv->agp.size) {
92 sisScreen->agp.handle = sisDRIPriv->agp.handle;
93 sisScreen->agp.size = sisDRIPriv->agp.size;
94 if ( drmMap( sPriv->fd, sisScreen->agp.handle, sisScreen->agp.size,
95 &sisScreen->agp.map ) )
96 {
97 sisScreen->agp.size = 0;
98 }
99 }
100
101 sisScreen->driScreen = sPriv;
102
103 /* parse information in __driConfigOptions */
104 driParseOptionInfo(&sisScreen->optionCache,
105 __driConfigOptions, __driNConfigOptions);
106
107 return sisScreen;
108 }
109
110 /* Destroy the device specific screen private data struct.
111 */
112 static void
113 sisDestroyScreen( __DRIscreenPrivate *sPriv )
114 {
115 sisScreenPtr sisScreen = (sisScreenPtr)sPriv->private;
116
117 if ( sisScreen == NULL )
118 return;
119
120 if (sisScreen->agp.size != 0)
121 drmUnmap( sisScreen->agp.map, sisScreen->agp.size );
122 drmUnmap( sisScreen->mmio.map, sisScreen->mmio.size );
123
124 FREE( sisScreen );
125 sPriv->private = NULL;
126 }
127
128 /* Create and initialize the Mesa and driver specific pixmap buffer
129 * data.
130 */
131 static GLboolean
132 sisCreateBuffer( __DRIscreenPrivate *driScrnPriv,
133 __DRIdrawablePrivate *driDrawPriv,
134 const __GLcontextModes *mesaVis,
135 GLboolean isPixmap )
136 {
137 if (isPixmap)
138 return GL_FALSE; /* not implemented */
139
140 driDrawPriv->driverPrivate = (void *)_mesa_create_framebuffer(
141 mesaVis,
142 GL_FALSE, /* software depth buffer? */
143 mesaVis->stencilBits > 0,
144 mesaVis->accumRedBits > 0,
145 mesaVis->alphaBits > 0 ); /* XXX */
146 return (driDrawPriv->driverPrivate != NULL);
147 }
148
149
150 static void
151 sisDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
152 {
153 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
154 }
155
156 __inline__ static void
157 sis_bitblt_copy_cmd (sisContextPtr smesa, ENGPACKET * pkt)
158 {
159 GLint *lpdwDest, *lpdwSrc;
160 int i;
161
162 lpdwSrc = (GLint *) pkt;
163 lpdwDest = (GLint *) (GET_IOBase (smesa) + REG_SRC_ADDR);
164
165 mWait3DCmdQueue (10);
166
167 for (i = 0; i < 7; i++)
168 *lpdwDest++ = *lpdwSrc++;
169
170 MMIO(REG_CMD0, *(GLint *)&pkt->stdwCmd);
171 MMIO(REG_CommandQueue, -1);
172 }
173
174 static void sisCopyBuffer( __DRIdrawablePrivate *dPriv )
175 {
176 sisContextPtr smesa = (sisContextPtr)dPriv->driContextPriv->driverPrivate;
177 int i;
178 ENGPACKET stEngPacket;
179
180 while ((*smesa->FrameCountPtr) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH)
181 ;
182
183 LOCK_HARDWARE();
184
185 stEngPacket.dwSrcBaseAddr = smesa->backOffset;
186 stEngPacket.dwSrcPitch = smesa->backPitch |
187 ((smesa->bytesPerPixel == 2) ? 0x80000000 : 0xc0000000);
188 stEngPacket.dwDestBaseAddr = 0;
189 stEngPacket.wDestPitch = smesa->frontPitch;
190 /* TODO: set maximum value? */
191 stEngPacket.wDestHeight = smesa->virtualY;
192
193 stEngPacket.stdwCmd.cRop = 0xcc;
194
195 if (smesa->blockWrite)
196 stEngPacket.stdwCmd.cCmd0 = CMD0_PAT_FG_COLOR;
197 else
198 stEngPacket.stdwCmd.cCmd0 = 0;
199 stEngPacket.stdwCmd.cCmd1 = CMD1_DIR_X_INC | CMD1_DIR_Y_INC;
200
201 for (i = 0; i < dPriv->numClipRects; i++) {
202 drm_clip_rect_t *box = &dPriv->pClipRects[i];
203 stEngPacket.stdwSrcPos.wY = box->y1 - dPriv->y;
204 stEngPacket.stdwSrcPos.wX = box->x1 - dPriv->x;
205 stEngPacket.stdwDestPos.wY = box->y1;
206 stEngPacket.stdwDestPos.wX = box->x1;
207
208 stEngPacket.stdwDim.wWidth = (GLshort) box->x2 - box->x1;
209 stEngPacket.stdwDim.wHeight = (GLshort) box->y2 - box->y1;
210 sis_bitblt_copy_cmd( smesa, &stEngPacket );
211 }
212
213 *(GLint *)(smesa->IOBase+0x8a2c) = *smesa->FrameCountPtr;
214 (*smesa->FrameCountPtr)++;
215
216 UNLOCK_HARDWARE ();
217 }
218
219
220 /* Copy the back color buffer to the front color buffer */
221 static void
222 sisSwapBuffers(__DRIdrawablePrivate *dPriv)
223 {
224 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
225 sisContextPtr smesa = (sisContextPtr) dPriv->driContextPriv->driverPrivate;
226 GLcontext *ctx = smesa->glCtx;
227
228 if (ctx->Visual.doubleBufferMode) {
229 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
230 sisCopyBuffer( dPriv );
231 }
232 } else {
233 /* XXX this shouldn't be an error but we can't handle it for now */
234 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
235 }
236 }
237
238
239 /* Initialize the driver specific screen private data.
240 */
241 static GLboolean
242 sisInitDriver( __DRIscreenPrivate *sPriv )
243 {
244 sPriv->private = (void *) sisCreateScreen( sPriv );
245
246 if ( !sPriv->private ) {
247 sisDestroyScreen( sPriv );
248 return GL_FALSE;
249 }
250
251 return GL_TRUE;
252 }
253
254 static struct __DriverAPIRec sisAPI = {
255 .InitDriver = sisInitDriver,
256 .DestroyScreen = sisDestroyScreen,
257 .CreateContext = sisCreateContext,
258 .DestroyContext = sisDestroyContext,
259 .CreateBuffer = sisCreateBuffer,
260 .DestroyBuffer = sisDestroyBuffer,
261 .SwapBuffers = sisSwapBuffers,
262 .MakeCurrent = sisMakeCurrent,
263 .UnbindContext = sisUnbindContext,
264 .GetSwapInfo = NULL,
265 .GetMSC = NULL,
266 .WaitForMSC = NULL,
267 .WaitForSBC = NULL,
268 .SwapBuffersMSC = NULL
269
270 };
271
272 /*
273 * This is the bootstrap function for the driver.
274 * The __driCreateScreen name is the symbol that libGL.so fetches.
275 * Return: pointer to a __DRIscreenPrivate.
276 */
277 #ifndef _SOLO
278 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
279 int numConfigs, __GLXvisualConfig *config)
280 {
281 __DRIscreenPrivate *psp;
282 psp = __driUtilCreateScreen( dpy, scrn, psc, numConfigs, config, &sisAPI );
283 return (void *)psp;
284 }
285 #else
286 void *__driCreateScreen(struct DRIDriverRec *driver,
287 struct DRIDriverContextRec *driverContext)
288 {
289 __DRIscreenPrivate *psp;
290 psp = __driUtilCreateScreen(driver, driverContext, &sisAPI);
291 return (void *) psp;
292 }
293 #endif