st/dri: Add option to control exposure of 10 bpc color configs.
[mesa.git] / src / gallium / state_trackers / dri / dri_screen.c
index 17b9f1c5faf610d22c4fd04b577c056eea92787f..adce2ff36dbb1a8b7cfef7991dbd9ff9ce4bf440 100644 (file)
  */
 
 #include "utils.h"
-#include "vblank.h"
-#include "xmlpool.h"
 
 #include "dri_screen.h"
 #include "dri_context.h"
-#include "dri_drawable.h"
-#include "dri_st_api.h"
-#include "dri1.h"
 
 #include "util/u_inlines.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_format.h"
-#include "state_tracker/drm_api.h"
+#include "pipe-loader/pipe_loader.h"
+#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
+#include "state_tracker/drm_driver.h"
 
 #include "util/u_debug.h"
+#include "util/u_format_s3tc.h"
 
-PUBLIC const char __driConfigOptions[] =
-   DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
-   DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
-   DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
-   DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
-    /*DRI_CONF_FORCE_S3TC_ENABLE(false) */
-   DRI_CONF_ALLOW_LARGE_TEXTURES(1)
-   DRI_CONF_SECTION_END DRI_CONF_END;
-
-const uint __driNConfigOptions = 3;
-
-static const __DRItexBufferExtension dri2TexBufferExtension = {
-    { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
-   dri2_set_tex_buffer,
-   dri2_set_tex_buffer2,
+#define MSAA_VISUAL_MAX_SAMPLES 32
+
+#undef false
+
+const __DRIconfigOptionsExtension gallium_config_options = {
+   .base = { __DRI_CONFIG_OPTIONS, 2 },
+   .xml = gallium_driinfo_xml,
+   .getXml = pipe_loader_get_driinfo_xml
 };
 
+#define false 0
+
 static void
-dri2_flush_drawable(__DRIdrawable *draw)
+dri_fill_st_options(struct dri_screen *screen)
 {
+   struct st_config_options *options = &screen->options;
+   const struct driOptionCache *optionCache = &screen->dev->option_cache;
+
+   options->disable_blend_func_extended =
+      driQueryOptionb(optionCache, "disable_blend_func_extended");
+   options->disable_glsl_line_continuations =
+      driQueryOptionb(optionCache, "disable_glsl_line_continuations");
+   options->disable_shader_bit_encoding =
+      driQueryOptionb(optionCache, "disable_shader_bit_encoding");
+   options->force_glsl_extensions_warn =
+      driQueryOptionb(optionCache, "force_glsl_extensions_warn");
+   options->force_glsl_version =
+      driQueryOptioni(optionCache, "force_glsl_version");
+   options->allow_glsl_extension_directive_midshader =
+      driQueryOptionb(optionCache, "allow_glsl_extension_directive_midshader");
+   options->allow_glsl_builtin_variable_redeclaration =
+      driQueryOptionb(optionCache, "allow_glsl_builtin_variable_redeclaration");
+   options->allow_higher_compat_version =
+      driQueryOptionb(optionCache, "allow_higher_compat_version");
+   options->glsl_zero_init = driQueryOptionb(optionCache, "glsl_zero_init");
+   options->force_glsl_abs_sqrt =
+      driQueryOptionb(optionCache, "force_glsl_abs_sqrt");
+   options->allow_glsl_cross_stage_interpolation_mismatch =
+      driQueryOptionb(optionCache, "allow_glsl_cross_stage_interpolation_mismatch");
+
+   driComputeOptionsSha1(optionCache, options->config_options_sha1);
 }
 
-static void
-dri2_invalidate_drawable(__DRIdrawable *dPriv)
+static unsigned
+dri_loader_get_cap(struct dri_screen *screen, enum dri_loader_cap cap)
 {
-   struct dri_drawable *drawable = dri_drawable(dPriv);
-   struct dri_context *ctx = dri_context(dPriv->driContextPriv);
-
-   dri2InvalidateDrawable(dPriv);
-   drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
+   const __DRIdri2LoaderExtension *dri2_loader = screen->sPriv->dri2.loader;
+   const __DRIimageLoaderExtension *image_loader = screen->sPriv->image.loader;
 
-   if (ctx)
-      ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb);
-}
+   if (dri2_loader && dri2_loader->base.version >= 4 &&
+       dri2_loader->getCapability)
+      return dri2_loader->getCapability(screen->sPriv->loaderPrivate, cap);
 
-static const __DRI2flushExtension dri2FlushExtension = {
-    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
-    dri2_flush_drawable,
-    dri2_invalidate_drawable,
-};
+   if (image_loader && image_loader->base.version >= 2 &&
+       image_loader->getCapability)
+      return image_loader->getCapability(screen->sPriv->loaderPrivate, cap);
 
-   static const __DRIextension *dri_screen_extensions[] = {
-      &driReadDrawableExtension,
-      &driCopySubBufferExtension.base,
-      &driSwapControlExtension.base,
-      &driFrameTrackingExtension.base,
-      &driMediaStreamCounterExtension.base,
-      &dri2TexBufferExtension.base,
-      &dri2FlushExtension.base,
-      NULL
-   };
+   return 0;
+}
 
-const __DRIconfig **
-dri_fill_in_modes(struct dri_screen *screen,
-                 unsigned pixel_bits)
+static const __DRIconfig **
+dri_fill_in_modes(struct dri_screen *screen)
 {
+   static const mesa_format mesa_formats[] = {
+      MESA_FORMAT_B10G10R10A2_UNORM,
+      MESA_FORMAT_B10G10R10X2_UNORM,
+      MESA_FORMAT_B8G8R8A8_UNORM,
+      MESA_FORMAT_B8G8R8X8_UNORM,
+      MESA_FORMAT_B8G8R8A8_SRGB,
+      MESA_FORMAT_B8G8R8X8_SRGB,
+      MESA_FORMAT_B5G6R5_UNORM,
+
+      /* The 32-bit RGBA format must not precede the 32-bit BGRA format.
+       * Likewise for RGBX and BGRX.  Otherwise, the GLX client and the GLX
+       * server may disagree on which format the GLXFBConfig represents,
+       * resulting in swapped color channels.
+       *
+       * The problem, as of 2017-05-30:
+       * When matching a GLXFBConfig to a __DRIconfig, GLX ignores the channel
+       * order and chooses the first __DRIconfig with the expected channel
+       * sizes. Specifically, GLX compares the GLXFBConfig's and __DRIconfig's
+       * __DRI_ATTRIB_{CHANNEL}_SIZE but ignores __DRI_ATTRIB_{CHANNEL}_MASK.
+       *
+       * EGL does not suffer from this problem. It correctly compares the
+       * channel masks when matching EGLConfig to __DRIconfig.
+       */
+
+      /* Required by Android, for HAL_PIXEL_FORMAT_RGBA_8888. */
+      MESA_FORMAT_R8G8B8A8_UNORM,
+
+      /* Required by Android, for HAL_PIXEL_FORMAT_RGBX_8888. */
+      MESA_FORMAT_R8G8B8X8_UNORM,
+   };
+   static const enum pipe_format pipe_formats[] = {
+      PIPE_FORMAT_B10G10R10A2_UNORM,
+      PIPE_FORMAT_B10G10R10X2_UNORM,
+      PIPE_FORMAT_BGRA8888_UNORM,
+      PIPE_FORMAT_BGRX8888_UNORM,
+      PIPE_FORMAT_BGRA8888_SRGB,
+      PIPE_FORMAT_BGRX8888_SRGB,
+      PIPE_FORMAT_B5G6R5_UNORM,
+      PIPE_FORMAT_RGBA8888_UNORM,
+      PIPE_FORMAT_RGBX8888_UNORM,
+   };
+   mesa_format format;
    __DRIconfig **configs = NULL;
-   __DRIconfig **configs_r5g6b5 = NULL;
-   __DRIconfig **configs_a8r8g8b8 = NULL;
-   __DRIconfig **configs_x8r8g8b8 = NULL;
-   unsigned num_modes;
    uint8_t depth_bits_array[5];
    uint8_t stencil_bits_array[5];
-   uint8_t msaa_samples_array[2];
    unsigned depth_buffer_factor;
-   unsigned back_buffer_factor;
-   unsigned msaa_samples_factor;
-   struct pipe_screen *p_screen = screen->pipe_screen;
-   boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8;
+   unsigned msaa_samples_max;
+   unsigned i;
+   struct pipe_screen *p_screen = screen->base.screen;
    boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32;
+   boolean mixed_color_depth;
+   boolean allow_rgb10;
 
    static const GLenum back_buffer_modes[] = {
-      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+      __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED,
+      __DRI_ATTRIB_SWAP_COPY
    };
 
-   depth_bits_array[0] = 0;
-   stencil_bits_array[0] = 0;
-   depth_buffer_factor = 1;
+   if (driQueryOptionb(&screen->dev->option_cache, "always_have_depth_buffer")) {
+      /* all visuals will have a depth buffer */
+      depth_buffer_factor = 0;
+   }
+   else {
+      depth_bits_array[0] = 0;
+      stencil_bits_array[0] = 0;
+      depth_buffer_factor = 1;
+   }
+
+   allow_rgb10 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb10_configs");
+
+   msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK)
+      ? MSAA_VISUAL_MAX_SAMPLES : 1;
 
    pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
-                                           PIPE_TEXTURE_2D,
-                                           PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+                                           PIPE_TEXTURE_2D, 0,
+                                            PIPE_BIND_DEPTH_STENCIL);
    pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
-                                           PIPE_TEXTURE_2D,
-                                           PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-   pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM,
-                                           PIPE_TEXTURE_2D,
-                                           PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-   pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8Z24_UNORM,
-                                           PIPE_TEXTURE_2D,
-                                           PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-   pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
-                                              PIPE_TEXTURE_2D,
-                                              PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
-   pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
-                                              PIPE_TEXTURE_2D,
-                                              PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
-   pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
-                                            PIPE_TEXTURE_2D,
-                                            PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
-
-   /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */
-   if (screen->sPriv->dri2.loader &&
-       (screen->sPriv->dri2.loader->base.version > 2) &&
-       (screen->sPriv->dri2.loader->getBuffersWithFormat != NULL)) {
-      pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
-                                             PIPE_TEXTURE_2D,
-                                             PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-      pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
-                                             PIPE_TEXTURE_2D,
-                                             PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
-   } else {
-      pf_z16 = FALSE;
-      pf_z32 = FALSE;
-   }
+                                           PIPE_TEXTURE_2D, 0,
+                                            PIPE_BIND_DEPTH_STENCIL);
+   pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT,
+                                           PIPE_TEXTURE_2D, 0,
+                                            PIPE_BIND_DEPTH_STENCIL);
+   pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM,
+                                           PIPE_TEXTURE_2D, 0,
+                                            PIPE_BIND_DEPTH_STENCIL);
+   pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
+                                          PIPE_TEXTURE_2D, 0,
+                                          PIPE_BIND_DEPTH_STENCIL);
+   pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
+                                          PIPE_TEXTURE_2D, 0,
+                                          PIPE_BIND_DEPTH_STENCIL);
 
    if (pf_z16) {
       depth_bits_array[depth_buffer_factor] = 16;
@@ -181,56 +218,65 @@ dri_fill_in_modes(struct dri_screen *screen,
       stencil_bits_array[depth_buffer_factor++] = 0;
    }
 
-   msaa_samples_array[0] = 0;
-   msaa_samples_array[1] = 4;
-   back_buffer_factor = 3;
-   msaa_samples_factor = 2;
+   mixed_color_depth =
+      p_screen->get_param(p_screen, PIPE_CAP_MIXED_COLOR_DEPTH_BITS);
 
-   num_modes =
-      depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4;
+   assert(ARRAY_SIZE(mesa_formats) == ARRAY_SIZE(pipe_formats));
 
-   if (pf_r5g6b5)
-      configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+   /* Expose only BGRA ordering if the loader doesn't support RGBA ordering. */
+   unsigned num_formats;
+   if (dri_loader_get_cap(screen, DRI_LOADER_CAP_RGBA_ORDERING))
+      num_formats = ARRAY_SIZE(mesa_formats);
+   else
+      num_formats = ARRAY_SIZE(mesa_formats) - 2; /* all - RGBA_ORDERING formats */
+
+   /* Add configs. */
+   for (format = 0; format < num_formats; format++) {
+      __DRIconfig **new_configs = NULL;
+      unsigned num_msaa_modes = 0; /* includes a single-sample mode */
+      uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES];
+
+      if (!allow_rgb10 &&
+          (mesa_formats[format] == MESA_FORMAT_B10G10R10A2_UNORM ||
+           mesa_formats[format] == MESA_FORMAT_B10G10R10X2_UNORM))
+         continue;
+
+      if (!p_screen->is_format_supported(p_screen, pipe_formats[format],
+                                         PIPE_TEXTURE_2D, 0,
+                                         PIPE_BIND_RENDER_TARGET))
+         continue;
+
+      for (i = 1; i <= msaa_samples_max; i++) {
+         int samples = i > 1 ? i : 0;
+
+         if (p_screen->is_format_supported(p_screen, pipe_formats[format],
+                                           PIPE_TEXTURE_2D, samples,
+                                           PIPE_BIND_RENDER_TARGET)) {
+            msaa_modes[num_msaa_modes++] = samples;
+         }
+      }
+
+      if (num_msaa_modes) {
+         /* Single-sample configs with an accumulation buffer. */
+         new_configs = driCreateConfigs(mesa_formats[format],
                                         depth_bits_array, stencil_bits_array,
                                         depth_buffer_factor, back_buffer_modes,
-                                        back_buffer_factor,
-                                        msaa_samples_array, msaa_samples_factor,
-                                        GL_TRUE);
-
-   if (pf_a8r8g8b8)
-      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,
-                                          msaa_samples_factor,
-                                          GL_TRUE);
-
-   if (pf_x8r8g8b8)
-      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,
-                                          msaa_samples_factor,
-                                          GL_TRUE);
-
-   if (pixel_bits == 16) {
-      configs = configs_r5g6b5;
-      if (configs_a8r8g8b8)
-         configs = configs ? driConcatConfigs(configs, configs_a8r8g8b8) : configs_a8r8g8b8;
-      if (configs_x8r8g8b8)
-        configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8;
-   } else {
-      configs = configs_a8r8g8b8;
-      if (configs_x8r8g8b8)
-        configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8;
-      if (configs_r5g6b5)
-         configs = configs ? driConcatConfigs(configs, configs_r5g6b5) : configs_r5g6b5;
+                                        ARRAY_SIZE(back_buffer_modes),
+                                        msaa_modes, 1,
+                                        GL_TRUE, !mixed_color_depth);
+         configs = driConcatConfigs(configs, new_configs);
+
+         /* Multi-sample configs without an accumulation buffer. */
+         if (num_msaa_modes > 1) {
+            new_configs = driCreateConfigs(mesa_formats[format],
+                                           depth_bits_array, stencil_bits_array,
+                                           depth_buffer_factor, back_buffer_modes,
+                                           ARRAY_SIZE(back_buffer_modes),
+                                           msaa_modes+1, num_msaa_modes-1,
+                                           GL_FALSE, !mixed_color_depth);
+            configs = driConcatConfigs(configs, new_configs);
+         }
+      }
    }
 
    if (configs == NULL) {
@@ -246,20 +292,61 @@ dri_fill_in_modes(struct dri_screen *screen,
  */
 void
 dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
-                   const __GLcontextModes *mode)
+                   const struct gl_config *mode)
 {
    memset(stvis, 0, sizeof(*stvis));
 
-   stvis->samples = mode->samples;
-   stvis->render_buffer = ST_ATTACHMENT_INVALID;
+   if (!mode)
+      return;
 
-   if (mode->redBits == 8) {
-      if (mode->alphaBits == 8)
-         stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
-      else
-         stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
-   } else {
+   /* Deduce the color format. */
+   switch (mode->redMask) {
+   case 0x3FF00000:
+      if (mode->alphaMask) {
+         assert(mode->alphaMask == 0xC0000000);
+         stvis->color_format = PIPE_FORMAT_B10G10R10A2_UNORM;
+      } else {
+         stvis->color_format = PIPE_FORMAT_B10G10R10X2_UNORM;
+      }
+      break;
+
+   case 0x00FF0000:
+      if (mode->alphaMask) {
+         assert(mode->alphaMask == 0xFF000000);
+         stvis->color_format = mode->sRGBCapable ?
+                                  PIPE_FORMAT_BGRA8888_SRGB :
+                                  PIPE_FORMAT_BGRA8888_UNORM;
+      } else {
+         stvis->color_format = mode->sRGBCapable ?
+                                  PIPE_FORMAT_BGRX8888_SRGB :
+                                  PIPE_FORMAT_BGRX8888_UNORM;
+      }
+      break;
+
+   case 0x000000FF:
+      if (mode->alphaMask) {
+         assert(mode->alphaMask == 0xFF000000);
+         stvis->color_format = mode->sRGBCapable ?
+                                  PIPE_FORMAT_RGBA8888_SRGB :
+                                  PIPE_FORMAT_RGBA8888_UNORM;
+      } else {
+         stvis->color_format = mode->sRGBCapable ?
+                                  PIPE_FORMAT_RGBX8888_SRGB :
+                                  PIPE_FORMAT_RGBX8888_UNORM;
+      }
+      break;
+
+   case 0x0000F800:
       stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
+      break;
+
+   default:
+      assert(!"unsupported visual: invalid red mask");
+      return;
+   }
+
+   if (mode->sampleBuffers) {
+      stvis->samples = mode->samples;
    }
 
    switch (mode->depthBits) {
@@ -277,8 +364,8 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
                                           PIPE_FORMAT_X8Z24_UNORM;
       } else {
         stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
-                                          PIPE_FORMAT_Z24S8_UNORM:
-                                          PIPE_FORMAT_S8Z24_UNORM;
+                                          PIPE_FORMAT_Z24_UNORM_S8_UINT:
+                                          PIPE_FORMAT_S8_UINT_Z24_UNORM;
       }
       break;
    case 32:
@@ -290,8 +377,11 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
 
    stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
-   if (mode->doubleBufferMode)
+   stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
+   if (mode->doubleBufferMode) {
       stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
+      stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT;
+   }
    if (mode->stereoMode) {
       stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
       if (mode->doubleBufferMode)
@@ -303,115 +393,149 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
    /* let the state tracker allocate the accum buffer */
 }
 
-/**
- * Get information about previous buffer swaps.
- */
+static boolean
+dri_get_egl_image(struct st_manager *smapi,
+                  void *egl_image,
+                  struct st_egl_image *stimg)
+{
+   struct dri_screen *screen = (struct dri_screen *)smapi;
+   __DRIimage *img = NULL;
+
+   if (screen->lookup_egl_image) {
+      img = screen->lookup_egl_image(screen, egl_image);
+   }
+
+   if (!img)
+      return FALSE;
+
+   stimg->texture = NULL;
+   pipe_resource_reference(&stimg->texture, img->texture);
+   switch (img->dri_components) {
+   case __DRI_IMAGE_COMPONENTS_Y_U_V:
+      stimg->format = PIPE_FORMAT_IYUV;
+      break;
+   case __DRI_IMAGE_COMPONENTS_Y_UV:
+      stimg->format = PIPE_FORMAT_NV12;
+      break;
+   default:
+      stimg->format = img->texture->format;
+      break;
+   }
+   stimg->level = img->level;
+   stimg->layer = img->layer;
+
+   return TRUE;
+}
+
 static int
-dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo)
+dri_get_param(struct st_manager *smapi,
+              enum st_manager_param param)
 {
-   if (dPriv == NULL || dPriv->driverPrivate == NULL || sInfo == NULL)
-      return -1;
-   else
+   struct dri_screen *screen = (struct dri_screen *)smapi;
+
+   switch(param) {
+   case ST_MANAGER_BROKEN_INVALIDATE:
+      return screen->broken_invalidate;
+   default:
       return 0;
+   }
 }
 
-static void
+void
+dri_destroy_screen_helper(struct dri_screen * screen)
+{
+   if (screen->base.destroy)
+      screen->base.destroy(&screen->base);
+
+   if (screen->st_api && screen->st_api->destroy)
+      screen->st_api->destroy(screen->st_api);
+
+   if (screen->base.screen)
+      screen->base.screen->destroy(screen->base.screen);
+
+   mtx_destroy(&screen->opencl_func_mutex);
+}
+
+void
 dri_destroy_screen(__DRIscreen * sPriv)
 {
    struct dri_screen *screen = dri_screen(sPriv);
-   int i;
 
-   if (screen->dri1_pipe)
-      screen->dri1_pipe->destroy(screen->dri1_pipe);
+   dri_destroy_screen_helper(screen);
 
-   if (screen->smapi)
-      dri_destroy_st_manager(screen->smapi);
-   if (screen->pipe_screen)
-      screen->pipe_screen->destroy(screen->pipe_screen);
+   pipe_loader_release(&screen->dev, 1);
 
-   for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
-      FREE(screen->optionCache.info[i].name);
-      FREE(screen->optionCache.info[i].ranges);
-   }
+   free(screen);
+   sPriv->driverPrivate = NULL;
+   sPriv->extensions = NULL;
+}
 
-   FREE(screen->optionCache.info);
-   FREE(screen->optionCache.values);
+static void
+dri_postprocessing_init(struct dri_screen *screen)
+{
+   unsigned i;
 
-   FREE(screen);
-   sPriv->private = NULL;
-   sPriv->extensions = NULL;
+   for (i = 0; i < PP_FILTERS; i++) {
+      screen->pp_enabled[i] = driQueryOptioni(&screen->dev->option_cache,
+                                              pp_filters[i].name);
+   }
 }
 
-/**
- * This is the driver specific part of the createNewScreen entry point.
- *
- * Returns the __GLcontextModes supported by this driver.
- */
-static const __DRIconfig **
-dri_init_screen2(__DRIscreen * sPriv)
+static void
+dri_set_background_context(struct st_context_iface *st,
+                           struct util_queue_monitoring *queue_info)
 {
-   struct dri_screen *screen;
-   struct drm_create_screen_arg arg;
-   const __DRIdri2LoaderExtension *dri2_ext =
-     sPriv->dri2.loader;
+   struct dri_context *ctx = (struct dri_context *)st->st_manager_private;
+   const __DRIbackgroundCallableExtension *backgroundCallable =
+      ctx->sPriv->dri2.backgroundCallable;
+
+   /* Note: Mesa will only call this function if GL multithreading is enabled
+    * We only do that if the loader exposed the __DRI_BACKGROUND_CALLABLE
+    * extension. So we know that backgroundCallable is not NULL.
+    */
+   assert(backgroundCallable);
+   backgroundCallable->setBackgroundContext(ctx->cPriv->loaderPrivate);
+
+   if (ctx->hud)
+      hud_add_queue_for_monitoring(ctx->hud, queue_info);
+}
 
-   screen = CALLOC_STRUCT(dri_screen);
-   if (!screen)
-      return NULL;
+void
+dri_init_options(struct dri_screen *screen)
+{
+   pipe_loader_load_options(screen->dev);
 
-   screen->api = drm_api_create();
-   screen->sPriv = sPriv;
-   screen->fd = sPriv->fd;
-   sPriv->private = (void *)screen;
-   sPriv->extensions = dri_screen_extensions;
-   arg.mode = DRM_CREATE_NORMAL;
-
-   screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg);
-   if (!screen->pipe_screen) {
-      debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
-      goto fail;
-   }
+   dri_fill_st_options(screen);
+}
 
-   screen->smapi = dri_create_st_manager(screen);
-   if (!screen->smapi)
-      goto fail;
+const __DRIconfig **
+dri_init_screen_helper(struct dri_screen *screen,
+                       struct pipe_screen *pscreen)
+{
+   screen->base.screen = pscreen;
+   screen->base.get_egl_image = dri_get_egl_image;
+   screen->base.get_param = dri_get_param;
+   screen->base.set_background_context = dri_set_background_context;
 
-   driParseOptionInfo(&screen->optionCache,
-                     __driConfigOptions, __driNConfigOptions);
+   screen->st_api = st_gl_api_create();
+   if (!screen->st_api)
+      return NULL;
 
-   screen->auto_fake_front = dri2_ext->base.version >= 3 &&
-      dri2_ext->getBuffersWithFormat != NULL;
+   if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES))
+      screen->target = PIPE_TEXTURE_2D;
+   else
+      screen->target = PIPE_TEXTURE_RECT;
 
-   return dri_fill_in_modes(screen, 32);
-fail:
-   dri_destroy_screen(sPriv);
-   return NULL;
-}
+   dri_postprocessing_init(screen);
 
-const struct __DriverAPIRec driDriverAPI = {
-   .DestroyScreen = dri_destroy_screen,
-   .CreateContext = dri_create_context,
-   .DestroyContext = dri_destroy_context,
-   .CreateBuffer = dri_create_buffer,
-   .DestroyBuffer = dri_destroy_buffer,
-   .MakeCurrent = dri_make_current,
-   .UnbindContext = dri_unbind_context,
-   .GetSwapInfo = dri_get_swap_info,
-   .GetDrawableMSC = driDrawableGetMSC32,
-   .WaitForMSC = driWaitForMSC32,
-   .InitScreen2 = dri_init_screen2,
-
-   .InitScreen = dri1_init_screen,
-   .SwapBuffers = dri1_swap_buffers,
-   .CopySubBuffer = dri1_copy_sub_buffer,
-};
+   screen->st_api->query_versions(screen->st_api, &screen->base,
+                                  &screen->options,
+                                  &screen->sPriv->max_gl_core_version,
+                                  &screen->sPriv->max_gl_compat_version,
+                                  &screen->sPriv->max_gl_es1_version,
+                                  &screen->sPriv->max_gl_es2_version);
 
-/* This is the table of extensions that the loader will dlsym() for. */
-PUBLIC const __DRIextension *__driDriverExtensions[] = {
-    &driCoreExtension.base,
-    &driLegacyExtension.base,
-    &driDRI2Extension.base,
-    NULL
-};
+   return dri_fill_in_modes(screen);
+}
 
 /* vim: set sw=3 ts=8 sts=3 expandtab: */