summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/intel/intel_batchbuffer.h
blob: 2d636df2ce5ab551cb0df93d9c2eb55aeedf4c05 (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
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H

#include "mtypes.h"

#include "dri_bufmgr.h"

struct intel_context;

#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.
    */
   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.
    */
   REFERENCES_CLIPRECTS
};

struct intel_batchbuffer
{
   struct intel_context *intel;

   dri_bo *buf;
   dri_fence *last_fence;

   GLubyte *map;
   GLubyte *ptr;

   enum cliprect_mode cliprect_mode;

   GLuint size;

   GLuint dirty_state;
};

struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
                                                  *intel);

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);

#define intel_batchbuffer_flush(batch) \
	_intel_batchbuffer_flush(batch, __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);

GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
                                       dri_bo *buffer,
                                       GLuint flags, GLuint 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
intel_batchbuffer_space(struct intel_batchbuffer *batch)
{
   return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
}


static INLINE void
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
{
   assert(batch->map);
   assert(intel_batchbuffer_space(batch) >= 4);
   *(GLuint *) (batch->ptr) = dword;
   batch->ptr += 4;
}

static INLINE void
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
                                GLuint sz,
				enum cliprect_mode cliprect_mode)
{
   assert(sz < batch->size - 8);
   if (intel_batchbuffer_space(batch) < sz)
      intel_batchbuffer_flush(batch);

   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);
      }
   }
}

/* 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); \
} while (0)

#define OUT_BATCH(d)  intel_batchbuffer_emit_dword(intel->batch, d)

#define OUT_RELOC(buf, cliprect_mode, delta) do { 			\
   assert((delta) >= 0);						\
   intel_batchbuffer_emit_reloc(intel->batch, buf, cliprect_mode, delta); \
} while (0)

#define ADVANCE_BATCH() do { } while(0)


#endif