summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/i965/brw_batchbuffer.h
blob: 288a9d275556b59144bfada8d2d8264a40c7629d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef BRW_BATCHBUFFER_H
#define BRW_BATCHBUFFER_H

#include "util/u_debug.h"

#include "brw_types.h"
#include "brw_winsys.h"
#include "brw_reg.h"

#define BATCH_SZ 16384
#define BATCH_RESERVED 16

/* All ignored:
 */
enum cliprect_mode {
   IGNORE_CLIPRECTS,
   LOOP_CLIPRECTS,
   NO_LOOP_CLIPRECTS,
   REFERENCES_CLIPRECTS
};




struct brw_batchbuffer {

   struct brw_winsys_screen *sws;
   struct brw_winsys_buffer *buf;
   struct brw_chipset chipset;

   /* Main-memory copy of the batch-buffer, built up incrementally &
    * then copied as one to the true buffer.
    *
    * XXX: is this still necessary?
    * XXX: if so, can this be hidden inside the GEM-specific winsys code?
    */
   boolean use_malloc_buffer;
   uint8_t *malloc_buffer;

   /**
    * Values exported to speed up the writing the batchbuffer,
    * instead of having to go trough a accesor function for
    * each dword written.
    */
   /*{@*/
   uint8_t *map;
   uint8_t *ptr;
   size_t size;
   struct {
      uint8_t *end_ptr;
   } emit;


   size_t relocs;
   size_t max_relocs;
   /*@}*/
};

struct brw_batchbuffer *brw_batchbuffer_alloc( struct brw_winsys_screen *sws,
                                               struct brw_chipset chipset );

void brw_batchbuffer_free(struct brw_batchbuffer *batch);

void _brw_batchbuffer_flush(struct brw_batchbuffer *batch,
			      const char *file, int line);


enum pipe_error
brw_batchbuffer_reset(struct brw_batchbuffer *batch);


/* Unlike bmBufferData, this currently requires the buffer be mapped.
 * Consider it a convenience function wrapping multple
 * intel_buffer_dword() calls.
 */
int brw_batchbuffer_data(struct brw_batchbuffer *batch,
                            const void *data, GLuint bytes,
			    enum cliprect_mode cliprect_mode);


int brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
			       struct brw_winsys_buffer *buffer,
			       enum brw_buffer_usage usage,
			       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 GLint
brw_batchbuffer_space(struct brw_batchbuffer *batch)
{
   return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
}


static INLINE void
brw_batchbuffer_emit_dword(struct brw_batchbuffer *batch, GLuint dword)
{
   assert(batch->map);
   assert(brw_batchbuffer_space(batch) >= 4);
   *(GLuint *) (batch->ptr) = dword;
   batch->ptr += 4;
}

static INLINE enum pipe_error
brw_batchbuffer_require_space(struct brw_batchbuffer *batch,
                                GLuint sz)
{
   assert(sz < batch->size - 8);
   if (brw_batchbuffer_space(batch) < sz) {
      assert(0);
      return PIPE_ERROR_OUT_OF_MEMORY;
   }
#ifdef DEBUG
   batch->emit.end_ptr = batch->ptr + sz;
#endif
   return 0;
}

/* Here are the crusty old macros, to be removed:
 */
#define BEGIN_BATCH(n, cliprect_mode) do {				\
      brw_batchbuffer_require_space(brw->batch, (n)*4);			\
   } while (0)

#define OUT_BATCH(d) brw_batchbuffer_emit_dword(brw->batch, d)

#define OUT_RELOC(buf, usage, delta) do {				\
      assert((unsigned) (delta) < buf->size);				\
      brw_batchbuffer_emit_reloc(brw->batch, buf,			\
				 usage, delta);				\
   } while (0)

#ifdef DEBUG
#define ADVANCE_BATCH() do {						\
      unsigned int _n = brw->batch->ptr - brw->batch->emit.end_ptr;	\
      if (_n != 0) {							\
	 debug_printf("%s: %d too many bytes emitted to batch\n",	\
		      __FUNCTION__, _n);				\
	 abort();							\
      }									\
      brw->batch->emit.end_ptr = NULL;					\
   } while(0)
#else
#define ADVANCE_BATCH()
#endif

static INLINE void
brw_batchbuffer_emit_mi_flush(struct brw_batchbuffer *batch)
{
   brw_batchbuffer_require_space(batch, 4);
   brw_batchbuffer_emit_dword(batch, MI_FLUSH);
}

#endif