intel_screen.c revision 0227d91a9e3cf65aae3266d100eebd3459dff4c3
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.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, 1, "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(2)
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 tiled: %d\n",
225           sarea->front_offset, sarea->front_size,
226           (unsigned) sarea->front_handle, sarea->front_tiled);
227   fprintf(stderr,
228           "SAREA: back  offset: 0x%08x  size: 0x%x  handle: 0x%x tiled: %d\n",
229           sarea->back_offset, sarea->back_size,
230           (unsigned) sarea->back_handle, sarea->back_tiled);
231   fprintf(stderr, "SAREA: depth offset: 0x%08x  size: 0x%x  handle: 0x%x tiled: %d\n",
232           sarea->depth_offset, sarea->depth_size,
233           (unsigned) sarea->depth_handle, sarea->depth_tiled);
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 *intelScreenExtensions[] = {
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 = intelScreenExtensions;
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							   screen->ttm ? screen->front.tiled : INTEL_TILE_NONE);
529         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
530				&intel_fb->color_rb[0]->Base);
531      }
532
533      if (mesaVis->doubleBufferMode) {
534         intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat,
535							   screen->ttm ? screen->back.tiled : INTEL_TILE_NONE);
536         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
537				&intel_fb->color_rb[1]->Base);
538
539	 if (screen->third.handle) {
540	    struct gl_renderbuffer *tmp_rb = NULL;
541
542	    intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat,
543							      screen->ttm ? screen->third.tiled : INTEL_TILE_NONE);
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					   screen->ttm ? screen->depth.tiled : INTEL_TILE_NONE);
554	    /* note: bind RB to two attachment points */
555	    _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
556				   &depthStencilRb->Base);
557	    _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
558				   &depthStencilRb->Base);
559	 } else {
560	    struct intel_renderbuffer *depthRb
561	       = intel_create_renderbuffer(GL_DEPTH_COMPONENT24,
562					   screen->ttm ? screen->depth.tiled : INTEL_TILE_NONE);
563	    _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
564				   &depthRb->Base);
565	 }
566      }
567      else if (mesaVis->depthBits == 16) {
568         /* just 16-bit depth buffer, no hw stencil */
569         struct intel_renderbuffer *depthRb
570            = intel_create_renderbuffer(GL_DEPTH_COMPONENT16,
571					screen->ttm ? screen->depth.tiled : INTEL_TILE_NONE);
572         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
573      }
574
575      /* now add any/all software-based renderbuffers we may need */
576      _mesa_add_soft_renderbuffers(&intel_fb->Base,
577                                   GL_FALSE, /* never sw color */
578                                   GL_FALSE, /* never sw depth */
579                                   swStencil, mesaVis->accumRedBits > 0,
580                                   GL_FALSE, /* never sw alpha */
581                                   GL_FALSE  /* never sw aux */ );
582      driDrawPriv->driverPrivate = (void *) intel_fb;
583
584      return GL_TRUE;
585   }
586}
587
588static void
589intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
590{
591   _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
592}
593
594
595/**
596 * Get information about previous buffer swaps.
597 */
598static int
599intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
600{
601   struct intel_framebuffer *intel_fb;
602
603   if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
604       || (sInfo == NULL)) {
605      return -1;
606   }
607
608   intel_fb = dPriv->driverPrivate;
609   sInfo->swap_count = intel_fb->swap_count;
610   sInfo->swap_ust = intel_fb->swap_ust;
611   sInfo->swap_missed_count = intel_fb->swap_missed_count;
612
613   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
614      ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)
615      : 0.0;
616
617   return 0;
618}
619
620
621/* There are probably better ways to do this, such as an
622 * init-designated function to register chipids and createcontext
623 * functions.
624 */
625extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
626                                   __DRIcontextPrivate * driContextPriv,
627                                   void *sharedContextPrivate);
628
629extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
630                                   __DRIcontextPrivate * driContextPriv,
631                                   void *sharedContextPrivate);
632extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis,
633				  __DRIcontextPrivate * driContextPriv,
634				  void *sharedContextPrivate);
635
636static GLboolean
637intelCreateContext(const __GLcontextModes * mesaVis,
638                   __DRIcontextPrivate * driContextPriv,
639                   void *sharedContextPrivate)
640{
641   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
642   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
643
644#ifdef I915
645   if (IS_9XX(intelScreen->deviceID)) {
646      if (!IS_965(intelScreen->deviceID)) {
647	 return i915CreateContext(mesaVis, driContextPriv,
648				  sharedContextPrivate);
649      }
650   } else {
651      return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
652   }
653#else
654   if (IS_965(intelScreen->deviceID))
655      return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate);
656#endif
657   fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
658   return GL_FALSE;
659}
660
661
662static __DRIconfig **
663intelFillInModes(__DRIscreenPrivate *psp,
664		 unsigned pixel_bits, unsigned depth_bits,
665                 unsigned stencil_bits, GLboolean have_back_buffer)
666{
667   __DRIconfig **configs;
668   __GLcontextModes *m;
669   unsigned depth_buffer_factor;
670   unsigned back_buffer_factor;
671   GLenum fb_format;
672   GLenum fb_type;
673   int i;
674
675   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
676    * support pageflipping at all.
677    */
678   static const GLenum back_buffer_modes[] = {
679      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
680   };
681
682   u_int8_t depth_bits_array[3];
683   u_int8_t stencil_bits_array[3];
684
685   depth_bits_array[0] = 0;
686   depth_bits_array[1] = depth_bits;
687   depth_bits_array[2] = depth_bits;
688
689   /* Just like with the accumulation buffer, always provide some modes
690    * with a stencil buffer.  It will be a sw fallback, but some apps won't
691    * care about that.
692    */
693   stencil_bits_array[0] = 0;
694   stencil_bits_array[1] = 0;
695   if (depth_bits == 24)
696      stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
697
698   stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
699
700   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
701   back_buffer_factor = (have_back_buffer) ? 3 : 1;
702
703   if (pixel_bits == 16) {
704      fb_format = GL_RGB;
705      fb_type = GL_UNSIGNED_SHORT_5_6_5;
706   }
707   else {
708      fb_format = GL_BGRA;
709      fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
710   }
711
712   configs = driCreateConfigs(fb_format, fb_type,
713			      depth_bits_array, stencil_bits_array,
714			      depth_buffer_factor, back_buffer_modes,
715			      back_buffer_factor);
716   if (configs == NULL) {
717    fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
718              __LINE__);
719      return NULL;
720   }
721
722   /* Mark the visual as slow if there are "fake" stencil bits.
723    */
724   for (i = 0; configs[i]; i++) {
725      m = &configs[i]->modes;
726      if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
727         m->visualRating = GLX_SLOW_CONFIG;
728      }
729   }
730
731   return configs;
732}
733
734
735/**
736 * This is the driver specific part of the createNewScreen entry point.
737 *
738 * \todo maybe fold this into intelInitDriver
739 *
740 * \return the __GLcontextModes supported by this driver
741 */
742static const __DRIconfig **intelInitScreen(__DRIscreenPrivate *psp)
743{
744#ifdef I915
745   static const __DRIversion ddx_expected = { 1, 5, 0 };
746#else
747   static const __DRIversion ddx_expected = { 1, 6, 0 };
748#endif
749   static const __DRIversion dri_expected = { 4, 0, 0 };
750   static const __DRIversion drm_expected = { 1, 5, 0 };
751   I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
752
753   if (!driCheckDriDdxDrmVersions2("i915",
754                                   &psp->dri_version, &dri_expected,
755                                   &psp->ddx_version, &ddx_expected,
756                                   &psp->drm_version, &drm_expected)) {
757      return NULL;
758   }
759
760   /* Calling driInitExtensions here, with a NULL context pointer,
761    * does not actually enable the extensions.  It just makes sure
762    * that all the dispatch offsets for all the extensions that
763    * *might* be enables are known.  This is needed because the
764    * dispatch offsets need to be known when _mesa_context_create is
765    * called, but we can't enable the extensions until we have a
766    * context pointer.
767    *
768    * Hello chicken.  Hello egg.  How are you two today?
769    */
770   intelInitExtensions(NULL, GL_TRUE);
771
772   if (!intelInitDriver(psp))
773       return NULL;
774
775   psp->extensions = intelScreenExtensions;
776
777   return (const __DRIconfig **)
778       intelFillInModes(psp, dri_priv->cpp * 8,
779			(dri_priv->cpp == 2) ? 16 : 24,
780			(dri_priv->cpp == 2) ? 0  : 8, 1);
781}
782
783struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
784{
785  /*
786   * This should probably change to have the screen allocate a dummy
787   * context at screen creation. For now just use the current context.
788   */
789
790  GET_CURRENT_CONTEXT(ctx);
791  if (ctx == NULL) {
792     _mesa_problem(NULL, "No current context in intelScreenContext\n");
793     return NULL;
794  }
795  return intel_context(ctx);
796}
797
798/**
799 * This is the driver specific part of the createNewScreen entry point.
800 *
801 * \return the __GLcontextModes supported by this driver
802 */
803static const
804__DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp)
805{
806   intelScreenPrivate *intelScreen;
807
808   /* Calling driInitExtensions here, with a NULL context pointer,
809    * does not actually enable the extensions.  It just makes sure
810    * that all the dispatch offsets for all the extensions that
811    * *might* be enables are known.  This is needed because the
812    * dispatch offsets need to be known when _mesa_context_create is
813    * called, but we can't enable the extensions until we have a
814    * context pointer.
815    *
816    * Hello chicken.  Hello egg.  How are you two today?
817    */
818   intelInitExtensions(NULL, GL_TRUE);
819
820   /* Allocate the private area */
821   intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
822   if (!intelScreen) {
823      fprintf(stderr, "\nERROR!  Allocating private area failed\n");
824      return GL_FALSE;
825   }
826   /* parse information in __driConfigOptions */
827   driParseOptionInfo(&intelScreen->optionCache,
828                      __driConfigOptions, __driNConfigOptions);
829
830   intelScreen->driScrnPriv = psp;
831   psp->private = (void *) intelScreen;
832
833   intelScreen->drmMinor = psp->drm_version.minor;
834
835   /* Determine chipset ID? */
836   if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID,
837			&intelScreen->deviceID))
838      return GL_FALSE;
839
840   /* Determine if IRQs are active? */
841   if (!intel_get_param(psp, I915_PARAM_IRQ_ACTIVE,
842			&intelScreen->irq_active))
843      return GL_FALSE;
844
845   /* Determine if batchbuffers are allowed */
846   if (!intel_get_param(psp, I915_PARAM_ALLOW_BATCHBUFFER,
847			&intelScreen->allow_batchbuffer))
848      return GL_FALSE;
849
850   if (!intelScreen->allow_batchbuffer) {
851      fprintf(stderr, "batch buffer not allowed\n");
852      return GL_FALSE;
853   }
854
855   psp->extensions = intelScreenExtensions;
856
857   return driConcatConfigs(intelFillInModes(psp, 16, 16, 0, 1),
858			   intelFillInModes(psp, 32, 24, 8, 1));
859}
860
861const struct __DriverAPIRec driDriverAPI = {
862   .InitScreen		 = intelInitScreen,
863   .DestroyScreen	 = intelDestroyScreen,
864   .CreateContext	 = intelCreateContext,
865   .DestroyContext	 = intelDestroyContext,
866   .CreateBuffer	 = intelCreateBuffer,
867   .DestroyBuffer	 = intelDestroyBuffer,
868   .SwapBuffers		 = intelSwapBuffers,
869   .MakeCurrent		 = intelMakeCurrent,
870   .UnbindContext	 = intelUnbindContext,
871   .GetSwapInfo		 = intelGetSwapInfo,
872   .GetDrawableMSC	 = driDrawableGetMSC32,
873   .WaitForMSC		 = driWaitForMSC32,
874   .CopySubBuffer	 = intelCopySubBuffer,
875
876   .InitScreen2		 = intelInitScreen2,
877   .HandleDrawableConfig = intelHandleDrawableConfig,
878   .HandleBufferAttach	 = intelHandleBufferAttach,
879};
880