add missing license texts
[mesa.git] / src / mesa / drivers / dri / i915 / intel_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, 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 TUNGSTEN GRAPHICS 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 #include "glheader.h"
29 #include "context.h"
30 #include "matrix.h"
31 #include "simple_list.h"
32 #include "utils.h"
33
34
35 #include "intel_screen.h"
36
37 #include "intel_tex.h"
38 #include "intel_span.h"
39 #include "intel_tris.h"
40 #include "intel_ioctl.h"
41
42
43
44 #include "i830_dri.h"
45
46 #ifdef USE_NEW_INTERFACE
47 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
48 #endif /*USE_NEW_INTERFACE*/
49
50
51 static void intelPrintDRIInfo(intelScreenPrivate *intelScreen,
52 __DRIscreenPrivate *sPriv,
53 I830DRIPtr gDRIPriv)
54 {
55 fprintf(stderr, "Front size : 0x%x\n", sPriv->fbSize);
56 fprintf(stderr, "Front offset : 0x%x\n", intelScreen->frontOffset);
57 fprintf(stderr, "Back size : 0x%x\n", intelScreen->back.size);
58 fprintf(stderr, "Back offset : 0x%x\n", intelScreen->backOffset);
59 fprintf(stderr, "Depth size : 0x%x\n", intelScreen->depth.size);
60 fprintf(stderr, "Depth offset : 0x%x\n", intelScreen->depthOffset);
61 fprintf(stderr, "Texture size : 0x%x\n", intelScreen->textureSize);
62 fprintf(stderr, "Texture offset : 0x%x\n", intelScreen->textureOffset);
63 fprintf(stderr, "Memory : 0x%x\n", gDRIPriv->mem);
64 }
65
66 static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
67 {
68 intelScreenPrivate *intelScreen;
69 I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv;
70
71
72 /* Allocate the private area */
73 intelScreen = (intelScreenPrivate *)MALLOC(sizeof(intelScreenPrivate));
74 if (!intelScreen) {
75 fprintf(stderr,"\nERROR! Allocating private area failed\n");
76 return GL_FALSE;
77 }
78
79 intelScreen->driScrnPriv = sPriv;
80 sPriv->private = (void *)intelScreen;
81
82 intelScreen->deviceID = gDRIPriv->deviceID;
83 intelScreen->width = gDRIPriv->width;
84 intelScreen->height = gDRIPriv->height;
85 intelScreen->mem = gDRIPriv->mem;
86 intelScreen->cpp = gDRIPriv->cpp;
87 intelScreen->frontPitch = gDRIPriv->fbStride;
88 intelScreen->frontOffset = gDRIPriv->fbOffset;
89
90 switch (gDRIPriv->bitsPerPixel) {
91 case 15: intelScreen->fbFormat = DV_PF_555; break;
92 case 16: intelScreen->fbFormat = DV_PF_565; break;
93 case 32: intelScreen->fbFormat = DV_PF_8888; break;
94 }
95
96 intelScreen->backOffset = gDRIPriv->backOffset;
97 intelScreen->backPitch = gDRIPriv->backPitch;
98 intelScreen->depthOffset = gDRIPriv->depthOffset;
99 intelScreen->depthPitch = gDRIPriv->depthPitch;
100 intelScreen->textureOffset = gDRIPriv->textureOffset;
101 intelScreen->textureSize = gDRIPriv->textureSize;
102 intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
103 intelScreen->back.handle = gDRIPriv->backbuffer;
104 intelScreen->back.size = gDRIPriv->backbufferSize;
105
106 if (drmMap(sPriv->fd,
107 intelScreen->back.handle,
108 intelScreen->back.size,
109 (drmAddress *)&intelScreen->back.map) != 0) {
110 fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
111 __LINE__, __FUNCTION__, __FILE__);
112 FREE(intelScreen);
113 sPriv->private = NULL;
114 return GL_FALSE;
115 }
116
117 intelScreen->depth.handle = gDRIPriv->depthbuffer;
118 intelScreen->depth.size = gDRIPriv->depthbufferSize;
119
120 if (drmMap(sPriv->fd,
121 intelScreen->depth.handle,
122 intelScreen->depth.size,
123 (drmAddress *)&intelScreen->depth.map) != 0) {
124 fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
125 __LINE__, __FUNCTION__, __FILE__);
126 FREE(intelScreen);
127 drmUnmap(intelScreen->back.map, intelScreen->back.size);
128 sPriv->private = NULL;
129 return GL_FALSE;
130 }
131
132 intelScreen->tex.handle = gDRIPriv->textures;
133 intelScreen->tex.size = gDRIPriv->textureSize;
134
135 if (drmMap(sPriv->fd,
136 intelScreen->tex.handle,
137 intelScreen->tex.size,
138 (drmAddress *)&intelScreen->tex.map) != 0) {
139 fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
140 __LINE__, __FUNCTION__, __FILE__);
141 FREE(intelScreen);
142 drmUnmap(intelScreen->back.map, intelScreen->back.size);
143 drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
144 sPriv->private = NULL;
145 return GL_FALSE;
146 }
147
148 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
149
150 if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
151
152 intelScreen->drmMinor = sPriv->drmMinor;
153
154 {
155 int ret;
156 drmI830GetParam gp;
157
158 gp.param = I830_PARAM_IRQ_ACTIVE;
159 gp.value = &intelScreen->irq_active;
160
161 ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
162 &gp, sizeof(gp));
163 if (ret) {
164 fprintf(stderr, "drmI830GetParam: %d\n", ret);
165 return GL_FALSE;
166 }
167 }
168
169 {
170 int ret;
171 drmI830GetParam gp;
172
173 gp.param = I830_PARAM_ALLOW_BATCHBUFFER;
174 gp.value = &intelScreen->allow_batchbuffer;
175
176 ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
177 &gp, sizeof(gp));
178 if (ret) {
179 fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret);
180 return GL_FALSE;
181 }
182 }
183
184 #ifndef _SOLO
185 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
186 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
187 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
188 void * const psc = sPriv->psc->screenConfigs;
189
190 if (glx_enable_extension != NULL) {
191 (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
192
193 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
194 (*glx_enable_extension)( psc, "GLX_SGIX_fbconfig" );
195 (*glx_enable_extension)( psc, "GLX_OML_swap_method" );
196 }
197
198 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
199 sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
200 sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA;
201 sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA;
202
203 (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
204 }
205 }
206 }
207 #endif
208
209 return GL_TRUE;
210 }
211
212
213 static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
214 {
215 intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
216
217 /* Need to unmap all the bufs and maps here:
218 */
219 drmUnmap(intelScreen->back.map, intelScreen->back.size);
220 drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
221 drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
222 FREE(intelScreen);
223 sPriv->private = NULL;
224 }
225
226 static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
227 __DRIdrawablePrivate *driDrawPriv,
228 const __GLcontextModes *mesaVis,
229 GLboolean isPixmap )
230 {
231 if (isPixmap) {
232 return GL_FALSE; /* not implemented */
233 } else {
234 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
235 mesaVis->depthBits != 24);
236
237 driDrawPriv->driverPrivate = (void *)
238 _mesa_create_framebuffer(mesaVis,
239 GL_FALSE, /* software depth buffer? */
240 swStencil,
241 mesaVis->accumRedBits > 0,
242 GL_FALSE /* s/w alpha planes */);
243
244 return (driDrawPriv->driverPrivate != NULL);
245 }
246 }
247
248 static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
249 {
250 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
251 }
252
253
254 /* There are probably better ways to do this, such as an
255 * init-designated function to register chipids and createcontext
256 * functions.
257 */
258 extern GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
259 __DRIcontextPrivate *driContextPriv,
260 void *sharedContextPrivate);
261
262 extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
263 __DRIcontextPrivate *driContextPriv,
264 void *sharedContextPrivate);
265
266
267
268
269 static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
270 __DRIcontextPrivate *driContextPriv,
271 void *sharedContextPrivate)
272 {
273 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
274 intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
275
276 switch (intelScreen->deviceID) {
277 case PCI_CHIP_845_G:
278 case PCI_CHIP_I830_M:
279 case PCI_CHIP_I855_GM:
280 case PCI_CHIP_I865_G:
281 return i830CreateContext( mesaVis, driContextPriv,
282 sharedContextPrivate );
283
284 case PCI_CHIP_I915_G:
285 return i915CreateContext( mesaVis, driContextPriv,
286 sharedContextPrivate );
287
288 default:
289 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
290 return GL_FALSE;
291 }
292 }
293
294
295 static const struct __DriverAPIRec intelAPI = {
296 .InitDriver = intelInitDriver,
297 .DestroyScreen = intelDestroyScreen,
298 .CreateContext = intelCreateContext,
299 .DestroyContext = intelDestroyContext,
300 .CreateBuffer = intelCreateBuffer,
301 .DestroyBuffer = intelDestroyBuffer,
302 .SwapBuffers = intelSwapBuffers,
303 .MakeCurrent = intelMakeCurrent,
304 .UnbindContext = intelUnbindContext,
305 .GetSwapInfo = NULL,
306 .GetMSC = NULL,
307 .WaitForMSC = NULL,
308 .WaitForSBC = NULL,
309 .SwapBuffersMSC = NULL
310 };
311
312 /*
313 * This is the bootstrap function for the driver.
314 * The __driCreateScreen name is the symbol that libGL.so fetches.
315 * Return: pointer to a __DRIscreenPrivate.
316 */
317 #if !defined(DRI_NEW_INTERFACE_ONLY)
318 #ifndef _SOLO
319 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
320 int numConfigs, __GLXvisualConfig *config)
321 {
322 __DRIscreenPrivate *psp;
323 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &intelAPI);
324 return (void *) psp;
325 }
326 #else
327 void *__driCreateScreen(struct DRIDriverRec *driver,
328 struct DRIDriverContextRec *driverContext)
329 {
330 __DRIscreenPrivate *psp;
331 psp = __driUtilCreateScreen(driver, driverContext, &i830API);
332 return (void *) psp;
333 }
334 #endif
335 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
336
337
338 /* This function is called by libGL.so as soon as libGL.so is loaded.
339 * This is where we'd register new extension functions with the dispatcher.
340 *
341 * Note: Most of these are probably already registered - just doing
342 * this for the benefit of old libGL.so's out there.
343 */
344 #include "glapioffsets.h"
345
346 void __driRegisterExtensions( void )
347 {
348 int i;
349 static struct { const char *name; int offset; } funcs[] = {
350 { "glSecondaryColor3bEXT", _gloffset_SecondaryColor3bEXT },
351 { "glSecondaryColor3dEXT", _gloffset_SecondaryColor3dEXT },
352 { "glSecondaryColor3fEXT", _gloffset_SecondaryColor3fEXT },
353 { "glSecondaryColor3iEXT", _gloffset_SecondaryColor3iEXT },
354 { "glSecondaryColor3sEXT", _gloffset_SecondaryColor3sEXT },
355 { "glSecondaryColor3ubEXT", _gloffset_SecondaryColor3ubEXT },
356 { "glSecondaryColor3uiEXT", _gloffset_SecondaryColor3uiEXT },
357 { "glSecondaryColor3usEXT", _gloffset_SecondaryColor3usEXT },
358 { "glSecondaryColor3bvEXT", _gloffset_SecondaryColor3bvEXT },
359 { "glSecondaryColor3dvEXT", _gloffset_SecondaryColor3dvEXT },
360 { "glSecondaryColor3fvEXT", _gloffset_SecondaryColor3fvEXT },
361 { "glSecondaryColor3ivEXT", _gloffset_SecondaryColor3ivEXT },
362 { "glSecondaryColor3svEXT", _gloffset_SecondaryColor3svEXT },
363 { "glSecondaryColor3ubvEXT", _gloffset_SecondaryColor3ubvEXT },
364 { "glSecondaryColor3uivEXT", _gloffset_SecondaryColor3uivEXT },
365 { "glSecondaryColor3usvEXT", _gloffset_SecondaryColor3usvEXT },
366 { "glSecondaryColorPointerEXT", _gloffset_SecondaryColorPointerEXT }
367 };
368
369 for (i = 0 ; i < sizeof(funcs) / sizeof(*funcs) ; i++ )
370 _glapi_add_entrypoint( funcs[i].name, funcs[i].offset );
371 }
372
373
374 #ifdef USE_NEW_INTERFACE
375 static __GLcontextModes * fill_in_modes( __GLcontextModes * modes,
376 unsigned pixel_bits,
377 unsigned depth_bits,
378 unsigned stencil_bits,
379 const GLenum * db_modes,
380 unsigned num_db_modes,
381 int visType )
382 {
383 static const uint8_t bits[2][4] = {
384 { 5, 6, 5, 0 },
385 { 8, 8, 8, 8 }
386 };
387
388 static const uint32_t masks[2][4] = {
389 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
390 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }
391 };
392
393 unsigned i;
394 unsigned j;
395 const unsigned index = ((pixel_bits + 15) / 16) - 1;
396
397 for ( i = 0 ; i < num_db_modes ; i++ ) {
398 for ( j = 0 ; j < 2 ; j++ ) {
399
400 modes->redBits = bits[index][0];
401 modes->greenBits = bits[index][1];
402 modes->blueBits = bits[index][2];
403 modes->alphaBits = bits[index][3];
404 modes->redMask = masks[index][0];
405 modes->greenMask = masks[index][1];
406 modes->blueMask = masks[index][2];
407 modes->alphaMask = masks[index][3];
408 modes->rgbBits = modes->redBits + modes->greenBits
409 + modes->blueBits + modes->alphaBits;
410
411 modes->accumRedBits = 16 * j;
412 modes->accumGreenBits = 16 * j;
413 modes->accumBlueBits = 16 * j;
414 modes->accumAlphaBits = (masks[index][3] != 0) ? 16 * j : 0;
415 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
416
417 modes->stencilBits = stencil_bits;
418 modes->depthBits = depth_bits;
419
420 modes->visualType = visType;
421 modes->renderType = GLX_RGBA_BIT;
422 modes->drawableType = GLX_WINDOW_BIT;
423 modes->rgbMode = GL_TRUE;
424
425 if ( db_modes[i] == GLX_NONE ) {
426 modes->doubleBufferMode = GL_FALSE;
427 }
428 else {
429 modes->doubleBufferMode = GL_TRUE;
430 modes->swapMethod = db_modes[i];
431 }
432
433 modes = modes->next;
434 }
435 }
436
437 return modes;
438 }
439 #endif /* USE_NEW_INTERFACE */
440
441
442 #ifdef USE_NEW_INTERFACE
443 static __GLcontextModes *
444 intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
445 unsigned stencil_bits, GLboolean have_back_buffer )
446 {
447 __GLcontextModes * modes;
448 __GLcontextModes * m;
449 unsigned num_modes;
450 unsigned depth_buffer_factor;
451 unsigned back_buffer_factor;
452 unsigned i;
453
454 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
455 * support pageflipping at all.
456 */
457 static const GLenum back_buffer_modes[] = {
458 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
459 };
460
461 int depth_buffer_modes[2][2];
462
463
464 depth_buffer_modes[0][0] = depth_bits;
465 depth_buffer_modes[1][0] = depth_bits;
466
467 /* Just like with the accumulation buffer, always provide some modes
468 * with a stencil buffer. It will be a sw fallback, but some apps won't
469 * care about that.
470 */
471 depth_buffer_modes[0][1] = 0;
472 depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
473
474 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
475 back_buffer_factor = (have_back_buffer) ? 3 : 1;
476
477 num_modes = depth_buffer_factor * back_buffer_factor * 4;
478
479 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
480 m = modes;
481 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
482 m = fill_in_modes( m, pixel_bits,
483 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
484 back_buffer_modes, back_buffer_factor,
485 GLX_TRUE_COLOR );
486 }
487
488 /* There's no direct color modes on intel? */
489 #if 0
490 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
491 m = fill_in_modes( m, pixel_bits,
492 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
493 back_buffer_modes, back_buffer_factor,
494 GLX_DIRECT_COLOR );
495 }
496 #endif
497
498 /* Mark the visual as slow if there are "fake" stencil bits.
499 */
500 for ( m = modes ; m != NULL ; m = m->next ) {
501 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
502 m->visualRating = GLX_SLOW_CONFIG;
503 }
504 }
505
506 return modes;
507 }
508 #endif /* USE_NEW_INTERFACE */
509
510
511 /**
512 * This is the bootstrap function for the driver. libGL supplies all of the
513 * requisite information about the system, and the driver initializes itself.
514 * This routine also fills in the linked list pointed to by \c driver_modes
515 * with the \c __GLcontextModes that the driver can support for windows or
516 * pbuffers.
517 *
518 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
519 * failure.
520 */
521 #ifdef USE_NEW_INTERFACE
522 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
523 const __GLcontextModes * modes,
524 const __DRIversion * ddx_version,
525 const __DRIversion * dri_version,
526 const __DRIversion * drm_version,
527 const __DRIframebuffer * frame_buffer,
528 drmAddress pSAREA, int fd,
529 int internal_api_version,
530 __GLcontextModes ** driver_modes )
531
532 {
533 __DRIscreenPrivate *psp;
534 static const __DRIversion ddx_expected = { 1, 0, 0 };
535 static const __DRIversion dri_expected = { 4, 0, 0 };
536 static const __DRIversion drm_expected = { 1, 1, 0 };
537
538 if ( ! driCheckDriDdxDrmVersions2( "i915",
539 dri_version, & dri_expected,
540 ddx_version, & ddx_expected,
541 drm_version, & drm_expected ) ) {
542 return NULL;
543 }
544
545 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
546 ddx_version, dri_version, drm_version,
547 frame_buffer, pSAREA, fd,
548 internal_api_version, &intelAPI);
549 if ( psp != NULL ) {
550 create_context_modes = (PFNGLXCREATECONTEXTMODES)
551 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
552 if ( create_context_modes != NULL ) {
553 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
554 *driver_modes = intelFillInModes( dri_priv->cpp * 8,
555 (dri_priv->cpp == 2) ? 16 : 24,
556 (dri_priv->cpp == 2) ? 0 : 8,
557 (dri_priv->backOffset != dri_priv->depthOffset) );
558 }
559 }
560
561 return (void *) psp;
562 }
563 #endif /* USE_NEW_INTERFACE */