f87a205f2027f620c9034b8b1c421b3d0bed5eec
[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 #include "GL/internal/dri_interface.h"
53
54 #ifdef USE_NEW_INTERFACE
55 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
56 #endif /* USE_NEW_INTERFACE */
57
58 #ifdef USE_NEW_INTERFACE
59 static __GLcontextModes *fill_in_modes( __GLcontextModes *modes,
60 unsigned pixel_bits,
61 unsigned depth_bits,
62 unsigned stencil_bits,
63 const GLenum * db_modes,
64 unsigned num_db_modes,
65 int visType )
66 {
67 static const uint8_t bits[1][4] = {
68 { 5, 6, 5, 0 }
69 };
70
71 static const uint32_t masks[1][4] = {
72 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
73 };
74
75 unsigned i;
76 unsigned j;
77 const unsigned index = 0;
78
79 for ( i = 0 ; i < num_db_modes ; i++ ) {
80 for ( j = 0 ; j < 2 ; j++ ) {
81
82 modes->redBits = bits[index][0];
83 modes->greenBits = bits[index][1];
84 modes->blueBits = bits[index][2];
85 modes->alphaBits = bits[index][3];
86 modes->redMask = masks[index][0];
87 modes->greenMask = masks[index][1];
88 modes->blueMask = masks[index][2];
89 modes->alphaMask = masks[index][3];
90 modes->rgbBits = modes->redBits + modes->greenBits
91 + modes->blueBits + modes->alphaBits;
92
93 modes->accumRedBits = 16 * j;
94 modes->accumGreenBits = 16 * j;
95 modes->accumBlueBits = 16 * j;
96 modes->accumAlphaBits = (masks[index][3] != 0) ? 16 * j : 0;
97 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
98
99 modes->stencilBits = stencil_bits;
100 modes->depthBits = depth_bits;
101
102 modes->visualType = visType;
103 modes->renderType = GLX_RGBA_BIT;
104 modes->drawableType = GLX_WINDOW_BIT;
105 modes->rgbMode = GL_TRUE;
106
107 if ( db_modes[i] == GLX_NONE ) {
108 modes->doubleBufferMode = GL_FALSE;
109 }
110 else {
111 modes->doubleBufferMode = GL_TRUE;
112 modes->swapMethod = db_modes[i];
113 }
114
115 modes = modes->next;
116 }
117 }
118
119 return modes;
120
121 }
122 #endif /* USE_NEW_INTERFACE */
123
124 #ifdef USE_NEW_INTERFACE
125 static __GLcontextModes *
126 i810FillInModes( unsigned pixel_bits, unsigned depth_bits,
127 unsigned stencil_bits, GLboolean have_back_buffer )
128 { __GLcontextModes * modes;
129 __GLcontextModes * m;
130 unsigned num_modes;
131 unsigned depth_buffer_factor;
132 unsigned back_buffer_factor;
133 unsigned i;
134
135 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
136 * enough to add support. Basically, if a context is created with an
137 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
138 * will never be used.
139 */
140 static const GLenum back_buffer_modes[] = {
141 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
142 };
143
144 int depth_buffer_modes[2][2];
145
146
147 depth_buffer_modes[0][0] = depth_bits;
148 depth_buffer_modes[1][0] = depth_bits;
149
150 /* Just like with the accumulation buffer, always provide some modes
151 * with a stencil buffer. It will be a sw fallback, but some apps won't
152 * care about that.
153 */
154 depth_buffer_modes[0][1] = 0;
155 depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
156
157 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
158 back_buffer_factor = (have_back_buffer) ? 2 : 1;
159
160 num_modes = depth_buffer_factor * back_buffer_factor * 4;
161
162 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
163 m = modes;
164 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
165 m = fill_in_modes( m, pixel_bits,
166 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
167 back_buffer_modes, back_buffer_factor,
168 GLX_TRUE_COLOR );
169 }
170
171 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
172 m = fill_in_modes( m, pixel_bits,
173 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
174 back_buffer_modes, back_buffer_factor,
175 GLX_DIRECT_COLOR );
176 }
177
178 /* Mark the visual as slow if there are "fake" stencil bits.
179 */
180 for ( m = modes ; m != NULL ; m = m->next ) {
181 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
182 m->visualRating = GLX_SLOW_CONFIG;
183 }
184 }
185
186 return modes;
187
188 }
189 #endif /* USE_NEW_INTERFACE */
190
191
192
193 /* static int i810_malloc_proxy_buf(drmBufMapPtr buffers) */
194 /* { */
195 /* char *buffer; */
196 /* drmBufPtr buf; */
197 /* int i; */
198
199 /* buffer = CALLOC(I810_DMA_BUF_SZ); */
200 /* if(buffer == NULL) return -1; */
201 /* for(i = 0; i < I810_DMA_BUF_NR; i++) { */
202 /* buf = &(buffers->list[i]); */
203 /* buf->address = (drmAddress)buffer; */
204 /* } */
205 /* return 0; */
206 /* } */
207
208 static drmBufMapPtr i810_create_empty_buffers(void)
209 {
210 drmBufMapPtr retval;
211
212 retval = (drmBufMapPtr)ALIGN_MALLOC(sizeof(drmBufMap), 32);
213 if(retval == NULL) return NULL;
214 memset(retval, 0, sizeof(drmBufMap));
215 retval->list = (drmBufPtr)ALIGN_MALLOC(sizeof(drmBuf) * I810_DMA_BUF_NR, 32);
216 if(retval->list == NULL) {
217 ALIGN_FREE(retval);
218 return NULL;
219 }
220 memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
221 return retval;
222 }
223
224
225 static GLboolean
226 i810InitDriver(__DRIscreenPrivate *sPriv)
227 {
228 i810ScreenPrivate *i810Screen;
229 I810DRIPtr gDRIPriv = (I810DRIPtr)sPriv->pDevPriv;
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 FREE(i810Screen);
305 drmUnmap(i810Screen->back.map, i810Screen->back.size);
306 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
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 static GLboolean
334 i810CreateBuffer( __DRIscreenPrivate *driScrnPriv,
335 __DRIdrawablePrivate *driDrawPriv,
336 const __GLcontextModes *mesaVis,
337 GLboolean isPixmap )
338 {
339 if (isPixmap) {
340 return GL_FALSE; /* not implemented */
341 }
342 else {
343 driDrawPriv->driverPrivate = (void *)
344 _mesa_create_framebuffer(mesaVis,
345 GL_FALSE, /* software depth buffer? */
346 mesaVis->stencilBits > 0,
347 mesaVis->accumRedBits > 0,
348 GL_FALSE /* s/w alpha planes */);
349 return (driDrawPriv->driverPrivate != NULL);
350 }
351 }
352
353
354 static void
355 i810DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
356 {
357 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
358 }
359
360
361 static const struct __DriverAPIRec i810API = {
362 .InitDriver = i810InitDriver,
363 .DestroyScreen = i810DestroyScreen,
364 .CreateContext = i810CreateContext,
365 .DestroyContext = i810DestroyContext,
366 .CreateBuffer = i810CreateBuffer,
367 .DestroyBuffer = i810DestroyBuffer,
368 .SwapBuffers = i810SwapBuffers,
369 .MakeCurrent = i810MakeCurrent,
370 .UnbindContext = i810UnbindContext,
371 .GetSwapInfo = NULL,
372 .GetMSC = NULL,
373 .WaitForMSC = NULL,
374 .WaitForSBC = NULL,
375 .SwapBuffersMSC = NULL
376 };
377
378
379 /*
380 * This is the bootstrap function for the driver.
381 * The __driCreateScreen name is the symbol that libGL.so fetches.
382 * Return: pointer to a __DRIscreenPrivate.
383 */
384 #if !defined(DRI_NEW_INTERFACE_ONLY)
385 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
386 int numConfigs, __GLXvisualConfig *config)
387 {
388 __DRIscreenPrivate *psp;
389 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &i810API);
390 return (void *) psp;
391 }
392 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
393
394 /**
395 * This is the bootstrap function for the driver. libGL supplies all of the
396 * requisite information about the system, and the driver initializes itself.
397 * This routine also fills in the linked list pointed to by \c driver_modes
398 * with the \c __GLcontextModes that the driver can support for windows or
399 * pbuffers.
400 *
401 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
402 * failure.
403 */
404 #ifdef USE_NEW_INTERFACE
405 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
406 const __GLcontextModes * modes,
407 const __DRIversion * ddx_version,
408 const __DRIversion * dri_version,
409 const __DRIversion * drm_version,
410 const __DRIframebuffer * frame_buffer,
411 drmAddress pSAREA, int fd,
412 int internal_api_version,
413 __GLcontextModes ** driver_modes )
414
415 {
416 __DRIscreenPrivate *psp;
417 static const __DRIversion ddx_expected = { 1, 0, 0 };
418 static const __DRIversion dri_expected = { 4, 0, 0 };
419 static const __DRIversion drm_expected = { 1, 2, 0 };
420
421 if ( ! driCheckDriDdxDrmVersions2( "i810",
422 dri_version, & dri_expected,
423 ddx_version, & ddx_expected,
424 drm_version, & drm_expected ) ) {
425 return NULL;
426 }
427
428 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
429 ddx_version, dri_version, drm_version,
430 frame_buffer, pSAREA, fd,
431 internal_api_version, &i810API);
432 if ( psp != NULL ) {
433 create_context_modes = (PFNGLXCREATECONTEXTMODES)
434 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
435 if ( create_context_modes != NULL ) {
436 *driver_modes = i810FillInModes( 16,
437 16, 0,
438 1);
439 }
440 }
441
442 return (void *) psp;
443 }
444 #endif /* USE_NEW_INTERFACE */