mesa: s/CALLOC/calloc/
[mesa.git] / src / mesa / drivers / dri / intel / intel_batchbuffer.h
index d4a94454dd52261bdf39336d99313d2582ef7061..b8b60cd862ba206cb5a785c4c849dee5692ab2b6 100644 (file)
 #include "intel_bufmgr.h"
 #include "intel_reg.h"
 
-#define BATCH_SZ 16384
-#define BATCH_RESERVED 16
-
-enum cliprect_mode {
-   /**
-    * Batchbuffer contents may be looped over per cliprect, but do not
-    * require it.
-    */
-   IGNORE_CLIPRECTS,
-   /**
-    * Batchbuffer contents require looping over per cliprect at batch submit
-    * time.
-    *
-    * This will be upgraded to NO_LOOP_CLIPRECTS when there's a single
-    * constant cliprect, as in DRI2 or FBO rendering.
-    */
-   LOOP_CLIPRECTS,
-   /**
-    * Batchbuffer contents contain drawing that should not be executed multiple
-    * times.
-    */
-   NO_LOOP_CLIPRECTS,
-   /**
-    * Batchbuffer contents contain drawing that already handles cliprects, such
-    * as 2D drawing to front/back/depth that doesn't respect DRAWING_RECTANGLE.
-    *
-    * Equivalent behavior to NO_LOOP_CLIPRECTS, but may not persist in batch
-    * outside of LOCK/UNLOCK.  This is upgraded to just NO_LOOP_CLIPRECTS when
-    * there's a constant cliprect, as in DRI2 or FBO rendering.
-    */
-   REFERENCES_CLIPRECTS
-};
-
-struct intel_batchbuffer
-{
-   struct intel_context *intel;
-
-   dri_bo *buf;
-
-   GLubyte *buffer;
-
-   GLubyte *map;
-   GLubyte *ptr;
-
-   enum cliprect_mode cliprect_mode;
-
-   GLuint size;
-
-   /** Tracking of BEGIN_BATCH()/OUT_BATCH()/ADVANCE_BATCH() debugging */
-   struct {
-      GLuint total;
-      GLubyte *start_ptr;
-   } emit;
-
-   GLuint dirty_state;
-   GLuint reserved_space;
-};
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
-                                                  *intel);
+/**
+ * Number of bytes to reserve for commands necessary to complete a batch.
+ *
+ * This includes:
+ * - MI_BATCHBUFFER_END (4 bytes)
+ * - Optional MI_NOOP for ensuring the batch length is qword aligned (4 bytes)
+ * - Any state emitted by vtbl->finish_batch()
+ *   - On 965+, this means ending occlusion queries (on Gen6, which has the
+ *     most workaround flushes, this can be as much as (4+4+5)*4 = 52 bytes)
+ */
+#define BATCH_RESERVED 60
 
-void intel_batchbuffer_free(struct intel_batchbuffer *batch);
+struct intel_batchbuffer;
 
+void intel_batchbuffer_init(struct intel_context *intel);
+void intel_batchbuffer_reset(struct intel_context *intel);
+void intel_batchbuffer_free(struct intel_context *intel);
+void intel_batchbuffer_save_state(struct intel_context *intel);
+void intel_batchbuffer_reset_to_saved(struct intel_context *intel);
 
-void _intel_batchbuffer_flush(struct intel_batchbuffer *batch,
-                             const char *file, int line);
+int _intel_batchbuffer_flush(struct intel_context *intel,
+                            const char *file, int line);
 
-#define intel_batchbuffer_flush(batch) \
-       _intel_batchbuffer_flush(batch, __FILE__, __LINE__)
+#define intel_batchbuffer_flush(intel) \
+       _intel_batchbuffer_flush(intel, __FILE__, __LINE__)
 
-void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
 
 
 /* Unlike bmBufferData, this currently requires the buffer be mapped.
  * Consider it a convenience function wrapping multple
  * intel_buffer_dword() calls.
  */
-void intel_batchbuffer_data(struct intel_batchbuffer *batch,
-                            const void *data, GLuint bytes,
-                           enum cliprect_mode cliprect_mode);
-
-void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
-                                     GLuint bytes);
+void intel_batchbuffer_data(struct intel_context *intel,
+                            const void *data, GLuint bytes, bool is_blit);
 
-GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
-                                       dri_bo *buffer,
+bool intel_batchbuffer_emit_reloc(struct intel_context *intel,
+                                       drm_intel_bo *buffer,
                                       uint32_t read_domains,
                                       uint32_t write_domain,
                                       uint32_t offset);
-void intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch);
+bool intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
+                                             drm_intel_bo *buffer,
+                                             uint32_t read_domains,
+                                             uint32_t write_domain,
+                                             uint32_t offset);
+void intel_batchbuffer_emit_mi_flush(struct intel_context *intel);
+void intel_emit_post_sync_nonzero_flush(struct intel_context *intel);
+void intel_emit_depth_stall_flushes(struct intel_context *intel);
+void gen7_emit_vs_workaround_flush(struct intel_context *intel);
+
+static INLINE uint32_t float_as_int(float f)
+{
+   union {
+      float f;
+      uint32_t d;
+   } fi;
+
+   fi.f = f;
+   return fi.d;
+}
 
 /* Inline functions - might actually be better off with these
  * non-inlined.  Certainly better off switching all command packets to
  * be passed as structs rather than dwords, but that's a little bit of
  * work...
  */
-static INLINE GLint
-intel_batchbuffer_space(struct intel_batchbuffer *batch)
+static INLINE unsigned
+intel_batchbuffer_space(struct intel_context *intel)
 {
-   return (batch->size - batch->reserved_space) - (batch->ptr - batch->map);
+   return (intel->batch.state_batch_offset - intel->batch.reserved_space)
+      - intel->batch.used*4;
 }
 
 
 static INLINE void
-intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
+intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword)
 {
-   assert(batch->map);
-   assert(intel_batchbuffer_space(batch) >= 4);
-   *(GLuint *) (batch->ptr) = dword;
-   batch->ptr += 4;
+#ifdef DEBUG
+   assert(intel_batchbuffer_space(intel) >= 4);
+#endif
+   intel->batch.map[intel->batch.used++] = dword;
 }
 
 static INLINE void
-intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
-                                GLuint sz,
-                               enum cliprect_mode cliprect_mode)
+intel_batchbuffer_emit_float(struct intel_context *intel, float f)
 {
-   assert(sz < batch->size - 8);
-   if (intel_batchbuffer_space(batch) < sz)
-      intel_batchbuffer_flush(batch);
-
-   if ((cliprect_mode == LOOP_CLIPRECTS ||
-       cliprect_mode == REFERENCES_CLIPRECTS) &&
-       batch->intel->constant_cliprect)
-      cliprect_mode = NO_LOOP_CLIPRECTS;
-
-   if (cliprect_mode != IGNORE_CLIPRECTS) {
-      if (batch->cliprect_mode == IGNORE_CLIPRECTS) {
-        batch->cliprect_mode = cliprect_mode;
-      } else {
-        if (batch->cliprect_mode != cliprect_mode) {
-           intel_batchbuffer_flush(batch);
-           batch->cliprect_mode = cliprect_mode;
-        }
-      }
+   intel_batchbuffer_emit_dword(intel, float_as_int(f));
+}
+
+static INLINE void
+intel_batchbuffer_require_space(struct intel_context *intel,
+                                GLuint sz, int is_blit)
+{
+
+   if (intel->gen >= 6 &&
+       intel->batch.is_blit != is_blit && intel->batch.used) {
+      intel_batchbuffer_flush(intel);
    }
+
+   intel->batch.is_blit = is_blit;
+
+#ifdef DEBUG
+   assert(sz < sizeof(intel->batch.map) - BATCH_RESERVED);
+#endif
+   if (intel_batchbuffer_space(intel) < sz)
+      intel_batchbuffer_flush(intel);
 }
 
+static INLINE void
+intel_batchbuffer_begin(struct intel_context *intel, int n, bool is_blit)
+{
+   intel_batchbuffer_require_space(intel, n * 4, is_blit);
+
+   intel->batch.emit = intel->batch.used;
+#ifdef DEBUG
+   intel->batch.total = n;
+#endif
+}
+
+static INLINE void
+intel_batchbuffer_advance(struct intel_context *intel)
+{
+#ifdef DEBUG
+   struct intel_batchbuffer *batch = &intel->batch;
+   unsigned int _n = batch->used - batch->emit;
+   assert(batch->total != 0);
+   if (_n != batch->total) {
+      fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n",
+             _n, batch->total);
+      abort();
+   }
+   batch->total = 0;
+#endif
+}
+
+void intel_batchbuffer_cached_advance(struct intel_context *intel);
+
 /* Here are the crusty old macros, to be removed:
  */
 #define BATCH_LOCALS
 
-#define BEGIN_BATCH(n, cliprect_mode) do {                             \
-   intel_batchbuffer_require_space(intel->batch, (n)*4, cliprect_mode); \
-   assert(intel->batch->emit.start_ptr == NULL);                       \
-   intel->batch->emit.total = (n) * 4;                                 \
-   intel->batch->emit.start_ptr = intel->batch->ptr;                   \
-} while (0)
-
-#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
-
+#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel, n, false)
+#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel, n, true)
+#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel, d)
+#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel,f)
 #define OUT_RELOC(buf, read_domains, write_domain, delta) do {         \
-   assert((unsigned) (delta) < buf->size);                             \
-   intel_batchbuffer_emit_reloc(intel->batch, buf,                     \
+   intel_batchbuffer_emit_reloc(intel, buf,                    \
                                read_domains, write_domain, delta);     \
 } while (0)
+#define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do {  \
+   intel_batchbuffer_emit_reloc_fenced(intel, buf,             \
+                                      read_domains, write_domain, delta); \
+} while (0)
+
+#define ADVANCE_BATCH() intel_batchbuffer_advance(intel);
+#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel);
 
-#define ADVANCE_BATCH() do {                                           \
-   unsigned int _n = intel->batch->ptr - intel->batch->emit.start_ptr; \
-   assert(intel->batch->emit.start_ptr != NULL);                       \
-   if (_n != intel->batch->emit.total) {                               \
-      fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n",      \
-             _n, intel->batch->emit.total);                            \
-      abort();                                                         \
-   }                                                                   \
-   intel->batch->emit.start_ptr = NULL;                                        \
-} while(0)
+#ifdef __cplusplus
+}
+#endif
 
 #endif