intel: Disable creating DRI2 FBconfigs with depth size != color size.
[mesa.git] / src / mesa / drivers / dri / intel / intel_screen.c
index c193830f05fb40dbabeeede87d555656423ea5ce..09eba13aab50c7e0dedf9161d5bda9f5cf74c9cc 100644 (file)
  * 
  **************************************************************************/
 
-#include "glheader.h"
-#include "context.h"
-#include "framebuffer.h"
-#include "matrix.h"
-#include "renderbuffer.h"
-#include "simple_list.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+
 #include "utils.h"
 #include "vblank.h"
 #include "xmlpool.h"
 
-
-#include "intel_screen.h"
-
+#include "intel_batchbuffer.h"
 #include "intel_buffers.h"
-#include "intel_tex.h"
-#include "intel_span.h"
-#include "intel_ioctl.h"
-#include "intel_fbo.h"
+#include "intel_bufmgr.h"
 #include "intel_chipset.h"
+#include "intel_extensions.h"
+#include "intel_fbo.h"
+#include "intel_regions.h"
+#include "intel_swapbuffers.h"
+#include "intel_screen.h"
+#include "intel_span.h"
+#include "intel_tex.h"
 
 #include "i915_drm.h"
 #include "i830_dri.h"
-#include "intel_regions.h"
-#include "intel_batchbuffer.h"
-#include "intel_bufmgr.h"
+
 
 PUBLIC const char __driConfigOptions[] =
    DRI_CONF_BEGIN
@@ -135,7 +134,7 @@ intelPrintDRIInfo(intelScreenPrivate * intelScreen,
 
 
 static void
-intelPrintSAREA(const struct drm_i915_sarea * sarea)
+intelPrintSAREA(const drm_i915_sarea_t * sarea)
 {
    fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width,
            sarea->height);
@@ -160,9 +159,9 @@ intelPrintSAREA(const struct drm_i915_sarea * sarea)
  * A number of the screen parameters are obtained/computed from
  * information in the SAREA.  This function updates those parameters.
  */
-void
+static void
 intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
-                           struct drm_i915_sarea * sarea)
+                           drm_i915_sarea_t * sarea)
 {
    intelScreen->width = sarea->width;
    intelScreen->height = sarea->height;
@@ -178,13 +177,6 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
    intelScreen->back.size = sarea->back_size;
    intelScreen->back.tiled = sarea->back_tiled;
 
-   if (intelScreen->driScrnPriv->ddx_version.minor >= 8) {
-      intelScreen->third.offset = sarea->third_offset;
-      intelScreen->third.handle = sarea->third_handle;
-      intelScreen->third.size = sarea->third_size;
-      intelScreen->third.tiled = sarea->third_tiled;
-   }
-
    intelScreen->depth.offset = sarea->depth_offset;
    intelScreen->depth.handle = sarea->depth_handle;
    intelScreen->depth.size = sarea->depth_size;
@@ -193,12 +185,10 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
    if (intelScreen->driScrnPriv->ddx_version.minor >= 9) {
       intelScreen->front.bo_handle = sarea->front_bo_handle;
       intelScreen->back.bo_handle = sarea->back_bo_handle;
-      intelScreen->third.bo_handle = sarea->third_bo_handle;
       intelScreen->depth.bo_handle = sarea->depth_bo_handle;
    } else {
       intelScreen->front.bo_handle = -1;
       intelScreen->back.bo_handle = -1;
-      intelScreen->third.bo_handle = -1;
       intelScreen->depth.bo_handle = -1;
    }
 
@@ -254,7 +244,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
 {
    intelScreenPrivate *intelScreen;
    I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
-   struct drm_i915_sarea *sarea;
+   drm_i915_sarea_t *sarea;
 
    if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
       fprintf(stderr,
@@ -274,9 +264,9 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
 
    intelScreen->driScrnPriv = sPriv;
    sPriv->private = (void *) intelScreen;
-   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
-   sarea = (struct drm_i915_sarea *)
-      (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
+   sarea = (drm_i915_sarea_t *)
+      (((GLubyte *) sPriv->pSAREA) + gDRIPriv->sarea_priv_offset);
+   intelScreen->sarea = sarea;
 
    intelScreen->deviceID = gDRIPriv->deviceID;
 
@@ -289,8 +279,6 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
       return GL_FALSE;
    }
 
-   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
-
    if (0)
       intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
 
@@ -301,11 +289,6 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
                        &intelScreen->irq_active))
       return GL_FALSE;
 
-   /* Determine if batchbuffers are allowed */
-   if (!intel_get_param(sPriv, I915_PARAM_ALLOW_BATCHBUFFER,
-                       &intelScreen->allow_batchbuffer))
-      return GL_FALSE;
-
    sPriv->extensions = intelScreenExtensions;
 
    return GL_TRUE;
@@ -317,7 +300,9 @@ intelDestroyScreen(__DRIscreenPrivate * sPriv)
 {
    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
 
+   dri_bufmgr_destroy(intelScreen->bufmgr);
    intelUnmapScreenRegions(intelScreen);
+   driDestroyOptionCache(&intelScreen->optionCache);
 
    FREE(intelScreen);
    sPriv->private = NULL;
@@ -332,15 +317,13 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
                   __DRIdrawablePrivate * driDrawPriv,
                   const __GLcontextModes * mesaVis, GLboolean isPixmap)
 {
-   intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
-
    if (isPixmap) {
       return GL_FALSE;          /* not implemented */
    }
    else {
       GLboolean swStencil = (mesaVis->stencilBits > 0 &&
                              mesaVis->depthBits != 24);
-      GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
+      GLenum rgbFormat;
 
       struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
 
@@ -349,6 +332,13 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
 
       _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
 
+      if (mesaVis->redBits == 5)
+        rgbFormat = GL_RGB5;
+      else if (mesaVis->alphaBits == 0)
+        rgbFormat = GL_RGB8;
+      else
+        rgbFormat = GL_RGBA8;
+
       /* setup the hardware-based renderbuffers */
       intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat);
       _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
@@ -360,12 +350,6 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
          _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
                                &intel_fb->color_rb[1]->Base);
 
-        if (screen->third.handle) {
-           struct gl_renderbuffer *tmp_rb = NULL;
-
-           intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat);
-           _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
-        }
       }
 
       if (mesaVis->depthBits == 24) {
@@ -468,6 +452,7 @@ intelCreateContext(const __GLcontextModes * mesaVis,
                                  sharedContextPrivate);
       }
    } else {
+      intelScreen->no_vbo = GL_TRUE;
       return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
    }
 #else
@@ -488,8 +473,6 @@ intelFillInModes(__DRIscreenPrivate *psp,
    __GLcontextModes *m;
    unsigned depth_buffer_factor;
    unsigned back_buffer_factor;
-   GLenum fb_format;
-   GLenum fb_type;
    int i;
 
    /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
@@ -499,8 +482,9 @@ intelFillInModes(__DRIscreenPrivate *psp,
       GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
    };
 
-   u_int8_t depth_bits_array[3];
-   u_int8_t stencil_bits_array[3];
+   uint8_t depth_bits_array[3];
+   uint8_t stencil_bits_array[3];
+   uint8_t msaa_samples_array[1];
 
    depth_bits_array[0] = 0;
    depth_bits_array[1] = depth_bits;
@@ -517,22 +501,39 @@ intelFillInModes(__DRIscreenPrivate *psp,
 
    stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
 
+   msaa_samples_array[0] = 0;
+
    depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
    back_buffer_factor = (have_back_buffer) ? 3 : 1;
 
    if (pixel_bits == 16) {
-      fb_format = GL_RGB;
-      fb_type = GL_UNSIGNED_SHORT_5_6_5;
+      configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+                                depth_bits_array, stencil_bits_array,
+                                depth_buffer_factor, back_buffer_modes,
+                                back_buffer_factor,
+                                msaa_samples_array, 1);
    }
    else {
-      fb_format = GL_BGRA;
-      fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+      __DRIconfig **configs_a8r8g8b8;
+      __DRIconfig **configs_x8r8g8b8;
+
+      configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+                                         depth_bits_array,
+                                         stencil_bits_array,
+                                         depth_buffer_factor,
+                                         back_buffer_modes,
+                                         back_buffer_factor,
+                                         msaa_samples_array, 1);
+      configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV,
+                                         depth_bits_array,
+                                         stencil_bits_array,
+                                         depth_buffer_factor,
+                                         back_buffer_modes,
+                                         back_buffer_factor,
+                                         msaa_samples_array, 1);
+      configs = driConcatConfigs(configs_a8r8g8b8, configs_x8r8g8b8);
    }
 
-   configs = driCreateConfigs(fb_format, fb_type,
-                             depth_bits_array, stencil_bits_array,
-                             depth_buffer_factor, back_buffer_modes,
-                             back_buffer_factor);
    if (configs == NULL) {
     fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
               __LINE__);
@@ -551,6 +552,69 @@ intelFillInModes(__DRIscreenPrivate *psp,
    return configs;
 }
 
+static GLboolean
+intel_init_bufmgr(intelScreenPrivate *intelScreen)
+{
+   GLboolean gem_disable = getenv("INTEL_NO_GEM") != NULL;
+   int gem_kernel = 0;
+   GLboolean gem_supported;
+   struct drm_i915_getparam gp;
+   __DRIscreenPrivate *spriv = intelScreen->driScrnPriv;
+
+   intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL;
+
+   gp.param = I915_PARAM_HAS_GEM;
+   gp.value = &gem_kernel;
+
+   (void) drmCommandWriteRead(spriv->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
+
+   /* If we've got a new enough DDX that's initializing GEM and giving us
+    * object handles for the shared buffers, use that.
+    */
+   intelScreen->ttm = GL_FALSE;
+   if (intelScreen->driScrnPriv->dri2.enabled)
+       gem_supported = GL_TRUE;
+   else if (intelScreen->driScrnPriv->ddx_version.minor >= 9 &&
+           gem_kernel &&
+           intelScreen->front.bo_handle != -1)
+       gem_supported = GL_TRUE;
+   else
+       gem_supported = GL_FALSE;
+
+   if (!gem_disable && gem_supported) {
+      intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ);
+      if (intelScreen->bufmgr != NULL)
+        intelScreen->ttm = GL_TRUE;
+   }
+   /* Otherwise, use the classic buffer manager. */
+   if (intelScreen->bufmgr == NULL) {
+      if (gem_disable) {
+        fprintf(stderr, "GEM disabled.  Using classic.\n");
+      } else {
+        fprintf(stderr, "Failed to initialize GEM.  "
+                "Falling back to classic.\n");
+      }
+
+      if (intelScreen->tex.size == 0) {
+        fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
+                __func__, __LINE__);
+        return GL_FALSE;
+      }
+
+      intelScreen->bufmgr =
+        intel_bufmgr_fake_init(spriv->fd,
+                               intelScreen->tex.offset,
+                               intelScreen->tex.map,
+                               intelScreen->tex.size,
+                               (unsigned int * volatile)
+                               &intelScreen->sarea->last_dispatch);
+   }
+
+   /* XXX bufmgr should be per-screen, not per-context */
+   intelScreen->ttm = intelScreen->ttm;
+
+   return GL_TRUE;
+}
 
 /**
  * This is the driver specific part of the createNewScreen entry point.
@@ -562,6 +626,7 @@ intelFillInModes(__DRIscreenPrivate *psp,
  */
 static const __DRIconfig **intelInitScreen(__DRIscreenPrivate *psp)
 {
+   intelScreenPrivate *intelScreen;
 #ifdef I915
    static const __DRIversion ddx_expected = { 1, 5, 0 };
 #else
@@ -595,6 +660,10 @@ static const __DRIconfig **intelInitScreen(__DRIscreenPrivate *psp)
 
    psp->extensions = intelScreenExtensions;
 
+   intelScreen = psp->private;
+   if (!intel_init_bufmgr(intelScreen))
+       return GL_FALSE;
+
    return (const __DRIconfig **)
        intelFillInModes(psp, dri_priv->cpp * 8,
                        (dri_priv->cpp == 2) ? 16 : 24,
@@ -626,6 +695,17 @@ static const
 __DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp)
 {
    intelScreenPrivate *intelScreen;
+   GLenum fb_format[3];
+   GLenum fb_type[3];
+   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+    * support pageflipping at all.
+    */
+   static const GLenum back_buffer_modes[] = {
+      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+   };
+   uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1];
+   int color;
+   __DRIconfig **configs = NULL;
 
    /* Calling driInitExtensions here, with a NULL context pointer,
     * does not actually enable the extensions.  It just makes sure
@@ -659,11 +739,77 @@ __DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp)
                        &intelScreen->deviceID))
       return GL_FALSE;
 
+   if (!intel_init_bufmgr(intelScreen))
+       return GL_FALSE;
+
    intelScreen->irq_active = 1;
    psp->extensions = intelScreenExtensions;
 
-   return driConcatConfigs(intelFillInModes(psp, 16, 16, 0, 1),
-                          intelFillInModes(psp, 32, 24, 8, 1));
+   depth_bits[0] = 0;
+   stencil_bits[0] = 0;
+   depth_bits[1] = 16;
+   stencil_bits[1] = 0;
+   depth_bits[2] = 24;
+   stencil_bits[2] = 0;
+   depth_bits[3] = 24;
+   stencil_bits[3] = 8;
+
+   msaa_samples_array[0] = 0;
+
+   fb_format[0] = GL_RGB;
+   fb_type[0] = GL_UNSIGNED_SHORT_5_6_5;
+
+   fb_format[1] = GL_BGR;
+   fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+   fb_format[2] = GL_BGRA;
+   fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+   depth_bits[0] = 0;
+   stencil_bits[0] = 0;
+
+   for (color = 0; color < ARRAY_SIZE(fb_format); color++) {
+      __DRIconfig **new_configs;
+      int depth_factor;
+
+      /* With DRI2 right now, GetBuffers always returns a depth/stencil buffer
+       * with the same cpp as the drawable.  So we can't support depth cpp !=
+       * color cpp currently.
+       */
+      if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) {
+        depth_bits[1] = 16;
+        stencil_bits[1] = 0;
+
+        depth_factor = 2;
+      } else {
+        depth_bits[1] = 24;
+        stencil_bits[1] = 0;
+        depth_bits[2] = 24;
+        stencil_bits[2] = 8;
+
+        depth_factor = 3;
+      }
+      new_configs = driCreateConfigs(fb_format[color], fb_type[color],
+                                    depth_bits,
+                                    stencil_bits,
+                                    depth_factor,
+                                    back_buffer_modes,
+                                    ARRAY_SIZE(back_buffer_modes),
+                                    msaa_samples_array,
+                                    ARRAY_SIZE(msaa_samples_array));
+      if (configs == NULL)
+        configs = new_configs;
+      else
+        configs = driConcatConfigs(configs, new_configs);
+   }
+
+   if (configs == NULL) {
+      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+              __LINE__);
+      return NULL;
+   }
+
+   return (const __DRIconfig **)configs;
 }
 
 const struct __DriverAPIRec driDriverAPI = {