intel_screen.c revision 180b41594c669574355b54ceb2c2ff96889bf336
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#include "intel_bufmgr_ttm.h"
53
54PUBLIC const char __driConfigOptions[] =
55   DRI_CONF_BEGIN
56   DRI_CONF_SECTION_PERFORMANCE
57      DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
58      DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
59      /* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
60       * DRI_CONF_BO_REUSE_ALL
61       */
62      DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 0, "0:1")
63	 DRI_CONF_DESC_BEGIN(en, "Buffer object reuse")
64	    DRI_CONF_ENUM(0, "Disable buffer object reuse")
65	    DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
66	 DRI_CONF_DESC_END
67      DRI_CONF_OPT_END
68   DRI_CONF_SECTION_END
69   DRI_CONF_SECTION_QUALITY
70      DRI_CONF_FORCE_S3TC_ENABLE(false)
71      DRI_CONF_ALLOW_LARGE_TEXTURES(1)
72   DRI_CONF_SECTION_END
73   DRI_CONF_SECTION_DEBUG
74     DRI_CONF_NO_RAST(false)
75   DRI_CONF_SECTION_END
76DRI_CONF_END;
77
78const GLuint __driNConfigOptions = 6;
79
80#ifdef USE_NEW_INTERFACE
81static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
82#endif /*USE_NEW_INTERFACE */
83
84/**
85 * Map all the memory regions described by the screen.
86 * \return GL_TRUE if success, GL_FALSE if error.
87 */
88GLboolean
89intelMapScreenRegions(__DRIscreenPrivate * sPriv)
90{
91   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
92
93   if (intelScreen->front.handle) {
94      if (drmMap(sPriv->fd,
95                 intelScreen->front.handle,
96                 intelScreen->front.size,
97                 (drmAddress *) & intelScreen->front.map) != 0) {
98         _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
99         return GL_FALSE;
100      }
101   }
102   else {
103      _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
104   }
105
106   if (0)
107      _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
108   if (drmMap(sPriv->fd,
109              intelScreen->back.handle,
110              intelScreen->back.size,
111              (drmAddress *) & intelScreen->back.map) != 0) {
112      intelUnmapScreenRegions(intelScreen);
113      return GL_FALSE;
114   }
115
116   if (intelScreen->third.handle) {
117      if (0)
118	 _mesa_printf("Third 0x%08x ", intelScreen->third.handle);
119      if (drmMap(sPriv->fd,
120		 intelScreen->third.handle,
121		 intelScreen->third.size,
122		 (drmAddress *) & intelScreen->third.map) != 0) {
123	 intelUnmapScreenRegions(intelScreen);
124	 return GL_FALSE;
125      }
126   }
127
128   if (0)
129      _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
130   if (drmMap(sPriv->fd,
131              intelScreen->depth.handle,
132              intelScreen->depth.size,
133              (drmAddress *) & intelScreen->depth.map) != 0) {
134      intelUnmapScreenRegions(intelScreen);
135      return GL_FALSE;
136   }
137
138   if (0)
139      _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
140   if (intelScreen->tex.size != 0) {
141      if (drmMap(sPriv->fd,
142		 intelScreen->tex.handle,
143		 intelScreen->tex.size,
144		 (drmAddress *) & intelScreen->tex.map) != 0) {
145	 intelUnmapScreenRegions(intelScreen);
146	 return GL_FALSE;
147      }
148   }
149
150   if (0)
151      printf("Mappings:  front: %p  back: %p  third: %p  depth: %p  tex: %p\n",
152             intelScreen->front.map,
153             intelScreen->back.map, intelScreen->third.map,
154             intelScreen->depth.map, intelScreen->tex.map);
155   return GL_TRUE;
156}
157
158void
159intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
160{
161#define REALLY_UNMAP 1
162   if (intelScreen->front.map) {
163#if REALLY_UNMAP
164      if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
165         printf("drmUnmap front failed!\n");
166#endif
167      intelScreen->front.map = NULL;
168   }
169   if (intelScreen->back.map) {
170#if REALLY_UNMAP
171      if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
172         printf("drmUnmap back failed!\n");
173#endif
174      intelScreen->back.map = NULL;
175   }
176   if (intelScreen->third.map) {
177#if REALLY_UNMAP
178      if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0)
179         printf("drmUnmap third failed!\n");
180#endif
181      intelScreen->third.map = NULL;
182   }
183   if (intelScreen->depth.map) {
184#if REALLY_UNMAP
185      drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
186      intelScreen->depth.map = NULL;
187#endif
188   }
189   if (intelScreen->tex.map) {
190#if REALLY_UNMAP
191      drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
192      intelScreen->tex.map = NULL;
193#endif
194   }
195}
196
197
198static void
199intelPrintDRIInfo(intelScreenPrivate * intelScreen,
200                  __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
201{
202   fprintf(stderr, "*** Front size:   0x%x  offset: 0x%x  pitch: %d\n",
203           intelScreen->front.size, intelScreen->front.offset,
204           intelScreen->pitch);
205   fprintf(stderr, "*** Back size:    0x%x  offset: 0x%x  pitch: %d\n",
206           intelScreen->back.size, intelScreen->back.offset,
207           intelScreen->pitch);
208   fprintf(stderr, "*** Depth size:   0x%x  offset: 0x%x  pitch: %d\n",
209           intelScreen->depth.size, intelScreen->depth.offset,
210           intelScreen->pitch);
211   fprintf(stderr, "*** Texture size: 0x%x  offset: 0x%x\n",
212           intelScreen->tex.size, intelScreen->tex.offset);
213   fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
214}
215
216
217static void
218intelPrintSAREA(const struct drm_i915_sarea * sarea)
219{
220   fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width,
221           sarea->height);
222   fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
223   fprintf(stderr,
224           "SAREA: front offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
225           sarea->front_offset, sarea->front_size,
226           (unsigned) sarea->front_handle);
227   fprintf(stderr,
228           "SAREA: back  offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
229           sarea->back_offset, sarea->back_size,
230           (unsigned) sarea->back_handle);
231   fprintf(stderr, "SAREA: depth offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
232           sarea->depth_offset, sarea->depth_size,
233           (unsigned) sarea->depth_handle);
234   fprintf(stderr, "SAREA: tex   offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
235           sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
236}
237
238
239/**
240 * A number of the screen parameters are obtained/computed from
241 * information in the SAREA.  This function updates those parameters.
242 */
243void
244intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
245                           struct drm_i915_sarea * sarea)
246{
247   intelScreen->width = sarea->width;
248   intelScreen->height = sarea->height;
249   intelScreen->pitch = sarea->pitch;
250
251   intelScreen->front.offset = sarea->front_offset;
252   intelScreen->front.handle = sarea->front_handle;
253   intelScreen->front.size = sarea->front_size;
254   intelScreen->front.tiled = sarea->front_tiled;
255
256   intelScreen->back.offset = sarea->back_offset;
257   intelScreen->back.handle = sarea->back_handle;
258   intelScreen->back.size = sarea->back_size;
259   intelScreen->back.tiled = sarea->back_tiled;
260
261   if (intelScreen->driScrnPriv->ddx_version.minor >= 8) {
262      intelScreen->third.offset = sarea->third_offset;
263      intelScreen->third.handle = sarea->third_handle;
264      intelScreen->third.size = sarea->third_size;
265      intelScreen->third.tiled = sarea->third_tiled;
266   }
267
268   intelScreen->depth.offset = sarea->depth_offset;
269   intelScreen->depth.handle = sarea->depth_handle;
270   intelScreen->depth.size = sarea->depth_size;
271   intelScreen->depth.tiled = sarea->depth_tiled;
272
273   if (intelScreen->driScrnPriv->ddx_version.minor >= 9) {
274      intelScreen->front.bo_handle = sarea->front_bo_handle;
275      intelScreen->back.bo_handle = sarea->back_bo_handle;
276      intelScreen->third.bo_handle = sarea->third_bo_handle;
277      intelScreen->depth.bo_handle = sarea->depth_bo_handle;
278   } else {
279      intelScreen->front.bo_handle = -1;
280      intelScreen->back.bo_handle = -1;
281      intelScreen->third.bo_handle = -1;
282      intelScreen->depth.bo_handle = -1;
283   }
284
285   intelScreen->tex.offset = sarea->tex_offset;
286   intelScreen->logTextureGranularity = sarea->log_tex_granularity;
287   intelScreen->tex.handle = sarea->tex_handle;
288   intelScreen->tex.size = sarea->tex_size;
289
290   if (0)
291      intelPrintSAREA(sarea);
292}
293
294static void
295intelHandleDrawableConfig(__DRIdrawablePrivate *dPriv,
296			  __DRIcontextPrivate *pcp,
297			  __DRIDrawableConfigEvent *event)
298{
299   struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
300   struct intel_region *region = NULL;
301   struct intel_renderbuffer *rb, *depth_rb, *stencil_rb;
302   struct intel_context *intel = pcp->driverPrivate;
303   int cpp, pitch;
304
305   cpp = intel->ctx.Visual.rgbBits / 8;
306   pitch = ((cpp * dPriv->w + 63) & ~63) / cpp;
307
308   rb = intel_fb->color_rb[1];
309   if (rb) {
310      region = intel_region_alloc(intel, cpp, pitch, dPriv->h);
311      intel_renderbuffer_set_region(rb, region);
312   }
313
314   rb = intel_fb->color_rb[2];
315   if (rb) {
316      region = intel_region_alloc(intel, cpp, pitch, dPriv->h);
317      intel_renderbuffer_set_region(rb, region);
318   }
319
320   depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
321   stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
322   if (depth_rb || stencil_rb)
323      region = intel_region_alloc(intel, cpp, pitch, dPriv->h);
324   if (depth_rb)
325      intel_renderbuffer_set_region(depth_rb, region);
326   if (stencil_rb)
327      intel_renderbuffer_set_region(stencil_rb, region);
328
329   /* FIXME: Tell the X server about the regions we just allocated and
330    * attached. */
331}
332
333#define BUFFER_FLAG_TILED 0x0100
334
335static void
336intelHandleBufferAttach(__DRIdrawablePrivate *dPriv,
337			__DRIcontextPrivate *pcp,
338			__DRIBufferAttachEvent *ba)
339{
340   struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
341   struct intel_renderbuffer *rb;
342   struct intel_region *region;
343   struct intel_context *intel = pcp->driverPrivate;
344   GLuint tiled;
345
346   switch (ba->buffer.attachment) {
347   case DRI_DRAWABLE_BUFFER_FRONT_LEFT:
348      rb = intel_fb->color_rb[0];
349      break;
350
351   case DRI_DRAWABLE_BUFFER_BACK_LEFT:
352      rb = intel_fb->color_rb[0];
353      break;
354
355   case DRI_DRAWABLE_BUFFER_DEPTH:
356     rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
357     break;
358
359   case DRI_DRAWABLE_BUFFER_STENCIL:
360     rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
361     break;
362
363   case DRI_DRAWABLE_BUFFER_ACCUM:
364   default:
365      fprintf(stderr, "unhandled buffer attach event, attacment type %d\n",
366	      ba->buffer.attachment);
367      return;
368   }
369
370#if 0
371   /* FIXME: Add this so we can filter out when the X server sends us
372    * attachment events for the buffers we just allocated.  Need to
373    * get the BO handle for a render buffer. */
374   if (intel_renderbuffer_get_region_handle(rb) == ba->buffer.handle)
375      return;
376#endif
377
378   tiled = (ba->buffer.flags & BUFFER_FLAG_TILED) > 0;
379   region = intel_region_alloc_for_handle(intel, ba->buffer.cpp,
380					  ba->buffer.pitch / ba->buffer.cpp,
381					  dPriv->h, tiled,
382					  ba->buffer.handle);
383
384   intel_renderbuffer_set_region(rb, region);
385}
386
387static const __DRItexOffsetExtension intelTexOffsetExtension = {
388   { __DRI_TEX_OFFSET },
389   intelSetTexOffset,
390};
391
392static const __DRItexBufferExtension intelTexBufferExtension = {
393    { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
394   intelSetTexBuffer,
395};
396
397static const __DRIextension *intelExtensions[] = {
398    &driReadDrawableExtension,
399    &driCopySubBufferExtension.base,
400    &driSwapControlExtension.base,
401    &driFrameTrackingExtension.base,
402    &driMediaStreamCounterExtension.base,
403    &intelTexOffsetExtension.base,
404    &intelTexBufferExtension.base,
405    NULL
406};
407
408static GLboolean
409intel_get_param(__DRIscreenPrivate *psp, int param, int *value)
410{
411   int ret;
412   struct drm_i915_getparam gp;
413
414   gp.param = param;
415   gp.value = value;
416
417   ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
418   if (ret) {
419      fprintf(stderr, "drm_i915_getparam: %d\n", ret);
420      return GL_FALSE;
421   }
422
423   return GL_TRUE;
424}
425
426static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
427{
428   intelScreenPrivate *intelScreen;
429   I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
430   struct drm_i915_sarea *sarea;
431
432   if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
433      fprintf(stderr,
434              "\nERROR!  sizeof(I830DRIRec) does not match passed size from device driver\n");
435      return GL_FALSE;
436   }
437
438   /* Allocate the private area */
439   intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
440   if (!intelScreen) {
441      fprintf(stderr, "\nERROR!  Allocating private area failed\n");
442      return GL_FALSE;
443   }
444   /* parse information in __driConfigOptions */
445   driParseOptionInfo(&intelScreen->optionCache,
446                      __driConfigOptions, __driNConfigOptions);
447
448   intelScreen->driScrnPriv = sPriv;
449   sPriv->private = (void *) intelScreen;
450   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
451   sarea = (struct drm_i915_sarea *)
452      (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
453
454   intelScreen->deviceID = gDRIPriv->deviceID;
455
456   intelUpdateScreenFromSAREA(intelScreen, sarea);
457
458   if (!intelMapScreenRegions(sPriv)) {
459      fprintf(stderr, "\nERROR!  mapping regions\n");
460      _mesa_free(intelScreen);
461      sPriv->private = NULL;
462      return GL_FALSE;
463   }
464
465   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
466
467   if (0)
468      intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
469
470   intelScreen->drmMinor = sPriv->drm_version.minor;
471
472   /* Determine if IRQs are active? */
473   if (!intel_get_param(sPriv, I915_PARAM_IRQ_ACTIVE,
474			&intelScreen->irq_active))
475      return GL_FALSE;
476
477   /* Determine if batchbuffers are allowed */
478   if (!intel_get_param(sPriv, I915_PARAM_ALLOW_BATCHBUFFER,
479			&intelScreen->allow_batchbuffer))
480      return GL_FALSE;
481
482   sPriv->extensions = intelExtensions;
483
484   return GL_TRUE;
485}
486
487
488static void
489intelDestroyScreen(__DRIscreenPrivate * sPriv)
490{
491   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
492
493   intelUnmapScreenRegions(intelScreen);
494
495   FREE(intelScreen);
496   sPriv->private = NULL;
497}
498
499
500/**
501 * This is called when we need to set up GL rendering to a new X window.
502 */
503static GLboolean
504intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
505                  __DRIdrawablePrivate * driDrawPriv,
506                  const __GLcontextModes * mesaVis, GLboolean isPixmap)
507{
508   intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
509
510   if (isPixmap) {
511      return GL_FALSE;          /* not implemented */
512   }
513   else {
514      GLboolean swStencil = (mesaVis->stencilBits > 0 &&
515                             mesaVis->depthBits != 24);
516      GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
517
518      struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
519
520      if (!intel_fb)
521	 return GL_FALSE;
522
523      _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
524
525      /* setup the hardware-based renderbuffers */
526      {
527         intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat);
528         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
529				&intel_fb->color_rb[0]->Base);
530      }
531
532      if (mesaVis->doubleBufferMode) {
533         intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat);
534         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
535				&intel_fb->color_rb[1]->Base);
536
537	 if (screen->third.handle) {
538	    struct gl_renderbuffer *tmp_rb = NULL;
539
540	    intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat);
541	    _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
542	 }
543      }
544
545      if (mesaVis->depthBits == 24) {
546	 if (mesaVis->stencilBits == 8) {
547	    /* combined depth/stencil buffer */
548	    struct intel_renderbuffer *depthStencilRb
549	       = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT);
550	    /* note: bind RB to two attachment points */
551	    _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
552				   &depthStencilRb->Base);
553	    _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
554				   &depthStencilRb->Base);
555	 } else {
556	    struct intel_renderbuffer *depthRb
557	       = intel_create_renderbuffer(GL_DEPTH_COMPONENT24);
558	    _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
559				   &depthRb->Base);
560	 }
561      }
562      else if (mesaVis->depthBits == 16) {
563         /* just 16-bit depth buffer, no hw stencil */
564         struct intel_renderbuffer *depthRb
565            = intel_create_renderbuffer(GL_DEPTH_COMPONENT16);
566         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
567      }
568
569      /* now add any/all software-based renderbuffers we may need */
570      _mesa_add_soft_renderbuffers(&intel_fb->Base,
571                                   GL_FALSE, /* never sw color */
572                                   GL_FALSE, /* never sw depth */
573                                   swStencil, mesaVis->accumRedBits > 0,
574                                   GL_FALSE, /* never sw alpha */
575                                   GL_FALSE  /* never sw aux */ );
576      driDrawPriv->driverPrivate = (void *) intel_fb;
577
578      return GL_TRUE;
579   }
580}
581
582static void
583intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
584{
585   _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
586}
587
588
589/**
590 * Get information about previous buffer swaps.
591 */
592static int
593intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
594{
595   struct intel_framebuffer *intel_fb;
596
597   if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
598       || (sInfo == NULL)) {
599      return -1;
600   }
601
602   intel_fb = dPriv->driverPrivate;
603   sInfo->swap_count = intel_fb->swap_count;
604   sInfo->swap_ust = intel_fb->swap_ust;
605   sInfo->swap_missed_count = intel_fb->swap_missed_count;
606
607   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
608      ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)
609      : 0.0;
610
611   return 0;
612}
613
614
615/* There are probably better ways to do this, such as an
616 * init-designated function to register chipids and createcontext
617 * functions.
618 */
619extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
620                                   __DRIcontextPrivate * driContextPriv,
621                                   void *sharedContextPrivate);
622
623extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
624                                   __DRIcontextPrivate * driContextPriv,
625                                   void *sharedContextPrivate);
626extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis,
627				  __DRIcontextPrivate * driContextPriv,
628				  void *sharedContextPrivate);
629
630static GLboolean
631intelCreateContext(const __GLcontextModes * mesaVis,
632                   __DRIcontextPrivate * driContextPriv,
633                   void *sharedContextPrivate)
634{
635   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
636   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
637
638#ifdef I915
639   if (IS_9XX(intelScreen->deviceID)) {
640      if (!IS_965(intelScreen->deviceID)) {
641	 return i915CreateContext(mesaVis, driContextPriv,
642				  sharedContextPrivate);
643      }
644   } else {
645      return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
646   }
647#else
648   if (IS_965(intelScreen->deviceID))
649      return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate);
650#endif
651   fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
652   return GL_FALSE;
653}
654
655
656static const struct __DriverAPIRec intelAPI = {
657   .DestroyScreen = intelDestroyScreen,
658   .CreateContext = intelCreateContext,
659   .DestroyContext = intelDestroyContext,
660   .CreateBuffer = intelCreateBuffer,
661   .DestroyBuffer = intelDestroyBuffer,
662   .SwapBuffers = intelSwapBuffers,
663   .MakeCurrent = intelMakeCurrent,
664   .UnbindContext = intelUnbindContext,
665   .GetSwapInfo = intelGetSwapInfo,
666   .GetDrawableMSC = driDrawableGetMSC32,
667   .WaitForMSC = driWaitForMSC32,
668   .WaitForSBC = NULL,
669   .SwapBuffersMSC = NULL,
670   .CopySubBuffer = intelCopySubBuffer,
671
672   .HandleDrawableConfig = intelHandleDrawableConfig,
673   .HandleBufferAttach = intelHandleBufferAttach,
674};
675
676
677static __GLcontextModes *
678intelFillInModes(__DRIscreenPrivate *psp,
679		 unsigned pixel_bits, unsigned depth_bits,
680                 unsigned stencil_bits, GLboolean have_back_buffer)
681{
682   __GLcontextModes *modes;
683   __GLcontextModes *m;
684   unsigned num_modes;
685   unsigned depth_buffer_factor;
686   unsigned back_buffer_factor;
687   GLenum fb_format;
688   GLenum fb_type;
689
690   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
691    * support pageflipping at all.
692    */
693   static const GLenum back_buffer_modes[] = {
694      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
695   };
696
697   u_int8_t depth_bits_array[3];
698   u_int8_t stencil_bits_array[3];
699
700
701   depth_bits_array[0] = 0;
702   depth_bits_array[1] = depth_bits;
703   depth_bits_array[2] = depth_bits;
704
705   /* Just like with the accumulation buffer, always provide some modes
706    * with a stencil buffer.  It will be a sw fallback, but some apps won't
707    * care about that.
708    */
709   stencil_bits_array[0] = 0;
710   stencil_bits_array[1] = 0;
711   if (depth_bits == 24)
712      stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
713
714   stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
715
716   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
717   back_buffer_factor = (have_back_buffer) ? 3 : 1;
718
719   num_modes = depth_buffer_factor * back_buffer_factor * 4;
720
721   if (pixel_bits == 16) {
722      fb_format = GL_RGB;
723      fb_type = GL_UNSIGNED_SHORT_5_6_5;
724   }
725   else {
726      fb_format = GL_BGRA;
727      fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
728   }
729
730   modes =
731      (*psp->contextModes->createContextModes) (num_modes,
732						sizeof(__GLcontextModes));
733   m = modes;
734   if (!driFillInModes(&m, fb_format, fb_type,
735                       depth_bits_array, stencil_bits_array,
736                       depth_buffer_factor, back_buffer_modes,
737                       back_buffer_factor, GLX_TRUE_COLOR)) {
738      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
739              __LINE__);
740      return NULL;
741   }
742   if (!driFillInModes(&m, fb_format, fb_type,
743                       depth_bits_array, stencil_bits_array,
744                       depth_buffer_factor, back_buffer_modes,
745                       back_buffer_factor, GLX_DIRECT_COLOR)) {
746      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
747              __LINE__);
748      return NULL;
749   }
750
751   /* Mark the visual as slow if there are "fake" stencil bits.
752    */
753   for (m = modes; m != NULL; m = m->next) {
754      if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
755         m->visualRating = GLX_SLOW_CONFIG;
756      }
757   }
758
759   return modes;
760}
761
762
763/**
764 * This is the driver specific part of the createNewScreen entry point.
765 *
766 * \todo maybe fold this into intelInitDriver
767 *
768 * \return the __GLcontextModes supported by this driver
769 */
770PUBLIC __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
771{
772#ifdef I915
773   static const __DRIversion ddx_expected = { 1, 5, 0 };
774#else
775   static const __DRIversion ddx_expected = { 1, 6, 0 };
776#endif
777   static const __DRIversion dri_expected = { 4, 0, 0 };
778   static const __DRIversion drm_expected = { 1, 5, 0 };
779   I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
780
781   psp->DriverAPI = intelAPI;
782
783   if (!driCheckDriDdxDrmVersions2("i915",
784                                   &psp->dri_version, &dri_expected,
785                                   &psp->ddx_version, &ddx_expected,
786                                   &psp->drm_version, &drm_expected)) {
787      return NULL;
788   }
789
790   /* Calling driInitExtensions here, with a NULL context pointer,
791    * does not actually enable the extensions.  It just makes sure
792    * that all the dispatch offsets for all the extensions that
793    * *might* be enables are known.  This is needed because the
794    * dispatch offsets need to be known when _mesa_context_create is
795    * called, but we can't enable the extensions until we have a
796    * context pointer.
797    *
798    * Hello chicken.  Hello egg.  How are you two today?
799    */
800   intelInitExtensions(NULL, GL_TRUE);
801
802   if (!intelInitDriver(psp))
803       return NULL;
804
805   return intelFillInModes(psp, dri_priv->cpp * 8,
806			   (dri_priv->cpp == 2) ? 16 : 24,
807			   (dri_priv->cpp == 2) ? 0  : 8, 1);
808}
809
810struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
811{
812  /*
813   * This should probably change to have the screen allocate a dummy
814   * context at screen creation. For now just use the current context.
815   */
816
817  GET_CURRENT_CONTEXT(ctx);
818  if (ctx == NULL) {
819     _mesa_problem(NULL, "No current context in intelScreenContext\n");
820     return NULL;
821  }
822  return intel_context(ctx);
823}
824
825/**
826 * This is the driver specific part of the createNewScreen entry point.
827 *
828 * \return the __GLcontextModes supported by this driver
829 */
830PUBLIC __GLcontextModes *__dri2DriverInitScreen(__DRIscreenPrivate *psp)
831{
832   intelScreenPrivate *intelScreen;
833   __GLcontextModes *modes, *m;
834
835   psp->DriverAPI = intelAPI;
836
837   /* Calling driInitExtensions here, with a NULL context pointer,
838    * does not actually enable the extensions.  It just makes sure
839    * that all the dispatch offsets for all the extensions that
840    * *might* be enables are known.  This is needed because the
841    * dispatch offsets need to be known when _mesa_context_create is
842    * called, but we can't enable the extensions until we have a
843    * context pointer.
844    *
845    * Hello chicken.  Hello egg.  How are you two today?
846    */
847   intelInitExtensions(NULL, GL_TRUE);
848
849   /* Allocate the private area */
850   intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
851   if (!intelScreen) {
852      fprintf(stderr, "\nERROR!  Allocating private area failed\n");
853      return GL_FALSE;
854   }
855   /* parse information in __driConfigOptions */
856   driParseOptionInfo(&intelScreen->optionCache,
857                      __driConfigOptions, __driNConfigOptions);
858
859   intelScreen->driScrnPriv = psp;
860   psp->private = (void *) intelScreen;
861
862   intelScreen->drmMinor = psp->drm_version.minor;
863
864   /* Determine chipset ID? */
865   if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID,
866			&intelScreen->deviceID))
867      return GL_FALSE;
868
869   /* Determine if IRQs are active? */
870   if (!intel_get_param(psp, I915_PARAM_IRQ_ACTIVE,
871			&intelScreen->irq_active))
872      return GL_FALSE;
873
874   /* Determine if batchbuffers are allowed */
875   if (!intel_get_param(psp, I915_PARAM_ALLOW_BATCHBUFFER,
876			&intelScreen->allow_batchbuffer))
877      return GL_FALSE;
878
879   if (!intelScreen->allow_batchbuffer) {
880      fprintf(stderr, "batch buffer not allowed\n");
881      return GL_FALSE;
882   }
883
884   psp->extensions = intelExtensions;
885
886   modes = intelFillInModes(psp, 16, 16, 0, 1);
887   for (m = modes; m->next != NULL; m = m->next)
888     ;
889   m->next = intelFillInModes(psp, 32, 24, 8, 1);
890
891   return modes;
892}
893