Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[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
28 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 *
32 */
33
34
35 #include "glheader.h"
36 #include "imports.h"
37 #include "context.h"
38 #include "framebuffer.h"
39 #include "fbobject.h"
40 #include "matrix.h"
41 #include "renderbuffer.h"
42 #include "simple_list.h"
43 #include "utils.h"
44
45 #include "i810screen.h"
46 #include "i810_dri.h"
47
48 #include "i810state.h"
49 #include "i810tex.h"
50 #include "i810span.h"
51 #include "i810tris.h"
52 #include "i810ioctl.h"
53
54 #include "GL/internal/dri_interface.h"
55
56 extern const struct dri_extension card_extensions[];
57
58 static __GLcontextModes *fill_in_modes( __GLcontextModes *modes,
59 unsigned pixel_bits,
60 unsigned depth_bits,
61 unsigned stencil_bits,
62 const GLenum * db_modes,
63 unsigned num_db_modes,
64 int visType )
65 {
66 static const u_int8_t bits[1][4] = {
67 { 5, 6, 5, 0 }
68 };
69
70 static const u_int32_t masks[1][4] = {
71 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
72 };
73
74 unsigned i;
75 unsigned j;
76 const unsigned index = 0;
77
78 for ( i = 0 ; i < num_db_modes ; i++ ) {
79 for ( j = 0 ; j < 2 ; j++ ) {
80
81 modes->redBits = bits[index][0];
82 modes->greenBits = bits[index][1];
83 modes->blueBits = bits[index][2];
84 modes->alphaBits = bits[index][3];
85 modes->redMask = masks[index][0];
86 modes->greenMask = masks[index][1];
87 modes->blueMask = masks[index][2];
88 modes->alphaMask = masks[index][3];
89 modes->rgbBits = modes->redBits + modes->greenBits
90 + modes->blueBits + modes->alphaBits;
91
92 modes->accumRedBits = 16 * j;
93 modes->accumGreenBits = 16 * j;
94 modes->accumBlueBits = 16 * j;
95 modes->accumAlphaBits = (masks[index][3] != 0) ? 16 * j : 0;
96 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
97
98 modes->stencilBits = stencil_bits;
99 modes->depthBits = depth_bits;
100
101 modes->visualType = visType;
102 modes->renderType = GLX_RGBA_BIT;
103 modes->drawableType = GLX_WINDOW_BIT;
104 modes->rgbMode = GL_TRUE;
105
106 if ( db_modes[i] == GLX_NONE ) {
107 modes->doubleBufferMode = GL_FALSE;
108 }
109 else {
110 modes->doubleBufferMode = GL_TRUE;
111 modes->swapMethod = db_modes[i];
112 }
113
114 modes = modes->next;
115 }
116 }
117
118 return modes;
119
120 }
121
122
123 static __GLcontextModes *
124 i810FillInModes( unsigned pixel_bits, unsigned depth_bits,
125 unsigned stencil_bits, GLboolean have_back_buffer )
126 { __GLcontextModes * modes;
127 __GLcontextModes * m;
128 unsigned num_modes;
129 unsigned depth_buffer_factor;
130 unsigned back_buffer_factor;
131 unsigned i;
132
133 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
134 * enough to add support. Basically, if a context is created with an
135 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
136 * will never be used.
137 */
138 static const GLenum back_buffer_modes[] = {
139 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
140 };
141
142 int depth_buffer_modes[2][2];
143
144
145 depth_buffer_modes[0][0] = depth_bits;
146 depth_buffer_modes[1][0] = depth_bits;
147
148 /* Just like with the accumulation buffer, always provide some modes
149 * with a stencil buffer. It will be a sw fallback, but some apps won't
150 * care about that.
151 */
152 depth_buffer_modes[0][1] = 0;
153 depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
154
155 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
156 back_buffer_factor = (have_back_buffer) ? 2 : 1;
157
158 num_modes = depth_buffer_factor * back_buffer_factor * 4;
159
160 modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
161 m = modes;
162 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
163 m = fill_in_modes( m, pixel_bits,
164 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
165 back_buffer_modes, back_buffer_factor,
166 GLX_TRUE_COLOR );
167 }
168
169 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
170 m = fill_in_modes( m, pixel_bits,
171 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
172 back_buffer_modes, back_buffer_factor,
173 GLX_DIRECT_COLOR );
174 }
175
176 /* Mark the visual as slow if there are "fake" stencil bits.
177 */
178 for ( m = modes ; m != NULL ; m = m->next ) {
179 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
180 m->visualRating = GLX_SLOW_CONFIG;
181 }
182 }
183
184 return modes;
185
186 }
187
188
189 /* static int i810_malloc_proxy_buf(drmBufMapPtr buffers) */
190 /* { */
191 /* char *buffer; */
192 /* drmBufPtr buf; */
193 /* int i; */
194
195 /* buffer = CALLOC(I810_DMA_BUF_SZ); */
196 /* if(buffer == NULL) return -1; */
197 /* for(i = 0; i < I810_DMA_BUF_NR; i++) { */
198 /* buf = &(buffers->list[i]); */
199 /* buf->address = (drmAddress)buffer; */
200 /* } */
201 /* return 0; */
202 /* } */
203
204 static drmBufMapPtr i810_create_empty_buffers(void)
205 {
206 drmBufMapPtr retval;
207
208 retval = (drmBufMapPtr)ALIGN_MALLOC(sizeof(drmBufMap), 32);
209 if(retval == NULL) return NULL;
210 memset(retval, 0, sizeof(drmBufMap));
211 retval->list = (drmBufPtr)ALIGN_MALLOC(sizeof(drmBuf) * I810_DMA_BUF_NR, 32);
212 if(retval->list == NULL) {
213 ALIGN_FREE(retval);
214 return NULL;
215 }
216 memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
217 return retval;
218 }
219
220
221 static GLboolean
222 i810InitDriver(__DRIscreenPrivate *sPriv)
223 {
224 i810ScreenPrivate *i810Screen;
225 I810DRIPtr gDRIPriv = (I810DRIPtr)sPriv->pDevPriv;
226
227 if (sPriv->devPrivSize != sizeof(I810DRIRec)) {
228 fprintf(stderr,"\nERROR! sizeof(I810DRIRec) does not match passed size from device driver\n");
229 return GL_FALSE;
230 }
231
232 /* Allocate the private area */
233 i810Screen = (i810ScreenPrivate *)CALLOC(sizeof(i810ScreenPrivate));
234 if (!i810Screen) {
235 __driUtilMessage("i810InitDriver: alloc i810ScreenPrivate struct failed");
236 return GL_FALSE;
237 }
238
239 i810Screen->driScrnPriv = sPriv;
240 sPriv->private = (void *)i810Screen;
241
242 i810Screen->deviceID=gDRIPriv->deviceID;
243 i810Screen->width=gDRIPriv->width;
244 i810Screen->height=gDRIPriv->height;
245 i810Screen->mem=gDRIPriv->mem;
246 i810Screen->cpp=gDRIPriv->cpp;
247 i810Screen->fbStride=gDRIPriv->fbStride;
248 i810Screen->fbOffset=gDRIPriv->fbOffset;
249
250 if (gDRIPriv->bitsPerPixel == 15)
251 i810Screen->fbFormat = DV_PF_555;
252 else
253 i810Screen->fbFormat = DV_PF_565;
254
255 i810Screen->backOffset=gDRIPriv->backOffset;
256 i810Screen->depthOffset=gDRIPriv->depthOffset;
257 i810Screen->backPitch = gDRIPriv->auxPitch;
258 i810Screen->backPitchBits = gDRIPriv->auxPitchBits;
259 i810Screen->textureOffset=gDRIPriv->textureOffset;
260 i810Screen->textureSize=gDRIPriv->textureSize;
261 i810Screen->logTextureGranularity = gDRIPriv->logTextureGranularity;
262
263 i810Screen->bufs = i810_create_empty_buffers();
264 if (i810Screen->bufs == NULL) {
265 __driUtilMessage("i810InitDriver: i810_create_empty_buffers() failed");
266 FREE(i810Screen);
267 return GL_FALSE;
268 }
269
270 i810Screen->back.handle = gDRIPriv->backbuffer;
271 i810Screen->back.size = gDRIPriv->backbufferSize;
272
273 if (drmMap(sPriv->fd,
274 i810Screen->back.handle,
275 i810Screen->back.size,
276 (drmAddress *)&i810Screen->back.map) != 0) {
277 FREE(i810Screen);
278 sPriv->private = NULL;
279 __driUtilMessage("i810InitDriver: drmMap failed");
280 return GL_FALSE;
281 }
282
283 i810Screen->depth.handle = gDRIPriv->depthbuffer;
284 i810Screen->depth.size = gDRIPriv->depthbufferSize;
285
286 if (drmMap(sPriv->fd,
287 i810Screen->depth.handle,
288 i810Screen->depth.size,
289 (drmAddress *)&i810Screen->depth.map) != 0) {
290 FREE(i810Screen);
291 drmUnmap(i810Screen->back.map, i810Screen->back.size);
292 sPriv->private = NULL;
293 __driUtilMessage("i810InitDriver: drmMap (2) failed");
294 return GL_FALSE;
295 }
296
297 i810Screen->tex.handle = gDRIPriv->textures;
298 i810Screen->tex.size = gDRIPriv->textureSize;
299
300 if (drmMap(sPriv->fd,
301 i810Screen->tex.handle,
302 i810Screen->tex.size,
303 (drmAddress *)&i810Screen->tex.map) != 0) {
304 drmUnmap(i810Screen->back.map, i810Screen->back.size);
305 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
306 FREE(i810Screen);
307 sPriv->private = NULL;
308 __driUtilMessage("i810InitDriver: drmMap (3) failed");
309 return GL_FALSE;
310 }
311
312 i810Screen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
313
314 return GL_TRUE;
315 }
316
317 static void
318 i810DestroyScreen(__DRIscreenPrivate *sPriv)
319 {
320 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
321
322 /* Need to unmap all the bufs and maps here:
323 */
324 drmUnmap(i810Screen->back.map, i810Screen->back.size);
325 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
326 drmUnmap(i810Screen->tex.map, i810Screen->tex.size);
327
328 FREE(i810Screen);
329 sPriv->private = NULL;
330 }
331
332
333 /**
334 * Create a buffer which corresponds to the window.
335 */
336 static GLboolean
337 i810CreateBuffer( __DRIscreenPrivate *driScrnPriv,
338 __DRIdrawablePrivate *driDrawPriv,
339 const __GLcontextModes *mesaVis,
340 GLboolean isPixmap )
341 {
342 i810ScreenPrivate *screen = (i810ScreenPrivate *) driScrnPriv->private;
343
344 if (isPixmap) {
345 return GL_FALSE; /* not implemented */
346 }
347 else {
348 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
349
350 {
351 driRenderbuffer *frontRb
352 = driNewRenderbuffer(GL_RGBA,
353 driScrnPriv->pFB,
354 screen->cpp,
355 /*screen->frontOffset*/0, screen->backPitch,
356 driDrawPriv);
357 i810SetSpanFunctions(frontRb, mesaVis);
358 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
359 }
360
361 if (mesaVis->doubleBufferMode) {
362 driRenderbuffer *backRb
363 = driNewRenderbuffer(GL_RGBA,
364 screen->back.map,
365 screen->cpp,
366 screen->backOffset, screen->backPitch,
367 driDrawPriv);
368 i810SetSpanFunctions(backRb, mesaVis);
369 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
370 }
371
372 if (mesaVis->depthBits == 16) {
373 driRenderbuffer *depthRb
374 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
375 screen->depth.map,
376 screen->cpp,
377 screen->depthOffset, screen->backPitch,
378 driDrawPriv);
379 i810SetSpanFunctions(depthRb, mesaVis);
380 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
381 }
382
383 _mesa_add_soft_renderbuffers(fb,
384 GL_FALSE, /* color */
385 GL_FALSE, /* depth */
386 mesaVis->stencilBits > 0,
387 mesaVis->accumRedBits > 0,
388 GL_FALSE, /* alpha */
389 GL_FALSE /* aux */);
390 driDrawPriv->driverPrivate = (void *) fb;
391
392 return (driDrawPriv->driverPrivate != NULL);
393 }
394 }
395
396
397 static void
398 i810DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
399 {
400 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
401 }
402
403
404 static const struct __DriverAPIRec i810API = {
405 .InitDriver = i810InitDriver,
406 .DestroyScreen = i810DestroyScreen,
407 .CreateContext = i810CreateContext,
408 .DestroyContext = i810DestroyContext,
409 .CreateBuffer = i810CreateBuffer,
410 .DestroyBuffer = i810DestroyBuffer,
411 .SwapBuffers = i810SwapBuffers,
412 .MakeCurrent = i810MakeCurrent,
413 .UnbindContext = i810UnbindContext,
414 .GetSwapInfo = NULL,
415 .GetMSC = NULL,
416 .WaitForMSC = NULL,
417 .WaitForSBC = NULL,
418 .SwapBuffersMSC = NULL
419 };
420
421
422 /**
423 * This is the bootstrap function for the driver. libGL supplies all of the
424 * requisite information about the system, and the driver initializes itself.
425 * This routine also fills in the linked list pointed to by \c driver_modes
426 * with the \c __GLcontextModes that the driver can support for windows or
427 * pbuffers.
428 *
429 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
430 * failure.
431 */
432 PUBLIC
433 void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
434 const __GLcontextModes * modes,
435 const __DRIversion * ddx_version,
436 const __DRIversion * dri_version,
437 const __DRIversion * drm_version,
438 const __DRIframebuffer * frame_buffer,
439 drmAddress pSAREA, int fd,
440 int internal_api_version,
441 const __DRIinterfaceMethods * interface,
442 __GLcontextModes ** driver_modes )
443
444 {
445 __DRIscreenPrivate *psp;
446 static const __DRIversion ddx_expected = { 1, 0, 0 };
447 static const __DRIversion dri_expected = { 4, 0, 0 };
448 static const __DRIversion drm_expected = { 1, 2, 0 };
449
450 dri_interface = interface;
451
452 if ( ! driCheckDriDdxDrmVersions2( "i810",
453 dri_version, & dri_expected,
454 ddx_version, & ddx_expected,
455 drm_version, & drm_expected ) ) {
456 return NULL;
457 }
458
459 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
460 ddx_version, dri_version, drm_version,
461 frame_buffer, pSAREA, fd,
462 internal_api_version, &i810API);
463 if ( psp != NULL ) {
464 *driver_modes = i810FillInModes( 16,
465 16, 0,
466 1);
467 driInitExtensions( NULL, card_extensions, GL_TRUE );
468 }
469
470 return (void *) psp;
471 }