1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4Copyright © 2002 David Dawes
5
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sub license, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial portions
18of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30#ifndef _INTEL_BATCHBUFFER_H
31#define _INTEL_BATCHBUFFER_H
32
33#define BATCH_RESERVED		16
34
35void intel_batch_init(ScrnInfoPtr pScrn);
36void intel_batch_teardown(ScrnInfoPtr pScrn);
37void intel_batch_flush(ScrnInfoPtr pScrn, Bool flushed);
38void intel_batch_wait_last(ScrnInfoPtr pScrn);
39
40static inline int
41intel_batch_space(I830Ptr pI830)
42{
43    return (pI830->batch_bo->size - BATCH_RESERVED) - (pI830->batch_used);
44}
45
46static inline void
47intel_batch_require_space(ScrnInfoPtr pScrn, I830Ptr pI830, GLuint sz)
48{
49    assert(sz < pI830->batch_bo->size - 8);
50    if (intel_batch_space(pI830) < sz)
51	intel_batch_flush(pScrn, FALSE);
52}
53
54static inline void
55intel_batch_start_atomic(ScrnInfoPtr pScrn, unsigned int sz)
56{
57    I830Ptr pI830 = I830PTR(pScrn);
58
59    assert(!pI830->in_batch_atomic);
60    intel_batch_require_space(pScrn, pI830, sz * 4);
61
62    pI830->in_batch_atomic = TRUE;
63    pI830->batch_atomic_limit = pI830->batch_used + sz * 4;
64}
65
66static inline void
67intel_batch_end_atomic(ScrnInfoPtr pScrn)
68{
69    I830Ptr pI830 = I830PTR(pScrn);
70
71    assert(pI830->in_batch_atomic);
72    assert(pI830->batch_used <= pI830->batch_atomic_limit);
73    pI830->in_batch_atomic = FALSE;
74}
75
76static inline void
77intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
78{
79    assert(pI830->batch_ptr != NULL);
80    assert(intel_batch_space(pI830) >= 4);
81    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = dword;
82    pI830->batch_used += 4;
83}
84
85static inline void
86intel_batch_emit_reloc (I830Ptr  pI830,
87			dri_bo  *bo,
88			uint32_t read_domains,
89			uint32_t write_domains,
90			uint32_t delta)
91{
92    assert(intel_batch_space(pI830) >= 4);
93    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = bo->offset + delta;
94    dri_bo_emit_reloc(pI830->batch_bo, read_domains, write_domains, delta,
95		      pI830->batch_used, bo);
96    pI830->batch_used += 4;
97}
98
99static inline void
100intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap,
101			      uint32_t read_domains, uint32_t write_domain,
102			      uint32_t delta)
103{
104    dri_bo *bo = i830_get_pixmap_bo(pPixmap);
105    uint32_t offset;
106    assert(pI830->batch_ptr != NULL);
107    assert(intel_batch_space(pI830) >= 4);
108    if (bo) {
109	intel_batch_emit_reloc(pI830, bo, read_domains, write_domain, delta);
110	return;
111    }
112    offset = intel_get_pixmap_offset(pPixmap);
113    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = offset + delta;
114    pI830->batch_used += 4;
115}
116
117#define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
118
119#define OUT_RELOC(bo, read_domains, write_domains, delta) \
120	intel_batch_emit_reloc (pI830, bo, read_domains, write_domains, delta)
121
122#define OUT_RELOC_PIXMAP(pPixmap, reads, write, delta)	\
123	intel_batch_emit_reloc_pixmap(pI830, pPixmap, reads, write, delta)
124
125union intfloat {
126	float f;
127	unsigned int ui;
128};
129
130#define OUT_BATCH_F(x) do {			\
131	union intfloat tmp;			\
132	tmp.f = (float)(x);			\
133	OUT_BATCH(tmp.ui);			\
134} while(0)
135
136#define BEGIN_BATCH(n)							\
137do {									\
138    if (pI830->batch_emitting != 0)					\
139	FatalError("%s: BEGIN_BATCH called without closing "		\
140		   "ADVANCE_BATCH\n", __FUNCTION__);			\
141    intel_batch_require_space(pScrn, pI830, (n) * 4);			\
142    pI830->batch_emitting = (n) * 4;					\
143    pI830->batch_emit_start = pI830->batch_used;			\
144} while (0)
145
146#define ADVANCE_BATCH() do {						\
147    if (pI830->batch_emitting == 0)					\
148	FatalError("%s: ADVANCE_BATCH called with no matching "		\
149		   "BEGIN_BATCH\n", __FUNCTION__);			\
150    if (pI830->batch_used > pI830->batch_emit_start + pI830->batch_emitting) \
151	FatalError("%s: ADVANCE_BATCH: exceeded allocation %d/%d\n ",	\
152		   __FUNCTION__,					\
153		   pI830->batch_used - pI830->batch_emit_start,		\
154		   pI830->batch_emitting);				\
155    if (pI830->batch_used < pI830->batch_emit_start + pI830->batch_emitting) \
156	FatalError("%s: ADVANCE_BATCH: under-used allocation %d/%d\n ", \
157		   __FUNCTION__,					\
158		   pI830->batch_used - pI830->batch_emit_start,		\
159		   pI830->batch_emitting);				\
160    if ((pI830->batch_emitting > 8) && (I810_DEBUG & DEBUG_ALWAYS_SYNC)) { \
161	/* Note: not actually syncing, just flushing each batch. */	\
162	intel_batch_flush(pScrn, FALSE);					\
163    }									\
164    pI830->batch_emitting = 0;						\
165} while (0)
166
167#endif /* _INTEL_BATCHBUFFER_H */
168