OSDN Git Service

i965: new integrated graphics chipset support
[android-x86/external-mesa.git] / src / mesa / drivers / dri / intel / 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 "framebuffer.h"
31 #include "matrix.h"
32 #include "renderbuffer.h"
33 #include "simple_list.h"
34 #include "utils.h"
35 #include "vblank.h"
36 #include "xmlpool.h"
37
38
39 #include "intel_screen.h"
40
41 #include "intel_buffers.h"
42 #include "intel_tex.h"
43 #include "intel_span.h"
44 #include "intel_ioctl.h"
45 #include "intel_fbo.h"
46 #include "intel_chipset.h"
47
48 #include "i915_drm.h"
49 #include "i830_dri.h"
50 #include "intel_regions.h"
51 #include "intel_batchbuffer.h"
52
53 PUBLIC const char __driConfigOptions[] =
54    DRI_CONF_BEGIN
55    DRI_CONF_SECTION_PERFORMANCE
56       DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
57       DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
58    DRI_CONF_SECTION_END
59    DRI_CONF_SECTION_QUALITY
60       DRI_CONF_FORCE_S3TC_ENABLE(false)
61       DRI_CONF_ALLOW_LARGE_TEXTURES(1)
62    DRI_CONF_SECTION_END
63    DRI_CONF_SECTION_DEBUG
64      DRI_CONF_NO_RAST(false)
65    DRI_CONF_SECTION_END
66 DRI_CONF_END;
67
68 const GLuint __driNConfigOptions = 5;
69
70 #ifdef USE_NEW_INTERFACE
71      static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
72 #endif /*USE_NEW_INTERFACE */
73
74      extern const struct dri_extension card_extensions[];
75      extern const struct dri_extension ttm_extensions[];
76
77 /**
78  * Map all the memory regions described by the screen.
79  * \return GL_TRUE if success, GL_FALSE if error.
80  */
81 GLboolean
82 intelMapScreenRegions(__DRIscreenPrivate * sPriv)
83 {
84    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
85
86    if (intelScreen->front.handle) {
87       if (drmMap(sPriv->fd,
88                  intelScreen->front.handle,
89                  intelScreen->front.size,
90                  (drmAddress *) & intelScreen->front.map) != 0) {
91          _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
92          return GL_FALSE;
93       }
94    }
95    else {
96       _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
97    }
98
99    if (0)
100       _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
101    if (drmMap(sPriv->fd,
102               intelScreen->back.handle,
103               intelScreen->back.size,
104               (drmAddress *) & intelScreen->back.map) != 0) {
105       intelUnmapScreenRegions(intelScreen);
106       return GL_FALSE;
107    }
108
109    if (intelScreen->third.handle) {
110       if (0)
111          _mesa_printf("Third 0x%08x ", intelScreen->third.handle);
112       if (drmMap(sPriv->fd,
113                  intelScreen->third.handle,
114                  intelScreen->third.size,
115                  (drmAddress *) & intelScreen->third.map) != 0) {
116          intelUnmapScreenRegions(intelScreen);
117          return GL_FALSE;
118       }
119    }
120
121    if (0)
122       _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
123    if (drmMap(sPriv->fd,
124               intelScreen->depth.handle,
125               intelScreen->depth.size,
126               (drmAddress *) & intelScreen->depth.map) != 0) {
127       intelUnmapScreenRegions(intelScreen);
128       return GL_FALSE;
129    }
130
131    if (0)
132       _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
133    if (intelScreen->tex.size != 0) {
134       if (drmMap(sPriv->fd,
135                  intelScreen->tex.handle,
136                  intelScreen->tex.size,
137                  (drmAddress *) & intelScreen->tex.map) != 0) {
138          intelUnmapScreenRegions(intelScreen);
139          return GL_FALSE;
140       }
141    }
142
143    if (0)
144       printf("Mappings:  front: %p  back: %p  third: %p  depth: %p  tex: %p\n",
145              intelScreen->front.map,
146              intelScreen->back.map, intelScreen->third.map,
147              intelScreen->depth.map, intelScreen->tex.map);
148    return GL_TRUE;
149 }
150
151 void
152 intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
153 {
154 #define REALLY_UNMAP 1
155    if (intelScreen->front.map) {
156 #if REALLY_UNMAP
157       if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
158          printf("drmUnmap front failed!\n");
159 #endif
160       intelScreen->front.map = NULL;
161    }
162    if (intelScreen->back.map) {
163 #if REALLY_UNMAP
164       if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
165          printf("drmUnmap back failed!\n");
166 #endif
167       intelScreen->back.map = NULL;
168    }
169    if (intelScreen->third.map) {
170 #if REALLY_UNMAP
171       if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0)
172          printf("drmUnmap third failed!\n");
173 #endif
174       intelScreen->third.map = NULL;
175    }
176    if (intelScreen->depth.map) {
177 #if REALLY_UNMAP
178       drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
179       intelScreen->depth.map = NULL;
180 #endif
181    }
182    if (intelScreen->tex.map) {
183 #if REALLY_UNMAP
184       drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
185       intelScreen->tex.map = NULL;
186 #endif
187    }
188 }
189
190
191 static void
192 intelPrintDRIInfo(intelScreenPrivate * intelScreen,
193                   __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
194 {
195    fprintf(stderr, "*** Front size:   0x%x  offset: 0x%x  pitch: %d\n",
196            intelScreen->front.size, intelScreen->front.offset,
197            intelScreen->pitch);
198    fprintf(stderr, "*** Back size:    0x%x  offset: 0x%x  pitch: %d\n",
199            intelScreen->back.size, intelScreen->back.offset,
200            intelScreen->pitch);
201    fprintf(stderr, "*** Depth size:   0x%x  offset: 0x%x  pitch: %d\n",
202            intelScreen->depth.size, intelScreen->depth.offset,
203            intelScreen->pitch);
204    fprintf(stderr, "*** Texture size: 0x%x  offset: 0x%x\n",
205            intelScreen->tex.size, intelScreen->tex.offset);
206    fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
207 }
208
209
210 static void
211 intelPrintSAREA(const drmI830Sarea * sarea)
212 {
213    fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width,
214            sarea->height);
215    fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
216    fprintf(stderr,
217            "SAREA: front offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
218            sarea->front_offset, sarea->front_size,
219            (unsigned) sarea->front_handle);
220    fprintf(stderr,
221            "SAREA: back  offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
222            sarea->back_offset, sarea->back_size,
223            (unsigned) sarea->back_handle);
224    fprintf(stderr, "SAREA: depth offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
225            sarea->depth_offset, sarea->depth_size,
226            (unsigned) sarea->depth_handle);
227    fprintf(stderr, "SAREA: tex   offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
228            sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
229 }
230
231
232 /**
233  * A number of the screen parameters are obtained/computed from
234  * information in the SAREA.  This function updates those parameters.
235  */
236 void
237 intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
238                            drmI830Sarea * sarea)
239 {
240    intelScreen->width = sarea->width;
241    intelScreen->height = sarea->height;
242    intelScreen->pitch = sarea->pitch;
243
244    intelScreen->front.offset = sarea->front_offset;
245    intelScreen->front.handle = sarea->front_handle;
246    intelScreen->front.size = sarea->front_size;
247    intelScreen->front.tiled = sarea->front_tiled;
248
249    intelScreen->back.offset = sarea->back_offset;
250    intelScreen->back.handle = sarea->back_handle;
251    intelScreen->back.size = sarea->back_size;
252    intelScreen->back.tiled = sarea->back_tiled;
253
254    if (intelScreen->driScrnPriv->ddx_version.minor >= 8) {
255       intelScreen->third.offset = sarea->third_offset;
256       intelScreen->third.handle = sarea->third_handle;
257       intelScreen->third.size = sarea->third_size;
258       intelScreen->third.tiled = sarea->third_tiled;
259    }
260
261    intelScreen->depth.offset = sarea->depth_offset;
262    intelScreen->depth.handle = sarea->depth_handle;
263    intelScreen->depth.size = sarea->depth_size;
264    intelScreen->depth.tiled = sarea->depth_tiled;
265
266    if (intelScreen->driScrnPriv->ddx_version.minor >= 9) {
267       intelScreen->front.bo_handle = sarea->front_bo_handle;
268       intelScreen->back.bo_handle = sarea->back_bo_handle;
269       intelScreen->third.bo_handle = sarea->third_bo_handle;
270       intelScreen->depth.bo_handle = sarea->depth_bo_handle;
271    } else {
272       intelScreen->front.bo_handle = -1;
273       intelScreen->back.bo_handle = -1;
274       intelScreen->third.bo_handle = -1;
275       intelScreen->depth.bo_handle = -1;
276    }
277
278    intelScreen->tex.offset = sarea->tex_offset;
279    intelScreen->logTextureGranularity = sarea->log_tex_granularity;
280    intelScreen->tex.handle = sarea->tex_handle;
281    intelScreen->tex.size = sarea->tex_size;
282
283    if (0)
284       intelPrintSAREA(sarea);
285 }
286
287 static const __DRItexOffsetExtension intelTexOffsetExtension = {
288    { __DRI_TEX_OFFSET },
289    intelSetTexOffset,
290 };
291
292 static const __DRIextension *intelExtensions[] = {
293     &driReadDrawableExtension,
294     &driCopySubBufferExtension.base,
295     &driSwapControlExtension.base,
296     &driFrameTrackingExtension.base,
297     &driMediaStreamCounterExtension.base,
298     &intelTexOffsetExtension.base,
299     NULL
300 };
301
302 static GLboolean
303 intel_get_param(__DRIscreenPrivate *psp, int param, int *value)
304 {
305    int ret;
306    drmI830GetParam gp;
307
308    gp.param = param;
309    gp.value = value;
310
311    ret = drmCommandWriteRead(psp->fd, DRM_I830_GETPARAM, &gp, sizeof(gp));
312    if (ret) {
313       fprintf(stderr, "drmI830GetParam: %d\n", ret);
314       return GL_FALSE;
315    }
316
317    return GL_TRUE;
318 }
319
320 static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
321 {
322    intelScreenPrivate *intelScreen;
323    I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
324    drmI830Sarea *sarea;
325
326    if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
327       fprintf(stderr,
328               "\nERROR!  sizeof(I830DRIRec) does not match passed size from device driver\n");
329       return GL_FALSE;
330    }
331
332    /* Allocate the private area */
333    intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
334    if (!intelScreen) {
335       fprintf(stderr, "\nERROR!  Allocating private area failed\n");
336       return GL_FALSE;
337    }
338    /* parse information in __driConfigOptions */
339    driParseOptionInfo(&intelScreen->optionCache,
340                       __driConfigOptions, __driNConfigOptions);
341
342    intelScreen->driScrnPriv = sPriv;
343    sPriv->private = (void *) intelScreen;
344    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
345    sarea = (drmI830Sarea *)
346       (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
347
348    intelScreen->deviceID = gDRIPriv->deviceID;
349
350    intelUpdateScreenFromSAREA(intelScreen, sarea);
351
352    if (!intelMapScreenRegions(sPriv)) {
353       fprintf(stderr, "\nERROR!  mapping regions\n");
354       _mesa_free(intelScreen);
355       sPriv->private = NULL;
356       return GL_FALSE;
357    }
358
359    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
360
361    if (0)
362       intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
363
364    intelScreen->drmMinor = sPriv->drm_version.minor;
365
366    /* Determine if IRQs are active? */
367    if (!intel_get_param(sPriv, I830_PARAM_IRQ_ACTIVE,
368                         &intelScreen->irq_active))
369       return GL_FALSE;
370
371    /* Determine if batchbuffers are allowed */
372    if (!intel_get_param(sPriv, I830_PARAM_ALLOW_BATCHBUFFER,
373                         &intelScreen->allow_batchbuffer))
374       return GL_FALSE;
375
376    sPriv->extensions = intelExtensions;
377
378    return GL_TRUE;
379 }
380
381
382 static void
383 intelDestroyScreen(__DRIscreenPrivate * sPriv)
384 {
385    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
386
387    intelUnmapScreenRegions(intelScreen);
388
389    FREE(intelScreen);
390    sPriv->private = NULL;
391 }
392
393
394 /**
395  * This is called when we need to set up GL rendering to a new X window.
396  */
397 static GLboolean
398 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
399                   __DRIdrawablePrivate * driDrawPriv,
400                   const __GLcontextModes * mesaVis, GLboolean isPixmap)
401 {
402    intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
403
404    if (isPixmap) {
405       return GL_FALSE;          /* not implemented */
406    }
407    else {
408       GLboolean swStencil = (mesaVis->stencilBits > 0 &&
409                              mesaVis->depthBits != 24);
410       GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
411
412       struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
413
414       if (!intel_fb)
415          return GL_FALSE;
416
417       _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
418
419       /* setup the hardware-based renderbuffers */
420       {
421          intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat);
422          _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
423                                 &intel_fb->color_rb[0]->Base);
424       }
425
426       if (mesaVis->doubleBufferMode) {
427          intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat);
428          _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
429                                 &intel_fb->color_rb[1]->Base);
430
431          if (screen->third.handle) {
432             struct gl_renderbuffer *tmp_rb = NULL;
433
434             intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat);
435             _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
436          }
437       }
438
439       if (mesaVis->depthBits == 24) {
440          if (mesaVis->stencilBits == 8) {
441             /* combined depth/stencil buffer */
442             struct intel_renderbuffer *depthStencilRb
443                = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT);
444             /* note: bind RB to two attachment points */
445             _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
446                                    &depthStencilRb->Base);
447             _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
448                                    &depthStencilRb->Base);
449          } else {
450             struct intel_renderbuffer *depthRb
451                = intel_create_renderbuffer(GL_DEPTH_COMPONENT24);
452             _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
453                                    &depthRb->Base);
454          }
455       }
456       else if (mesaVis->depthBits == 16) {
457          /* just 16-bit depth buffer, no hw stencil */
458          struct intel_renderbuffer *depthRb
459             = intel_create_renderbuffer(GL_DEPTH_COMPONENT16);
460          _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
461       }
462
463       /* now add any/all software-based renderbuffers we may need */
464       _mesa_add_soft_renderbuffers(&intel_fb->Base,
465                                    GL_FALSE, /* never sw color */
466                                    GL_FALSE, /* never sw depth */
467                                    swStencil, mesaVis->accumRedBits > 0,
468                                    GL_FALSE, /* never sw alpha */
469                                    GL_FALSE  /* never sw aux */ );
470       driDrawPriv->driverPrivate = (void *) intel_fb;
471
472       return GL_TRUE;
473    }
474 }
475
476 static void
477 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
478 {
479    _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
480 }
481
482
483 /**
484  * Get information about previous buffer swaps.
485  */
486 static int
487 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
488 {
489    struct intel_framebuffer *intel_fb;
490
491    if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
492        || (sInfo == NULL)) {
493       return -1;
494    }
495
496    intel_fb = dPriv->driverPrivate;
497    sInfo->swap_count = intel_fb->swap_count;
498    sInfo->swap_ust = intel_fb->swap_ust;
499    sInfo->swap_missed_count = intel_fb->swap_missed_count;
500
501    sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
502       ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)
503       : 0.0;
504
505    return 0;
506 }
507
508
509 /* There are probably better ways to do this, such as an
510  * init-designated function to register chipids and createcontext
511  * functions.
512  */
513 extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
514                                    __DRIcontextPrivate * driContextPriv,
515                                    void *sharedContextPrivate);
516
517 extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
518                                    __DRIcontextPrivate * driContextPriv,
519                                    void *sharedContextPrivate);
520 extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis,
521                                   __DRIcontextPrivate * driContextPriv,
522                                   void *sharedContextPrivate);
523
524 static GLboolean
525 intelCreateContext(const __GLcontextModes * mesaVis,
526                    __DRIcontextPrivate * driContextPriv,
527                    void *sharedContextPrivate)
528 {
529    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
530    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
531
532 #ifdef I915
533    if (IS_9XX(intelScreen->deviceID)) {
534       if (!IS_965(intelScreen->deviceID)) {
535          return i915CreateContext(mesaVis, driContextPriv,
536                                   sharedContextPrivate);
537       }
538    } else {
539       return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
540    }
541 #else
542    if (IS_965(intelScreen->deviceID))
543       return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate);
544 #endif
545    fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
546    return GL_FALSE;
547 }
548
549
550 static const struct __DriverAPIRec intelAPI = {
551    .DestroyScreen = intelDestroyScreen,
552    .CreateContext = intelCreateContext,
553    .DestroyContext = intelDestroyContext,
554    .CreateBuffer = intelCreateBuffer,
555    .DestroyBuffer = intelDestroyBuffer,
556    .SwapBuffers = intelSwapBuffers,
557    .MakeCurrent = intelMakeCurrent,
558    .UnbindContext = intelUnbindContext,
559    .GetSwapInfo = intelGetSwapInfo,
560    .GetMSC = driGetMSC32,
561    .GetDrawableMSC = driDrawableGetMSC32,
562    .WaitForMSC = driWaitForMSC32,
563    .WaitForSBC = NULL,
564    .SwapBuffersMSC = NULL,
565    .CopySubBuffer = intelCopySubBuffer,
566 #ifdef I915
567    .setTexOffset = intelSetTexOffset,
568 #endif
569 };
570
571
572 static __GLcontextModes *
573 intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
574                  unsigned stencil_bits, GLboolean have_back_buffer)
575 {
576    __GLcontextModes *modes;
577    __GLcontextModes *m;
578    unsigned num_modes;
579    unsigned depth_buffer_factor;
580    unsigned back_buffer_factor;
581    GLenum fb_format;
582    GLenum fb_type;
583
584    /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
585     * support pageflipping at all.
586     */
587    static const GLenum back_buffer_modes[] = {
588       GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
589    };
590
591    u_int8_t depth_bits_array[3];
592    u_int8_t stencil_bits_array[3];
593
594
595    depth_bits_array[0] = 0;
596    depth_bits_array[1] = depth_bits;
597    depth_bits_array[2] = depth_bits;
598
599    /* Just like with the accumulation buffer, always provide some modes
600     * with a stencil buffer.  It will be a sw fallback, but some apps won't
601     * care about that.
602     */
603    stencil_bits_array[0] = 0;
604    stencil_bits_array[1] = 0;
605    if (depth_bits == 24)
606       stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
607
608    stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
609
610    depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
611    back_buffer_factor = (have_back_buffer) ? 3 : 1;
612
613    num_modes = depth_buffer_factor * back_buffer_factor * 4;
614
615    if (pixel_bits == 16) {
616       fb_format = GL_RGB;
617       fb_type = GL_UNSIGNED_SHORT_5_6_5;
618    }
619    else {
620       fb_format = GL_BGRA;
621       fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
622    }
623
624    modes =
625       (*dri_interface->createContextModes) (num_modes,
626                                             sizeof(__GLcontextModes));
627    m = modes;
628    if (!driFillInModes(&m, fb_format, fb_type,
629                        depth_bits_array, stencil_bits_array,
630                        depth_buffer_factor, back_buffer_modes,
631                        back_buffer_factor, GLX_TRUE_COLOR)) {
632       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
633               __LINE__);
634       return NULL;
635    }
636    if (!driFillInModes(&m, fb_format, fb_type,
637                        depth_bits_array, stencil_bits_array,
638                        depth_buffer_factor, back_buffer_modes,
639                        back_buffer_factor, GLX_DIRECT_COLOR)) {
640       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
641               __LINE__);
642       return NULL;
643    }
644
645    /* Mark the visual as slow if there are "fake" stencil bits.
646     */
647    for (m = modes; m != NULL; m = m->next) {
648       if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
649          m->visualRating = GLX_SLOW_CONFIG;
650       }
651    }
652
653    return modes;
654 }
655
656
657 /**
658  * This is the driver specific part of the createNewScreen entry point.
659  * 
660  * \todo maybe fold this into intelInitDriver
661  *
662  * \return the __GLcontextModes supported by this driver
663  */
664 PUBLIC __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
665 {
666 #ifdef I915
667    static const __DRIversion ddx_expected = { 1, 5, 0 };
668 #else
669    static const __DRIversion ddx_expected = { 1, 6, 0 };
670 #endif
671    static const __DRIversion dri_expected = { 4, 0, 0 };
672    static const __DRIversion drm_expected = { 1, 5, 0 };
673    I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
674
675    psp->DriverAPI = intelAPI;
676
677    if (!driCheckDriDdxDrmVersions2("i915",
678                                    &psp->dri_version, &dri_expected,
679                                    &psp->ddx_version, &ddx_expected,
680                                    &psp->drm_version, &drm_expected)) {
681       return NULL;
682    }
683
684    /* Calling driInitExtensions here, with a NULL context pointer,
685     * does not actually enable the extensions.  It just makes sure
686     * that all the dispatch offsets for all the extensions that
687     * *might* be enables are known.  This is needed because the
688     * dispatch offsets need to be known when _mesa_context_create is
689     * called, but we can't enable the extensions until we have a
690     * context pointer.
691     *
692     * Hello chicken.  Hello egg.  How are you two today?
693     */
694    driInitExtensions(NULL, card_extensions, GL_FALSE);
695    driInitExtensions(NULL, ttm_extensions, GL_FALSE);
696
697    if (!intelInitDriver(psp))
698        return NULL;
699
700    return intelFillInModes(dri_priv->cpp * 8,
701                            (dri_priv->cpp == 2) ? 16 : 24,
702                            (dri_priv->cpp == 2) ? 0  : 8, 1);
703 }
704
705 struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
706 {
707   /*
708    * This should probably change to have the screen allocate a dummy
709    * context at screen creation. For now just use the current context.
710    */
711
712   GET_CURRENT_CONTEXT(ctx);
713   if (ctx == NULL) {
714      _mesa_problem(NULL, "No current context in intelScreenContext\n");
715      return NULL;
716   }
717   return intel_context(ctx);
718 }
719