i965: Implement ARB_fragment_layer_viewport.
[mesa.git] / src / mesa / drivers / dri / i915 / intel_batchbuffer.c
index 39e46ca3530be8c9f662074060e405170e8af148..e0f14a43063db015e00f175553e564248b52769b 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2006 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 static void
 intel_batchbuffer_reset(struct intel_context *intel);
 
-struct cached_batch_item {
-   struct cached_batch_item *next;
-   uint16_t header;
-   uint16_t size;
-};
-
-static void clear_cache( struct intel_context *intel )
-{
-   struct cached_batch_item *item = intel->batch.cached_items;
-
-   while (item) {
-      struct cached_batch_item *next = item->next;
-      free(item);
-      item = next;
-   }
-
-   intel->batch.cached_items = NULL;
-}
-
 void
 intel_batchbuffer_init(struct intel_context *intel)
 {
    intel_batchbuffer_reset(intel);
 
-   if (!intel->has_llc) {
-      intel->batch.cpu_map = malloc(intel->maxBatchSize);
-      intel->batch.map = intel->batch.cpu_map;
-   }
+   intel->batch.cpu_map = malloc(intel->maxBatchSize);
+   intel->batch.map = intel->batch.cpu_map;
 }
 
 static void
@@ -74,40 +53,11 @@ intel_batchbuffer_reset(struct intel_context *intel)
    }
    intel->batch.last_bo = intel->batch.bo;
 
-   clear_cache(intel);
-
    intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
                                        intel->maxBatchSize, 4096);
-   if (intel->has_llc) {
-      drm_intel_bo_map(intel->batch.bo, true);
-      intel->batch.map = intel->batch.bo->virtual;
-   }
 
    intel->batch.reserved_space = BATCH_RESERVED;
-   intel->batch.state_batch_offset = intel->batch.bo->size;
    intel->batch.used = 0;
-   intel->batch.needs_sol_reset = false;
-}
-
-void
-intel_batchbuffer_save_state(struct intel_context *intel)
-{
-   intel->batch.saved.used = intel->batch.used;
-   intel->batch.saved.reloc_count =
-      drm_intel_gem_bo_get_reloc_count(intel->batch.bo);
-}
-
-void
-intel_batchbuffer_reset_to_saved(struct intel_context *intel)
-{
-   drm_intel_gem_bo_clear_relocs(intel->batch.bo, intel->batch.saved.reloc_count);
-
-   intel->batch.used = intel->batch.saved.used;
-
-   /* Cached batch state is dead, since we just cleared some unknown part of the
-    * batchbuffer.  Assume that the caller resets any other state necessary.
-    */
-   clear_cache(intel);
 }
 
 void
@@ -116,8 +66,6 @@ intel_batchbuffer_free(struct intel_context *intel)
    free(intel->batch.cpu_map);
    drm_intel_bo_unreference(intel->batch.last_bo);
    drm_intel_bo_unreference(intel->batch.bo);
-   drm_intel_bo_unreference(intel->batch.workaround_bo);
-   clear_cache(intel);
 }
 
 static void
@@ -168,33 +116,14 @@ do_flush_locked(struct intel_context *intel)
    struct intel_batchbuffer *batch = &intel->batch;
    int ret = 0;
 
-   if (intel->has_llc) {
-      drm_intel_bo_unmap(batch->bo);
-   } else {
-      ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map);
-      if (ret == 0 && batch->state_batch_offset != batch->bo->size) {
-        ret = drm_intel_bo_subdata(batch->bo,
-                                   batch->state_batch_offset,
-                                   batch->bo->size - batch->state_batch_offset,
-                                   (char *)batch->map + batch->state_batch_offset);
-      }
-   }
+   ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map);
 
    if (!intel->intelScreen->no_hw) {
-      int flags = I915_EXEC_RENDER;
-      if (batch->needs_sol_reset)
-        flags |= I915_EXEC_GEN7_SOL_RESET;
-
       if (ret == 0) {
          if (unlikely(INTEL_DEBUG & DEBUG_AUB) && intel->vtbl.annotate_aub)
             intel->vtbl.annotate_aub(intel);
-        if (intel->hw_ctx == NULL || batch->is_blit) {
-           ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0,
-                                       flags);
-        } else {
-           ret = drm_intel_gem_bo_context_exec(batch->bo, intel->hw_ctx,
-                                               4 * batch->used, flags);
-        }
+         ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0,
+                                     I915_EXEC_RENDER);
       }
    }
 
@@ -313,178 +242,14 @@ intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
 
 void
 intel_batchbuffer_data(struct intel_context *intel,
-                       const void *data, GLuint bytes, bool is_blit)
+                       const void *data, GLuint bytes)
 {
    assert((bytes & 3) == 0);
-   intel_batchbuffer_require_space(intel, bytes, is_blit);
-   __memcpy(intel->batch.map + intel->batch.used, data, bytes);
+   intel_batchbuffer_require_space(intel, bytes);
+   memcpy(intel->batch.map + intel->batch.used, data, bytes);
    intel->batch.used += bytes >> 2;
 }
 
-void
-intel_batchbuffer_cached_advance(struct intel_context *intel)
-{
-   struct cached_batch_item **prev = &intel->batch.cached_items, *item;
-   uint32_t sz = (intel->batch.used - intel->batch.emit) * sizeof(uint32_t);
-   uint32_t *start = intel->batch.map + intel->batch.emit;
-   uint16_t op = *start >> 16;
-
-   while (*prev) {
-      uint32_t *old;
-
-      item = *prev;
-      old = intel->batch.map + item->header;
-      if (op == *old >> 16) {
-        if (item->size == sz && memcmp(old, start, sz) == 0) {
-           if (prev != &intel->batch.cached_items) {
-              *prev = item->next;
-              item->next = intel->batch.cached_items;
-              intel->batch.cached_items = item;
-           }
-           intel->batch.used = intel->batch.emit;
-           return;
-        }
-
-        goto emit;
-      }
-      prev = &item->next;
-   }
-
-   item = malloc(sizeof(struct cached_batch_item));
-   if (item == NULL)
-      return;
-
-   item->next = intel->batch.cached_items;
-   intel->batch.cached_items = item;
-
-emit:
-   item->size = sz;
-   item->header = intel->batch.emit;
-}
-
-/**
- * Restriction [DevSNB, DevIVB]:
- *
- * Prior to changing Depth/Stencil Buffer state (i.e. any combination of
- * 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS, 3DSTATE_STENCIL_BUFFER,
- * 3DSTATE_HIER_DEPTH_BUFFER) SW must first issue a pipelined depth stall
- * (PIPE_CONTROL with Depth Stall bit set), followed by a pipelined depth
- * cache flush (PIPE_CONTROL with Depth Flush Bit set), followed by
- * another pipelined depth stall (PIPE_CONTROL with Depth Stall bit set),
- * unless SW can otherwise guarantee that the pipeline from WM onwards is
- * already flushed (e.g., via a preceding MI_FLUSH).
- */
-void
-intel_emit_depth_stall_flushes(struct intel_context *intel)
-{
-   assert(intel->gen >= 6 && intel->gen <= 7);
-
-   BEGIN_BATCH(4);
-   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
-   OUT_BATCH(PIPE_CONTROL_DEPTH_STALL);
-   OUT_BATCH(0); /* address */
-   OUT_BATCH(0); /* write data */
-   ADVANCE_BATCH()
-
-   BEGIN_BATCH(4);
-   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
-   OUT_BATCH(PIPE_CONTROL_DEPTH_CACHE_FLUSH);
-   OUT_BATCH(0); /* address */
-   OUT_BATCH(0); /* write data */
-   ADVANCE_BATCH();
-
-   BEGIN_BATCH(4);
-   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
-   OUT_BATCH(PIPE_CONTROL_DEPTH_STALL);
-   OUT_BATCH(0); /* address */
-   OUT_BATCH(0); /* write data */
-   ADVANCE_BATCH();
-}
-
-/**
- * From the BSpec, volume 2a.03: VS Stage Input / State:
- * "[DevIVB] A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
- *  stall needs to be sent just prior to any 3DSTATE_VS, 3DSTATE_URB_VS,
- *  3DSTATE_CONSTANT_VS, 3DSTATE_BINDING_TABLE_POINTER_VS,
- *  3DSTATE_SAMPLER_STATE_POINTER_VS command.  Only one PIPE_CONTROL needs
- *  to be sent before any combination of VS associated 3DSTATE."
- */
-void
-gen7_emit_vs_workaround_flush(struct intel_context *intel)
-{
-   assert(intel->gen == 7);
-
-   BEGIN_BATCH(4);
-   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
-   OUT_BATCH(PIPE_CONTROL_DEPTH_STALL | PIPE_CONTROL_WRITE_IMMEDIATE);
-   OUT_RELOC(intel->batch.workaround_bo,
-            I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
-   OUT_BATCH(0); /* write data */
-   ADVANCE_BATCH();
-}
-
-/**
- * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
- * implementing two workarounds on gen6.  From section 1.4.7.1
- * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
- *
- * [DevSNB-C+{W/A}] Before any depth stall flush (including those
- * produced by non-pipelined state commands), software needs to first
- * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
- * 0.
- *
- * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
- * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
- *
- * And the workaround for these two requires this workaround first:
- *
- * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
- * BEFORE the pipe-control with a post-sync op and no write-cache
- * flushes.
- *
- * And this last workaround is tricky because of the requirements on
- * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
- * volume 2 part 1:
- *
- *     "1 of the following must also be set:
- *      - Render Target Cache Flush Enable ([12] of DW1)
- *      - Depth Cache Flush Enable ([0] of DW1)
- *      - Stall at Pixel Scoreboard ([1] of DW1)
- *      - Depth Stall ([13] of DW1)
- *      - Post-Sync Operation ([13] of DW1)
- *      - Notify Enable ([8] of DW1)"
- *
- * The cache flushes require the workaround flush that triggered this
- * one, so we can't use it.  Depth stall would trigger the same.
- * Post-sync nonzero is what triggered this second workaround, so we
- * can't use that one either.  Notify enable is IRQs, which aren't
- * really our business.  That leaves only stall at scoreboard.
- */
-void
-intel_emit_post_sync_nonzero_flush(struct intel_context *intel)
-{
-   if (!intel->batch.need_workaround_flush)
-      return;
-
-   BEGIN_BATCH(4);
-   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
-   OUT_BATCH(PIPE_CONTROL_CS_STALL |
-            PIPE_CONTROL_STALL_AT_SCOREBOARD);
-   OUT_BATCH(0); /* address */
-   OUT_BATCH(0); /* write data */
-   ADVANCE_BATCH();
-
-   BEGIN_BATCH(4);
-   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
-   OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
-   OUT_RELOC(intel->batch.workaround_bo,
-            I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
-   OUT_BATCH(0); /* write data */
-   ADVANCE_BATCH();
-
-   intel->batch.need_workaround_flush = false;
-}
-
 /* Emit a pipelined flush to either flush render and texture cache for
  * reading from a FBO-drawn texture, or flush so that frontbuffer
  * render appears on the screen in DRI1.