mesa: add/update comments in _mesa_copy_buffer_subdata()
[mesa.git] / src / mesa / drivers / dri / i965 / brw_context.c
index 360fc12621adfef2d94148bb22322f76c6c28742..48c141c9c2e7a3d681b087aa5e3aeeb344148eab 100644 (file)
 
 
 #include "main/imports.h"
-#include "main/api_noop.h"
 #include "main/macros.h"
 #include "main/simple_list.h"
-#include "shader/shader_api.h"
+
+#include "vbo/vbo_context.h"
 
 #include "brw_context.h"
 #include "brw_defines.h"
 #include "brw_draw.h"
 #include "brw_state.h"
+
+#include "gen6_hiz.h"
+
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
 #include "intel_span.h"
-#include "tnl/t_pipeline.h"
+#include "intel_tex.h"
+#include "intel_tex_obj.h"
 
+#include "tnl/t_pipeline.h"
+#include "glsl/ralloc.h"
 
 /***************************************
  * Mesa's Driver Functions
  ***************************************/
 
-static void brwUseProgram(GLcontext *ctx, GLuint program)
+/**
+ * \brief Prepare for entry into glBegin/glEnd block.
+ *
+ * Resolve buffers before entering a glBegin/glEnd block. This is
+ * necessary to prevent recursive calls to FLUSH_VERTICES.
+ *
+ * This resolves the depth buffer of each enabled depth texture and the HiZ
+ * buffer of the attached depth renderbuffer.
+ *
+ * Details
+ * -------
+ * When vertices are queued during a glBegin/glEnd block, those vertices must
+ * be drawn before any rendering state changes. To ensure this, Mesa calls
+ * FLUSH_VERTICES as a prehook to such state changes. Therefore,
+ * FLUSH_VERTICES itself cannot change rendering state without falling into a
+ * recursive trap.
+ *
+ * This precludes meta-ops, namely buffer resolves, from occurring while any
+ * vertices are queued. To prevent that situation, we resolve some buffers on
+ * entering a glBegin/glEnd
+ *
+ * \see brwCleanupExecEnd()
+ */
+static void brwPrepareExecBegin(struct gl_context *ctx)
 {
-   _mesa_use_program(ctx, program);
-}
+   struct brw_context *brw = brw_context(ctx);
+   struct intel_context *intel = &brw->intel;
+   struct intel_renderbuffer *draw_irb;
+   struct intel_texture_object *tex_obj;
 
-static void brwInitProgFuncs( struct dd_function_table *functions )
-{
-   functions->UseProgram = brwUseProgram;
+   if (!intel->has_hiz) {
+      /* The context uses no feature that requires buffer resolves. */
+      return;
+   }
+
+   /* Resolve each enabled texture. */
+   for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+      if (!ctx->Texture.Unit[i]._ReallyEnabled)
+        continue;
+      tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
+      if (!tex_obj || !tex_obj->mt)
+        continue;
+      intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt);
+   }
+
+   /* Resolve the attached depth buffer. */
+   draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
+   if (draw_irb) {
+      intel_renderbuffer_resolve_hiz(intel, draw_irb);
+   }
 }
-static void brwInitDriverFunctions( struct dd_function_table *functions )
+
+static void brwInitDriverFunctions(struct intel_screen *screen,
+                                  struct dd_function_table *functions)
 {
    intelInitDriverFunctions( functions );
 
    brwInitFragProgFuncs( functions );
-   brwInitProgFuncs( functions );
    brw_init_queryobj_functions(functions);
 
-   functions->Viewport = intel_viewport;
+   functions->PrepareExecBegin = brwPrepareExecBegin;
+   functions->BeginTransformFeedback = brw_begin_transform_feedback;
+
+   if (screen->gen >= 7)
+      functions->EndTransformFeedback = gen7_end_transform_feedback;
+   else
+      functions->EndTransformFeedback = brw_end_transform_feedback;
 }
 
-GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
-                           __DRIcontext *driContextPriv,
-                           void *sharedContextPrivate)
+bool
+brwCreateContext(int api,
+                const struct gl_config *mesaVis,
+                __DRIcontext *driContextPriv,
+                void *sharedContextPrivate)
 {
+   __DRIscreen *sPriv = driContextPriv->driScreenPriv;
+   struct intel_screen *screen = sPriv->driverPrivate;
    struct dd_function_table functions;
-   struct brw_context *brw = (struct brw_context *) CALLOC_STRUCT(brw_context);
+   struct brw_context *brw = rzalloc(NULL, struct brw_context);
    struct intel_context *intel = &brw->intel;
-   GLcontext *ctx = &intel->ctx;
+   struct gl_context *ctx = &intel->ctx;
+   unsigned i;
 
    if (!brw) {
       printf("%s: failed to alloc context\n", __FUNCTION__);
-      return GL_FALSE;
+      return false;
    }
 
-   brwInitVtbl( brw );
-   brwInitDriverFunctions( &functions );
+   brwInitDriverFunctions(screen, &functions);
 
-   if (!intelInitContext( intel, mesaVis, driContextPriv,
+   if (!intelInitContext( intel, api, mesaVis, driContextPriv,
                          sharedContextPrivate, &functions )) {
       printf("%s: failed to init intel context\n", __FUNCTION__);
       FREE(brw);
-      return GL_FALSE;
+      return false;
    }
 
+   brwInitVtbl( brw );
+
+   brw_init_surface_formats(brw);
+
    /* Initialize swrast, tnl driver tables: */
    intelInitSpanFuncs(ctx);
 
@@ -102,26 +168,64 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
    ctx->Const.MaxTextureCoordUnits = 8; /* Mesa limit */
    ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
                                      ctx->Const.MaxTextureImageUnits);
-   ctx->Const.MaxVertexTextureImageUnits = 0; /* no vertex shader textures */
+   ctx->Const.MaxVertexTextureImageUnits = BRW_MAX_TEX_UNIT;
    ctx->Const.MaxCombinedTextureImageUnits =
       ctx->Const.MaxVertexTextureImageUnits +
       ctx->Const.MaxTextureImageUnits;
 
-   /* Mesa limits textures to 4kx4k; it would be nice to fix that someday
-    */
-   ctx->Const.MaxTextureLevels = 13;
+   ctx->Const.MaxTextureLevels = 14; /* 8192 */
+   if (ctx->Const.MaxTextureLevels > MAX_TEXTURE_LEVELS)
+          ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
    ctx->Const.Max3DTextureLevels = 9;
    ctx->Const.MaxCubeTextureLevels = 12;
+   /* minimum maximum.  Users are likely to run into memory problems
+    * even at this size, since 64 * 2048 * 2048 * 4 = 1GB and we can't
+    * address that much.
+    */
+   ctx->Const.MaxArrayTextureLayers = 64;
    ctx->Const.MaxTextureRectSize = (1<<12);
    
    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
 
+   /* Hardware only supports a limited number of transform feedback buffers.
+    * So we need to override the Mesa default (which is based only on software
+    * limits).
+    */
+   ctx->Const.MaxTransformFeedbackSeparateAttribs = BRW_MAX_SOL_BUFFERS;
+
+   /* On Gen6, in the worst case, we use up one binding table entry per
+    * transform feedback component (see comments above the definition of
+    * BRW_MAX_SOL_BINDINGS, in brw_context.h), so we need to advertise a value
+    * for MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS equal to
+    * BRW_MAX_SOL_BINDINGS.
+    *
+    * In "separate components" mode, we need to divide this value by
+    * BRW_MAX_SOL_BUFFERS, so that the total number of binding table entries
+    * used up by all buffers will not exceed BRW_MAX_SOL_BINDINGS.
+    */
+   ctx->Const.MaxTransformFeedbackInterleavedComponents = BRW_MAX_SOL_BINDINGS;
+   ctx->Const.MaxTransformFeedbackSeparateComponents =
+      BRW_MAX_SOL_BINDINGS / BRW_MAX_SOL_BUFFERS;
+
    /* if conformance mode is set, swrast can handle any size AA point */
    ctx->Const.MaxPointSizeAA = 255.0;
 
    /* We want the GLSL compiler to emit code that uses condition codes */
-   ctx->Shader.EmitCondCodes = GL_TRUE;
-   ctx->Shader.EmitNVTempInitialization = GL_TRUE;
+   for (i = 0; i <= MESA_SHADER_FRAGMENT; i++) {
+      ctx->ShaderCompilerOptions[i].MaxIfDepth = intel->gen < 6 ? 16 : UINT_MAX;
+      ctx->ShaderCompilerOptions[i].EmitCondCodes = true;
+      ctx->ShaderCompilerOptions[i].EmitNVTempInitialization = true;
+      ctx->ShaderCompilerOptions[i].EmitNoNoise = true;
+      ctx->ShaderCompilerOptions[i].EmitNoMainReturn = true;
+      ctx->ShaderCompilerOptions[i].EmitNoIndirectInput = true;
+      ctx->ShaderCompilerOptions[i].EmitNoIndirectOutput = true;
+
+      ctx->ShaderCompilerOptions[i].EmitNoIndirectUniform =
+        (i == MESA_SHADER_FRAGMENT);
+      ctx->ShaderCompilerOptions[i].EmitNoIndirectTemp =
+        (i == MESA_SHADER_FRAGMENT);
+      ctx->ShaderCompilerOptions[i].LowerClipDistance = true;
+   }
 
    ctx->Const.VertexProgram.MaxNativeInstructions = (16 * 1024);
    ctx->Const.VertexProgram.MaxAluInstructions = 0;
@@ -150,53 +254,121 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
       MIN2(ctx->Const.FragmentProgram.MaxNativeParameters,
           ctx->Const.FragmentProgram.MaxEnvParams);
 
+   /* Fragment shaders use real, 32-bit twos-complement integers for all
+    * integer types.
+    */
+   ctx->Const.FragmentProgram.LowInt.RangeMin = 31;
+   ctx->Const.FragmentProgram.LowInt.RangeMax = 30;
+   ctx->Const.FragmentProgram.LowInt.Precision = 0;
+   ctx->Const.FragmentProgram.HighInt = ctx->Const.FragmentProgram.MediumInt
+      = ctx->Const.FragmentProgram.LowInt;
+
+   /* Gen6 converts quads to polygon in beginning of 3D pipeline,
+      but we're not sure how it's actually done for vertex order,
+      that affect provoking vertex decision. Always use last vertex
+      convention for quad primitive which works as expected for now. */
+   if (intel->gen >= 6)
+       ctx->Const.QuadsFollowProvokingVertexConvention = false;
+
    if (intel->is_g4x || intel->gen >= 5) {
-      brw->CMD_VF_STATISTICS = CMD_VF_STATISTICS_GM45;
+      brw->CMD_VF_STATISTICS = GM45_3DSTATE_VF_STATISTICS;
       brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_GM45;
-      brw->has_surface_tile_offset = GL_TRUE;
-      brw->has_compr4 = GL_TRUE;
-      brw->has_aa_line_parameters = GL_TRUE;
-      brw->has_pln = GL_TRUE;
+      brw->has_surface_tile_offset = true;
+      if (intel->gen < 6)
+         brw->has_compr4 = true;
+      brw->has_aa_line_parameters = true;
+      brw->has_pln = true;
   } else {
-      brw->CMD_VF_STATISTICS = CMD_VF_STATISTICS_965;
+      brw->CMD_VF_STATISTICS = GEN4_3DSTATE_VF_STATISTICS;
       brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_965;
    }
 
    /* WM maximum threads is number of EUs times number of threads per EU. */
-   if (intel->gen == 5) {
+   if (intel->gen >= 7) {
+      if (intel->gt == 1) {
+        brw->max_wm_threads = 86;
+        brw->max_vs_threads = 36;
+        brw->max_gs_threads = 36;
+        brw->urb.size = 128;
+        brw->urb.max_vs_entries = 512;
+        brw->urb.max_gs_entries = 192;
+      } else if (intel->gt == 2) {
+        brw->max_wm_threads = 86;
+        brw->max_vs_threads = 128;
+        brw->max_gs_threads = 128;
+        brw->urb.size = 256;
+        brw->urb.max_vs_entries = 704;
+        brw->urb.max_gs_entries = 320;
+      } else {
+        assert(!"Unknown gen7 device.");
+      }
+   } else if (intel->gen == 6) {
+      if (intel->gt == 2) {
+        /* This could possibly be 80, but is supposed to require
+         * disabling of WIZ hashing (bit 6 of GT_MODE, 0x20d0) and a
+         * GPU reset to change.
+         */
+        brw->max_wm_threads = 40;
+        brw->max_vs_threads = 60;
+        brw->max_gs_threads = 60;
+        brw->urb.size = 64;            /* volume 5c.5 section 5.1 */
+        brw->urb.max_vs_entries = 256; /* volume 2a (see 3DSTATE_URB) */
+        brw->urb.max_gs_entries = 256;
+      } else {
+        brw->max_wm_threads = 40;
+        brw->max_vs_threads = 24;
+        brw->max_gs_threads = 21; /* conservative; 24 if rendering disabled */
+        brw->urb.size = 32;            /* volume 5c.5 section 5.1 */
+        brw->urb.max_vs_entries = 128; /* volume 2a (see 3DSTATE_URB) */
+        brw->urb.max_gs_entries = 256;
+      }
+      brw->urb.gen6_gs_previously_active = false;
+   } else if (intel->gen == 5) {
       brw->urb.size = 1024;
-      brw->vs_max_threads = 72;
-      brw->wm_max_threads = 12 * 6;
+      brw->max_vs_threads = 72;
+      brw->max_gs_threads = 32;
+      brw->max_wm_threads = 12 * 6;
    } else if (intel->is_g4x) {
       brw->urb.size = 384;
-      brw->vs_max_threads = 32;
-      brw->wm_max_threads = 10 * 5;
+      brw->max_vs_threads = 32;
+      brw->max_gs_threads = 2;
+      brw->max_wm_threads = 10 * 5;
    } else if (intel->gen < 6) {
       brw->urb.size = 256;
-      brw->vs_max_threads = 16;
-      brw->wm_max_threads = 8 * 4;
-      brw->has_negative_rhw_bug = GL_TRUE;
-   }
-
-   if (INTEL_DEBUG & DEBUG_SINGLE_THREAD) {
-      brw->vs_max_threads = 1;
-      brw->wm_max_threads = 1;
+      brw->max_vs_threads = 16;
+      brw->max_gs_threads = 2;
+      brw->max_wm_threads = 8 * 4;
+      brw->has_negative_rhw_bug = true;
    }
 
    brw_init_state( brw );
 
+   brw->curbe.last_buf = calloc(1, 4096);
+   brw->curbe.next_buf = calloc(1, 4096);
+
    brw->state.dirty.mesa = ~0;
    brw->state.dirty.brw = ~0;
 
    brw->emit_state_always = 0;
 
-   ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
-   ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+   intel->batch.need_workaround_flush = true;
 
-   make_empty_list(&brw->query.active_head);
+   ctx->VertexProgram._MaintainTnlProgram = true;
+   ctx->FragmentProgram._MaintainTexEnvProgram = true;
 
    brw_draw_init( brw );
 
-   return GL_TRUE;
+   brw->new_vs_backend = (getenv("INTEL_OLD_VS") == NULL);
+   brw->precompile = driQueryOptionb(&intel->optionCache, "shader_precompile");
+
+   /* If we're using the new shader backend, we require integer uniforms
+    * stored as actual integers.
+    */
+   if (brw->new_vs_backend) {
+      ctx->Const.NativeIntegers = true;
+      ctx->Const.UniformBooleanTrue = 1;
+   }
+
+   return true;
 }