#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
-#include "mtypes.h"
-#include "dri_bufmgr.h"
+#include "main/mtypes.h"
-struct intel_context;
+#include "intel_context.h"
+#include "intel_bufmgr.h"
+#include "intel_reg.h"
#define BATCH_SZ 16384
#define BATCH_RESERVED 16
-#define MAX_RELOCS 4096
-
-#define INTEL_BATCH_NO_CLIPRECTS 0x1
-#define INTEL_BATCH_CLIPRECTS 0x2
-
-struct buffer_reloc
-{
- dri_bo *buf;
- GLuint offset;
- GLuint delta; /* not needed? */
- GLuint validate_flags;
+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;
- dri_fence *last_fence;
- GLuint flags;
- drmBOList list;
- GLuint list_count;
+ GLubyte *buffer;
+
GLubyte *map;
GLubyte *ptr;
- struct buffer_reloc reloc[MAX_RELOCS];
- GLuint nr_relocs;
+ 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;
};
struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
void intel_batchbuffer_free(struct intel_batchbuffer *batch);
-void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
+void _intel_batchbuffer_flush(struct intel_batchbuffer *batch,
+ const char *file, int line);
-void intel_batchbuffer_flush(struct intel_batchbuffer *batch);
+#define intel_batchbuffer_flush(batch) \
+ _intel_batchbuffer_flush(batch, __FILE__, __LINE__)
void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
* intel_buffer_dword() calls.
*/
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
- const void *data, GLuint bytes, GLuint flags);
+ const void *data, GLuint bytes,
+ enum cliprect_mode cliprect_mode);
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
GLuint bytes);
GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
dri_bo *buffer,
- GLuint flags, GLuint offset);
+ uint32_t read_domains,
+ uint32_t write_domain,
+ uint32_t offset);
/* 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 GLuint
+static INLINE GLint
intel_batchbuffer_space(struct intel_batchbuffer *batch)
{
return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
static INLINE void
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
- GLuint sz, GLuint flags)
+ GLuint sz,
+ enum cliprect_mode cliprect_mode)
{
assert(sz < batch->size - 8);
- if (intel_batchbuffer_space(batch) < sz ||
- (batch->flags != 0 && flags != 0 && batch->flags != flags))
+ if (intel_batchbuffer_space(batch) < sz)
intel_batchbuffer_flush(batch);
- batch->flags |= flags;
+ 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;
+ }
+ }
+ }
}
/* Here are the crusty old macros, to be removed:
*/
#define BATCH_LOCALS
-#define BEGIN_BATCH(n, flags) do { \
- assert(!intel->prim.flush); \
- intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \
+#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 OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
-#define OUT_RELOC(buf, flags, delta) do { \
- assert((delta) >= 0); \
- intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta); \
+#define OUT_RELOC(buf, read_domains, write_domain, delta) do { \
+ assert((unsigned) (delta) < buf->size); \
+ intel_batchbuffer_emit_reloc(intel->batch, buf, \
+ read_domains, write_domain, delta); \
} while (0)
-#define ADVANCE_BATCH() do { } while(0)
+#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)
+
+static INLINE void
+intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch)
+{
+ intel_batchbuffer_require_space(batch, 4, IGNORE_CLIPRECTS);
+ intel_batchbuffer_emit_dword(batch, MI_FLUSH);
+}
#endif