i965/gen7: expose OpenGL 4.2 on Haswell when supported
[mesa.git] / src / mesa / drivers / dri / i965 / intel_screen.c
index d4e34ec4a2dec33c6dfdcd804da293bbcfadc07a..a8d401cdffa76081160cd59c9650577ec9146eac 100644 (file)
@@ -230,6 +230,9 @@ static struct intel_image_format intel_image_formats[] = {
    { __DRI_IMAGE_FOURCC_XBGR8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
      { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } },
 
+   { __DRI_IMAGE_FOURCC_ARGB1555, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } },
+
    { __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_COMPONENTS_RGB, 1,
      { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
 
@@ -916,6 +919,9 @@ brw_query_renderer_integer(__DRIscreen *dri_screen,
    case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
       value[0] = 1;
       return 0;
+   case __DRI2_RENDERER_HAS_TEXTURE_3D:
+      value[0] = 1;
+      return 0;
    default:
       return driQueryRendererIntegerCommon(dri_screen, param, value);
    }
@@ -1088,7 +1094,7 @@ intelCreateBuffer(__DRIscreen *dri_screen,
    if (mesaVis->depthBits == 24) {
       assert(mesaVis->stencilBits == 8);
 
-      if (screen->devinfo->has_hiz_and_separate_stencil) {
+      if (screen->devinfo.has_hiz_and_separate_stencil) {
          rb = intel_create_private_renderbuffer(MESA_FORMAT_Z24_UNORM_X8_UINT,
                                                 num_samples);
          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
@@ -1141,7 +1147,7 @@ intelDestroyBuffer(__DRIdrawable * driDrawPriv)
 static void
 intel_detect_sseu(struct intel_screen *screen)
 {
-   assert(screen->devinfo->gen >= 8);
+   assert(screen->devinfo.gen >= 8);
    int ret;
 
    screen->subslice_total = -1;
@@ -1265,6 +1271,96 @@ intel_detect_timestamp(struct intel_screen *screen)
    return 0;
 }
 
+ /**
+ * Test if we can use MI_LOAD_REGISTER_MEM from an untrusted batchbuffer.
+ *
+ * Some combinations of hardware and kernel versions allow this feature,
+ * while others don't.  Instead of trying to enumerate every case, just
+ * try and write a register and see if works.
+ */
+static bool
+intel_detect_pipelined_register(struct intel_screen *screen,
+                                int reg, uint32_t expected_value, bool reset)
+{
+   drm_intel_bo *results, *bo;
+   uint32_t *batch;
+   uint32_t offset = 0;
+   bool success = false;
+
+   /* Create a zero'ed temporary buffer for reading our results */
+   results = drm_intel_bo_alloc(screen->bufmgr, "registers", 4096, 0);
+   if (results == NULL)
+      goto err;
+
+   bo = drm_intel_bo_alloc(screen->bufmgr, "batchbuffer", 4096, 0);
+   if (bo == NULL)
+      goto err_results;
+
+   if (drm_intel_bo_map(bo, 1))
+      goto err_batch;
+
+   batch = bo->virtual;
+
+   /* Write the register. */
+   *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
+   *batch++ = reg;
+   *batch++ = expected_value;
+
+   /* Save the register's value back to the buffer. */
+   *batch++ = MI_STORE_REGISTER_MEM | (3 - 2);
+   *batch++ = reg;
+   drm_intel_bo_emit_reloc(bo, (char *)batch -(char *)bo->virtual,
+                           results, offset*sizeof(uint32_t),
+                           I915_GEM_DOMAIN_INSTRUCTION,
+                           I915_GEM_DOMAIN_INSTRUCTION);
+   *batch++ = results->offset + offset*sizeof(uint32_t);
+
+   /* And afterwards clear the register */
+   if (reset) {
+      *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
+      *batch++ = reg;
+      *batch++ = 0;
+   }
+
+   *batch++ = MI_BATCH_BUFFER_END;
+
+   drm_intel_bo_mrb_exec(bo, ALIGN((char *)batch - (char *)bo->virtual, 8),
+                         NULL, 0, 0,
+                         I915_EXEC_RENDER);
+
+   /* Check whether the value got written. */
+   if (drm_intel_bo_map(results, false) == 0) {
+      success = *((uint32_t *)results->virtual + offset) == expected_value;
+      drm_intel_bo_unmap(results);
+   }
+
+err_batch:
+   drm_intel_bo_unreference(bo);
+err_results:
+   drm_intel_bo_unreference(results);
+err:
+   return success;
+}
+
+static bool
+intel_detect_pipelined_so(struct intel_screen *screen)
+{
+   /* Supposedly, Broadwell just works. */
+   if (screen->devinfo.gen >= 8)
+      return true;
+
+   if (screen->devinfo.gen <= 6)
+      return false;
+
+   /* We use SO_WRITE_OFFSET0 since you're supposed to write it (unlike the
+    * statistics registers), and we already reset it to zero before using it.
+    */
+   return intel_detect_pipelined_register(screen,
+                                          GEN7_SO_WRITE_OFFSET(0),
+                                          0x1337d0d0,
+                                          false);
+}
+
 /**
  * Return array of MSAA modes supported by the hardware. The array is
  * zero-terminated and sorted in decreasing order.
@@ -1278,13 +1374,13 @@ intel_supported_msaa_modes(const struct intel_screen  *screen)
    static const int gen6_modes[] = {4, 0, -1};
    static const int gen4_modes[] = {0, -1};
 
-   if (screen->devinfo->gen >= 9) {
+   if (screen->devinfo.gen >= 9) {
       return gen9_modes;
-   } else if (screen->devinfo->gen >= 8) {
+   } else if (screen->devinfo.gen >= 8) {
       return gen8_modes;
-   } else if (screen->devinfo->gen >= 7) {
+   } else if (screen->devinfo.gen >= 7) {
       return gen7_modes;
-   } else if (screen->devinfo->gen == 6) {
+   } else if (screen->devinfo.gen == 6) {
       return gen6_modes;
    } else {
       return gen4_modes;
@@ -1309,7 +1405,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
    static const uint8_t multisample_samples[2]  = {4, 8};
 
    struct intel_screen *screen = dri_screen->driverPrivate;
-   const struct gen_device_info *devinfo = screen->devinfo;
+   const struct gen_device_info *devinfo = &screen->devinfo;
    uint8_t depth_bits[4], stencil_bits[4];
    __DRIconfig **configs = NULL;
 
@@ -1431,21 +1527,22 @@ static void
 set_max_gl_versions(struct intel_screen *screen)
 {
    __DRIscreen *dri_screen = screen->driScrnPriv;
-   const bool has_astc = screen->devinfo->gen >= 9;
+   const bool has_astc = screen->devinfo.gen >= 9;
 
-   switch (screen->devinfo->gen) {
+   switch (screen->devinfo.gen) {
    case 9:
    case 8:
-      dri_screen->max_gl_core_version = 44;
+      dri_screen->max_gl_core_version = 45;
       dri_screen->max_gl_compat_version = 30;
       dri_screen->max_gl_es1_version = 11;
       dri_screen->max_gl_es2_version = has_astc ? 32 : 31;
       break;
    case 7:
-      dri_screen->max_gl_core_version = 33;
+      dri_screen->max_gl_core_version = screen->devinfo.is_haswell &&
+         can_do_pipelined_register_writes(screen) ? 42 : 33;
       dri_screen->max_gl_compat_version = 30;
       dri_screen->max_gl_es1_version = 11;
-      dri_screen->max_gl_es2_version = screen->devinfo->is_haswell ? 31 : 30;
+      dri_screen->max_gl_es2_version = screen->devinfo.is_haswell ? 31 : 30;
       break;
    case 6:
       dri_screen->max_gl_core_version = 33;
@@ -1573,8 +1670,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
        return false;
 
    screen->deviceID = drm_intel_bufmgr_gem_get_devid(screen->bufmgr);
-   screen->devinfo = gen_get_device_info(screen->deviceID);
-   if (!screen->devinfo)
+   if (!gen_get_device_info(screen->deviceID, &screen->devinfo))
       return false;
 
    brw_process_intel_debug_variable();
@@ -1582,7 +1678,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
    if (INTEL_DEBUG & DEBUG_BUFMGR)
       dri_bufmgr_set_debug(screen->bufmgr, true);
 
-   if ((INTEL_DEBUG & DEBUG_SHADER_TIME) && screen->devinfo->gen < 7) {
+   if ((INTEL_DEBUG & DEBUG_SHADER_TIME) && screen->devinfo.gen < 7) {
       fprintf(stderr,
               "shader_time debugging requires gen7 (Ivybridge) or better.\n");
       INTEL_DEBUG &= ~DEBUG_SHADER_TIME;
@@ -1632,12 +1728,15 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
    screen->hw_has_timestamp = intel_detect_timestamp(screen);
 
    /* GENs prior to 8 do not support EU/Subslice info */
-   if (screen->devinfo->gen >= 8) {
+   if (screen->devinfo.gen >= 8) {
       intel_detect_sseu(screen);
-   } else if (screen->devinfo->gen == 7) {
-      screen->subslice_total = 1 << (screen->devinfo->gt - 1);
+   } else if (screen->devinfo.gen == 7) {
+      screen->subslice_total = 1 << (screen->devinfo.gt - 1);
    }
 
+   if (intel_detect_pipelined_so(screen))
+      screen->kernel_features |= KERNEL_ALLOWS_SOL_OFFSET_WRITES;
+
    const char *force_msaa = getenv("INTEL_FORCE_MSAA");
    if (force_msaa) {
       screen->winsys_msaa_samples_override =
@@ -1659,7 +1758,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
     *
     * Don't even try on pre-Gen6, since we don't attempt to use contexts there.
     */
-   if (screen->devinfo->gen >= 6) {
+   if (screen->devinfo.gen >= 6) {
       struct drm_i915_reset_stats stats;
       memset(&stats, 0, sizeof(stats));
 
@@ -1674,24 +1773,40 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
       screen->cmd_parser_version = 0;
    }
 
+   if (screen->devinfo.gen >= 8 || screen->cmd_parser_version >= 2)
+      screen->kernel_features |= KERNEL_ALLOWS_PREDICATE_WRITES;
+
+   /* Haswell requires command parser version 4 in order to have L3
+    * atomic scratch1 and chicken3 bits
+    */
+   if (screen->devinfo.is_haswell && screen->cmd_parser_version >= 4) {
+      screen->kernel_features |=
+         KERNEL_ALLOWS_HSW_SCRATCH1_AND_ROW_CHICKEN3;
+   }
+
    /* Haswell requires command parser version 6 in order to write to the
     * MI_MATH GPR registers, and version 7 in order to use
     * MI_LOAD_REGISTER_REG (which all users of MI_MATH use).
     */
-   screen->has_mi_math_and_lrr = screen->devinfo->gen >= 8 ||
-                                      (screen->devinfo->is_haswell &&
-                                       screen->cmd_parser_version >= 7);
+   if (screen->devinfo.gen >= 8 ||
+       (screen->devinfo.is_haswell && screen->cmd_parser_version >= 7)) {
+      screen->kernel_features |= KERNEL_ALLOWS_MI_MATH_AND_LRR;
+   }
+
+   /* Gen7 needs at least command parser version 5 to support compute */
+   if (screen->devinfo.gen >= 8 || screen->cmd_parser_version >= 5)
+      screen->kernel_features |= KERNEL_ALLOWS_COMPUTE_DISPATCH;
 
    dri_screen->extensions = !screen->has_context_reset_notification
       ? screenExtensions : intelRobustScreenExtensions;
 
    screen->compiler = brw_compiler_create(screen,
-                                               screen->devinfo);
+                                          &screen->devinfo);
    screen->compiler->shader_debug_log = shader_debug_log_mesa;
    screen->compiler->shader_perf_log = shader_perf_log_mesa;
    screen->program_id = 1;
 
-   if (screen->devinfo->has_resource_streamer) {
+   if (screen->devinfo.has_resource_streamer) {
       screen->has_resource_streamer =
         intel_get_boolean(screen, I915_PARAM_HAS_RESOURCE_STREAMER);
    }