a095b28add1b280d98981a2237eef34d3267d395
[mesa.git] / src / mesa / drivers / dri / i810 / i810screen.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810screen.c,v 1.2 2002/10/30 12:51:33 alanh Exp $ */
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 *
33 */
34
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "context.h"
39 #include "matrix.h"
40 #include "simple_list.h"
41 #include "utils.h"
42
43 #include "i810screen.h"
44 #include "i810_dri.h"
45
46 #include "i810state.h"
47 #include "i810tex.h"
48 #include "i810span.h"
49 #include "i810tris.h"
50 #include "i810ioctl.h"
51
52 #ifndef _SOLO
53 #include "glxextensions.h"
54 #endif
55
56 #ifdef USE_NEW_INTERFACE
57 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
58 #endif /* USE_NEW_INTERFACE */
59
60 #ifdef USE_NEW_INTERFACE
61 static __GLcontextModes *fill_in_modes( __GLcontextModes *modes,
62 unsigned pixel_bits,
63 unsigned depth_bits,
64 unsigned stencil_bits,
65 const GLenum * db_modes,
66 unsigned num_db_modes,
67 int visType )
68 {
69 static const uint8_t bits[1][4] = {
70 { 5, 6, 5, 0 }
71 };
72
73 static const uint32_t masks[1][4] = {
74 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
75 };
76
77 unsigned i;
78 unsigned j;
79 const unsigned index = 0;
80
81 for ( i = 0 ; i < num_db_modes ; i++ ) {
82 for ( j = 0 ; j < 2 ; j++ ) {
83
84 modes->redBits = bits[index][0];
85 modes->greenBits = bits[index][1];
86 modes->blueBits = bits[index][2];
87 modes->alphaBits = bits[index][3];
88 modes->redMask = masks[index][0];
89 modes->greenMask = masks[index][1];
90 modes->blueMask = masks[index][2];
91 modes->alphaMask = masks[index][3];
92 modes->rgbBits = modes->redBits + modes->greenBits
93 + modes->blueBits + modes->alphaBits;
94
95 modes->accumRedBits = 16 * j;
96 modes->accumGreenBits = 16 * j;
97 modes->accumBlueBits = 16 * j;
98 modes->accumAlphaBits = (masks[index][3] != 0) ? 16 * j : 0;
99 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
100
101 modes->stencilBits = stencil_bits;
102 modes->depthBits = depth_bits;
103
104 modes->visualType = visType;
105 modes->renderType = GLX_RGBA_BIT;
106 modes->drawableType = GLX_WINDOW_BIT;
107 modes->rgbMode = GL_TRUE;
108
109 if ( db_modes[i] == GLX_NONE ) {
110 modes->doubleBufferMode = GL_FALSE;
111 }
112 else {
113 modes->doubleBufferMode = GL_TRUE;
114 modes->swapMethod = db_modes[i];
115 }
116
117 modes = modes->next;
118 }
119 }
120
121 return modes;
122
123 }
124 #endif /* USE_NEW_INTERFACE */
125
126 #ifdef USE_NEW_INTERFACE
127 static __GLcontextModes *
128 i810FillInModes( unsigned pixel_bits, unsigned depth_bits,
129 unsigned stencil_bits, GLboolean have_back_buffer )
130 { __GLcontextModes * modes;
131 __GLcontextModes * m;
132 unsigned num_modes;
133 unsigned depth_buffer_factor;
134 unsigned back_buffer_factor;
135 unsigned i;
136
137 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
138 * enough to add support. Basically, if a context is created with an
139 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
140 * will never be used.
141 */
142 static const GLenum back_buffer_modes[] = {
143 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
144 };
145
146 int depth_buffer_modes[2][2];
147
148
149 depth_buffer_modes[0][0] = depth_bits;
150 depth_buffer_modes[1][0] = depth_bits;
151
152 /* Just like with the accumulation buffer, always provide some modes
153 * with a stencil buffer. It will be a sw fallback, but some apps won't
154 * care about that.
155 */
156 depth_buffer_modes[0][1] = 0;
157 depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
158
159 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
160 back_buffer_factor = (have_back_buffer) ? 2 : 1;
161
162 num_modes = depth_buffer_factor * back_buffer_factor * 4;
163
164 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
165 m = modes;
166 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
167 m = fill_in_modes( m, pixel_bits,
168 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
169 back_buffer_modes, back_buffer_factor,
170 GLX_TRUE_COLOR );
171 }
172
173 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
174 m = fill_in_modes( m, pixel_bits,
175 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
176 back_buffer_modes, back_buffer_factor,
177 GLX_DIRECT_COLOR );
178 }
179
180 /* Mark the visual as slow if there are "fake" stencil bits.
181 */
182 for ( m = modes ; m != NULL ; m = m->next ) {
183 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
184 m->visualRating = GLX_SLOW_CONFIG;
185 }
186 }
187
188 return modes;
189
190 }
191 #endif /* USE_NEW_INTERFACE */
192
193
194
195 /* static int i810_malloc_proxy_buf(drmBufMapPtr buffers) */
196 /* { */
197 /* char *buffer; */
198 /* drmBufPtr buf; */
199 /* int i; */
200
201 /* buffer = CALLOC(I810_DMA_BUF_SZ); */
202 /* if(buffer == NULL) return -1; */
203 /* for(i = 0; i < I810_DMA_BUF_NR; i++) { */
204 /* buf = &(buffers->list[i]); */
205 /* buf->address = (drmAddress)buffer; */
206 /* } */
207 /* return 0; */
208 /* } */
209
210 static drmBufMapPtr i810_create_empty_buffers(void)
211 {
212 drmBufMapPtr retval;
213
214 retval = (drmBufMapPtr)ALIGN_MALLOC(sizeof(drmBufMap), 32);
215 if(retval == NULL) return NULL;
216 memset(retval, 0, sizeof(drmBufMap));
217 retval->list = (drmBufPtr)ALIGN_MALLOC(sizeof(drmBuf) * I810_DMA_BUF_NR, 32);
218 if(retval->list == NULL) {
219 ALIGN_FREE(retval);
220 return NULL;
221 }
222 memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
223 return retval;
224 }
225
226
227 static GLboolean
228 i810InitDriver(__DRIscreenPrivate *sPriv)
229 {
230 i810ScreenPrivate *i810Screen;
231 I810DRIPtr gDRIPriv = (I810DRIPtr)sPriv->pDevPriv;
232
233 if ( ! driCheckDriDdxDrmVersions( sPriv, "i810", 4, 0, 1, 0, 1, 2 ) )
234 return GL_FALSE;
235
236 /* Allocate the private area */
237 i810Screen = (i810ScreenPrivate *)CALLOC(sizeof(i810ScreenPrivate));
238 if (!i810Screen) {
239 __driUtilMessage("i810InitDriver: alloc i810ScreenPrivate struct failed");
240 return GL_FALSE;
241 }
242
243 i810Screen->driScrnPriv = sPriv;
244 sPriv->private = (void *)i810Screen;
245
246 i810Screen->deviceID=gDRIPriv->deviceID;
247 i810Screen->width=gDRIPriv->width;
248 i810Screen->height=gDRIPriv->height;
249 i810Screen->mem=gDRIPriv->mem;
250 i810Screen->cpp=gDRIPriv->cpp;
251 i810Screen->fbStride=gDRIPriv->fbStride;
252 i810Screen->fbOffset=gDRIPriv->fbOffset;
253
254 if (gDRIPriv->bitsPerPixel == 15)
255 i810Screen->fbFormat = DV_PF_555;
256 else
257 i810Screen->fbFormat = DV_PF_565;
258
259 i810Screen->backOffset=gDRIPriv->backOffset;
260 i810Screen->depthOffset=gDRIPriv->depthOffset;
261 i810Screen->backPitch = gDRIPriv->auxPitch;
262 i810Screen->backPitchBits = gDRIPriv->auxPitchBits;
263 i810Screen->textureOffset=gDRIPriv->textureOffset;
264 i810Screen->textureSize=gDRIPriv->textureSize;
265 i810Screen->logTextureGranularity = gDRIPriv->logTextureGranularity;
266
267 i810Screen->bufs = i810_create_empty_buffers();
268 if (i810Screen->bufs == NULL) {
269 __driUtilMessage("i810InitDriver: i810_create_empty_buffers() failed");
270 FREE(i810Screen);
271 return GL_FALSE;
272 }
273
274 i810Screen->back.handle = gDRIPriv->backbuffer;
275 i810Screen->back.size = gDRIPriv->backbufferSize;
276
277 if (drmMap(sPriv->fd,
278 i810Screen->back.handle,
279 i810Screen->back.size,
280 (drmAddress *)&i810Screen->back.map) != 0) {
281 FREE(i810Screen);
282 sPriv->private = NULL;
283 __driUtilMessage("i810InitDriver: drmMap failed");
284 return GL_FALSE;
285 }
286
287 i810Screen->depth.handle = gDRIPriv->depthbuffer;
288 i810Screen->depth.size = gDRIPriv->depthbufferSize;
289
290 if (drmMap(sPriv->fd,
291 i810Screen->depth.handle,
292 i810Screen->depth.size,
293 (drmAddress *)&i810Screen->depth.map) != 0) {
294 FREE(i810Screen);
295 drmUnmap(i810Screen->back.map, i810Screen->back.size);
296 sPriv->private = NULL;
297 __driUtilMessage("i810InitDriver: drmMap (2) failed");
298 return GL_FALSE;
299 }
300
301 i810Screen->tex.handle = gDRIPriv->textures;
302 i810Screen->tex.size = gDRIPriv->textureSize;
303
304 if (drmMap(sPriv->fd,
305 i810Screen->tex.handle,
306 i810Screen->tex.size,
307 (drmAddress *)&i810Screen->tex.map) != 0) {
308 FREE(i810Screen);
309 drmUnmap(i810Screen->back.map, i810Screen->back.size);
310 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
311 sPriv->private = NULL;
312 __driUtilMessage("i810InitDriver: drmMap (3) failed");
313 return GL_FALSE;
314 }
315
316 i810Screen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
317
318 return GL_TRUE;
319 }
320
321 static void
322 i810DestroyScreen(__DRIscreenPrivate *sPriv)
323 {
324 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
325
326 /* Need to unmap all the bufs and maps here:
327 */
328 drmUnmap(i810Screen->back.map, i810Screen->back.size);
329 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
330 drmUnmap(i810Screen->tex.map, i810Screen->tex.size);
331
332 FREE(i810Screen);
333 sPriv->private = NULL;
334 }
335
336
337 static GLboolean
338 i810CreateBuffer( __DRIscreenPrivate *driScrnPriv,
339 __DRIdrawablePrivate *driDrawPriv,
340 const __GLcontextModes *mesaVis,
341 GLboolean isPixmap )
342 {
343 if (isPixmap) {
344 return GL_FALSE; /* not implemented */
345 }
346 else {
347 driDrawPriv->driverPrivate = (void *)
348 _mesa_create_framebuffer(mesaVis,
349 GL_FALSE, /* software depth buffer? */
350 mesaVis->stencilBits > 0,
351 mesaVis->accumRedBits > 0,
352 GL_FALSE /* s/w alpha planes */);
353 return (driDrawPriv->driverPrivate != NULL);
354 }
355 }
356
357
358 static void
359 i810DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
360 {
361 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
362 }
363
364
365 static GLboolean
366 i810OpenCloseFullScreen(__DRIcontextPrivate *driContextPriv)
367 {
368 return GL_TRUE;
369 }
370
371 static const struct __DriverAPIRec i810API = {
372 .InitDriver = i810InitDriver,
373 .DestroyScreen = i810DestroyScreen,
374 .CreateContext = i810CreateContext,
375 .DestroyContext = i810DestroyContext,
376 .CreateBuffer = i810CreateBuffer,
377 .DestroyBuffer = i810DestroyBuffer,
378 .SwapBuffers = i810SwapBuffers,
379 .MakeCurrent = i810MakeCurrent,
380 .UnbindContext = i810UnbindContext,
381 .OpenFullScreen = i810OpenCloseFullScreen,
382 .CloseFullScreen = i810OpenCloseFullScreen,
383 .GetSwapInfo = NULL,
384 .GetMSC = NULL,
385 .WaitForMSC = NULL,
386 .WaitForSBC = NULL,
387 .SwapBuffersMSC = NULL
388 };
389
390
391 /*
392 * This is the bootstrap function for the driver.
393 * The __driCreateScreen name is the symbol that libGL.so fetches.
394 * Return: pointer to a __DRIscreenPrivate.
395 */
396 #ifndef _SOLO
397 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
398 int numConfigs, __GLXvisualConfig *config)
399 {
400 __DRIscreenPrivate *psp;
401 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &i810API);
402 return (void *) psp;
403 }
404 #else
405 void *__driCreateScreen(struct DRIDriverRec *driver,
406 struct DRIDriverContextRec *driverContext)
407 {
408 __DRIscreenPrivate *psp;
409 psp = __driUtilCreateScreen(driver, driverContext, &i810API);
410 return (void *) psp;
411 }
412 #endif
413
414 /**
415 * This is the bootstrap function for the driver. libGL supplies all of the
416 * requisite information about the system, and the driver initializes itself.
417 * This routine also fills in the linked list pointed to by \c driver_modes
418 * with the \c __GLcontextModes that the driver can support for windows or
419 * pbuffers.
420 *
421 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
422 * failure.
423 */
424 #ifdef USE_NEW_INTERFACE
425 void * __driCreateNewScreen( Display *dpy, int scrn, __DRIscreen *psc,
426 const __GLcontextModes * modes,
427 const __DRIversion * ddx_version,
428 const __DRIversion * dri_version,
429 const __DRIversion * drm_version,
430 const __DRIframebuffer * frame_buffer,
431 drmAddress pSAREA, int fd,
432 int internal_api_version,
433 __GLcontextModes ** driver_modes )
434
435 {
436 __DRIscreenPrivate *psp;
437
438 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
439 ddx_version, dri_version, drm_version,
440 frame_buffer, pSAREA, fd,
441 internal_api_version, &i810API);
442 if ( psp != NULL ) {
443 create_context_modes = (PFNGLXCREATECONTEXTMODES)
444 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
445 if ( create_context_modes != NULL ) {
446 *driver_modes = i810FillInModes( 16,
447 16, 0,
448 1);
449 }
450 }
451
452 return (void *) psp;
453 }
454 #endif /* USE_NEW_INTERFACE */