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