intel_batchbuffer.h revision 03b705cf
103b705cfSriastradh/**************************************************************************
203b705cfSriastradh
303b705cfSriastradhCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
403b705cfSriastradhCopyright © 2002 David Dawes
503b705cfSriastradh
603b705cfSriastradhAll Rights Reserved.
703b705cfSriastradh
803b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a
903b705cfSriastradhcopy of this software and associated documentation files (the
1003b705cfSriastradh"Software"), to deal in the Software without restriction, including
1103b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish,
1203b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to
1303b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to
1403b705cfSriastradhthe following conditions:
1503b705cfSriastradh
1603b705cfSriastradhThe above copyright notice and this permission notice (including the
1703b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions
1803b705cfSriastradhof the Software.
1903b705cfSriastradh
2003b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2103b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2203b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2303b705cfSriastradhIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2403b705cfSriastradhANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2503b705cfSriastradhTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2603b705cfSriastradhSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2703b705cfSriastradh
2803b705cfSriastradh**************************************************************************/
2903b705cfSriastradh
3003b705cfSriastradh#ifndef _INTEL_BATCHBUFFER_H
3103b705cfSriastradh#define _INTEL_BATCHBUFFER_H
3203b705cfSriastradh
3303b705cfSriastradh#define BATCH_RESERVED		16
3403b705cfSriastradh
3503b705cfSriastradh
3603b705cfSriastradhvoid intel_batch_init(ScrnInfoPtr scrn);
3703b705cfSriastradhvoid intel_batch_teardown(ScrnInfoPtr scrn);
3803b705cfSriastradhvoid intel_batch_emit_flush(ScrnInfoPtr scrn);
3903b705cfSriastradhvoid intel_batch_submit(ScrnInfoPtr scrn);
4003b705cfSriastradh
4103b705cfSriastradhstatic inline int intel_batch_space(intel_screen_private *intel)
4203b705cfSriastradh{
4303b705cfSriastradh	return (intel->batch_bo->size - BATCH_RESERVED) - (4*intel->batch_used);
4403b705cfSriastradh}
4503b705cfSriastradh
4603b705cfSriastradhstatic inline int intel_vertex_space(intel_screen_private *intel)
4703b705cfSriastradh{
4803b705cfSriastradh	return intel->vertex_bo ? intel->vertex_bo->size - (4*intel->vertex_used) : 0;
4903b705cfSriastradh}
5003b705cfSriastradh
5103b705cfSriastradhstatic inline void
5203b705cfSriastradhintel_batch_require_space(ScrnInfoPtr scrn, intel_screen_private *intel, int sz)
5303b705cfSriastradh{
5403b705cfSriastradh	assert(sz < intel->batch_bo->size - 8);
5503b705cfSriastradh	if (intel_batch_space(intel) < sz)
5603b705cfSriastradh		intel_batch_submit(scrn);
5703b705cfSriastradh}
5803b705cfSriastradh
5903b705cfSriastradhstatic inline void intel_batch_start_atomic(ScrnInfoPtr scrn, int sz)
6003b705cfSriastradh{
6103b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
6203b705cfSriastradh
6303b705cfSriastradh	assert(!intel->in_batch_atomic);
6403b705cfSriastradh
6503b705cfSriastradh	if (intel->current_batch != RENDER_BATCH) {
6603b705cfSriastradh		if (intel->current_batch && intel->context_switch)
6703b705cfSriastradh			intel->context_switch(intel, RENDER_BATCH);
6803b705cfSriastradh	}
6903b705cfSriastradh
7003b705cfSriastradh	intel_batch_require_space(scrn, intel, sz * 4);
7103b705cfSriastradh	intel->current_batch = RENDER_BATCH;
7203b705cfSriastradh
7303b705cfSriastradh	intel->in_batch_atomic = TRUE;
7403b705cfSriastradh	intel->batch_atomic_limit = intel->batch_used + sz;
7503b705cfSriastradh}
7603b705cfSriastradh
7703b705cfSriastradhstatic inline void intel_batch_end_atomic(ScrnInfoPtr scrn)
7803b705cfSriastradh{
7903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
8003b705cfSriastradh
8103b705cfSriastradh	assert(intel->in_batch_atomic);
8203b705cfSriastradh	assert(intel->batch_used <= intel->batch_atomic_limit);
8303b705cfSriastradh	intel->in_batch_atomic = FALSE;
8403b705cfSriastradh}
8503b705cfSriastradh
8603b705cfSriastradhstatic inline void intel_batch_emit_dword(intel_screen_private *intel, uint32_t dword)
8703b705cfSriastradh{
8803b705cfSriastradh	intel->batch_ptr[intel->batch_used++] = dword;
8903b705cfSriastradh}
9003b705cfSriastradh
9103b705cfSriastradhstatic inline void intel_batch_align(intel_screen_private *intel, uint32_t align)
9203b705cfSriastradh{
9303b705cfSriastradh	uint32_t delta;
9403b705cfSriastradh
9503b705cfSriastradh	align /= 4;
9603b705cfSriastradh	assert(align);
9703b705cfSriastradh
9803b705cfSriastradh	if ((delta = intel->batch_used & (align - 1))) {
9903b705cfSriastradh		delta = align - delta;
10003b705cfSriastradh		memset (intel->batch_ptr + intel->batch_used, 0, 4*delta);
10103b705cfSriastradh		intel->batch_used += delta;
10203b705cfSriastradh	}
10303b705cfSriastradh}
10403b705cfSriastradh
10503b705cfSriastradhstatic inline void
10603b705cfSriastradhintel_batch_emit_reloc(intel_screen_private *intel,
10703b705cfSriastradh		       dri_bo * bo,
10803b705cfSriastradh		       uint32_t read_domains,
10903b705cfSriastradh		       uint32_t write_domains, uint32_t delta, int needs_fence)
11003b705cfSriastradh{
11103b705cfSriastradh	if (needs_fence)
11203b705cfSriastradh		drm_intel_bo_emit_reloc_fence(intel->batch_bo,
11303b705cfSriastradh					      intel->batch_used * 4,
11403b705cfSriastradh					      bo, delta,
11503b705cfSriastradh					      read_domains, write_domains);
11603b705cfSriastradh	else
11703b705cfSriastradh		drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used * 4,
11803b705cfSriastradh					bo, delta,
11903b705cfSriastradh					read_domains, write_domains);
12003b705cfSriastradh
12103b705cfSriastradh	intel_batch_emit_dword(intel, bo->offset + delta);
12203b705cfSriastradh}
12303b705cfSriastradh
12403b705cfSriastradhstatic inline void
12503b705cfSriastradhintel_batch_mark_pixmap_domains(intel_screen_private *intel,
12603b705cfSriastradh				struct intel_pixmap *priv,
12703b705cfSriastradh				uint32_t read_domains, uint32_t write_domain)
12803b705cfSriastradh{
12903b705cfSriastradh	assert (read_domains);
13003b705cfSriastradh	assert (write_domain == 0 || write_domain == read_domains);
13103b705cfSriastradh
13203b705cfSriastradh	if (list_is_empty(&priv->batch))
13303b705cfSriastradh		list_add(&priv->batch, &intel->batch_pixmaps);
13403b705cfSriastradh
13503b705cfSriastradh	priv->dirty |= write_domain != 0;
13603b705cfSriastradh	priv->busy = 1;
13703b705cfSriastradh
13803b705cfSriastradh	intel->needs_flush |= write_domain != 0;
13903b705cfSriastradh}
14003b705cfSriastradh
14103b705cfSriastradhstatic inline void
14203b705cfSriastradhintel_batch_emit_reloc_pixmap(intel_screen_private *intel, PixmapPtr pixmap,
14303b705cfSriastradh			      uint32_t read_domains, uint32_t write_domain,
14403b705cfSriastradh			      uint32_t delta, int needs_fence)
14503b705cfSriastradh{
14603b705cfSriastradh	struct intel_pixmap *priv = intel_get_pixmap_private(pixmap);
14703b705cfSriastradh
14803b705cfSriastradh	intel_batch_mark_pixmap_domains(intel, priv, read_domains, write_domain);
14903b705cfSriastradh
15003b705cfSriastradh	intel_batch_emit_reloc(intel, priv->bo,
15103b705cfSriastradh			       read_domains, write_domain,
15203b705cfSriastradh			       delta, needs_fence);
15303b705cfSriastradh}
15403b705cfSriastradh
15503b705cfSriastradh#define ALIGN_BATCH(align) intel_batch_align(intel, align);
15603b705cfSriastradh#define OUT_BATCH(dword) intel_batch_emit_dword(intel, dword)
15703b705cfSriastradh
15803b705cfSriastradh#define OUT_RELOC(bo, read_domains, write_domains, delta) \
15903b705cfSriastradh	intel_batch_emit_reloc(intel, bo, read_domains, write_domains, delta, 0)
16003b705cfSriastradh
16103b705cfSriastradh#define OUT_RELOC_FENCED(bo, read_domains, write_domains, delta) \
16203b705cfSriastradh	intel_batch_emit_reloc(intel, bo, read_domains, write_domains, delta, 1)
16303b705cfSriastradh
16403b705cfSriastradh#define OUT_RELOC_PIXMAP(pixmap, reads, write, delta)	\
16503b705cfSriastradh	intel_batch_emit_reloc_pixmap(intel, pixmap, reads, write, delta, 0)
16603b705cfSriastradh
16703b705cfSriastradh#define OUT_RELOC_PIXMAP_FENCED(pixmap, reads, write, delta)	\
16803b705cfSriastradh	intel_batch_emit_reloc_pixmap(intel, pixmap, reads, write, delta, 1)
16903b705cfSriastradh
17003b705cfSriastradhunion intfloat {
17103b705cfSriastradh	float f;
17203b705cfSriastradh	unsigned int ui;
17303b705cfSriastradh};
17403b705cfSriastradh
17503b705cfSriastradh#define OUT_BATCH_F(x) do {			\
17603b705cfSriastradh	union intfloat tmp;			\
17703b705cfSriastradh	tmp.f = (float)(x);			\
17803b705cfSriastradh	OUT_BATCH(tmp.ui);			\
17903b705cfSriastradh} while(0)
18003b705cfSriastradh
18103b705cfSriastradh#define __BEGIN_BATCH(n,batch_idx)					\
18203b705cfSriastradhdo {									\
18303b705cfSriastradh	if (intel->batch_emitting != 0)					\
18403b705cfSriastradh		FatalError("%s: BEGIN_BATCH called without closing "	\
18503b705cfSriastradh			   "ADVANCE_BATCH\n", __FUNCTION__);		\
18603b705cfSriastradh	assert(!intel->in_batch_atomic);				\
18703b705cfSriastradh	if (intel->current_batch != batch_idx) {			\
18803b705cfSriastradh		if (intel->current_batch && intel->context_switch)	\
18903b705cfSriastradh			intel->context_switch(intel, batch_idx);	\
19003b705cfSriastradh	}								\
19103b705cfSriastradh	intel_batch_require_space(scrn, intel, (n) * 4);		\
19203b705cfSriastradh	intel->current_batch = batch_idx;				\
19303b705cfSriastradh	intel->batch_emitting = (n);					\
19403b705cfSriastradh	intel->batch_emit_start = intel->batch_used;			\
19503b705cfSriastradh} while (0)
19603b705cfSriastradh
19703b705cfSriastradh#define BEGIN_BATCH(n)	__BEGIN_BATCH(n,RENDER_BATCH)
19803b705cfSriastradh#define BEGIN_BATCH_BLT(n)	__BEGIN_BATCH(n,BLT_BATCH)
19903b705cfSriastradh
20003b705cfSriastradh#define ADVANCE_BATCH() do {						\
20103b705cfSriastradh	if (intel->batch_emitting == 0)					\
20203b705cfSriastradh		FatalError("%s: ADVANCE_BATCH called with no matching "	\
20303b705cfSriastradh			   "BEGIN_BATCH\n", __FUNCTION__);		\
20403b705cfSriastradh	if (intel->batch_used >						\
20503b705cfSriastradh	    intel->batch_emit_start + intel->batch_emitting)		\
20603b705cfSriastradh		FatalError("%s: ADVANCE_BATCH: exceeded allocation %d/%d\n ", \
20703b705cfSriastradh			   __FUNCTION__,				\
20803b705cfSriastradh			   intel->batch_used - intel->batch_emit_start,	\
20903b705cfSriastradh			   intel->batch_emitting);			\
21003b705cfSriastradh	if (intel->batch_used < intel->batch_emit_start +		\
21103b705cfSriastradh	    intel->batch_emitting)					\
21203b705cfSriastradh		FatalError("%s: ADVANCE_BATCH: under-used allocation %d/%d\n ", \
21303b705cfSriastradh			   __FUNCTION__,				\
21403b705cfSriastradh			   intel->batch_used - intel->batch_emit_start,	\
21503b705cfSriastradh			   intel->batch_emitting);			\
21603b705cfSriastradh	intel->batch_emitting = 0;					\
21703b705cfSriastradh} while (0)
21803b705cfSriastradh
21903b705cfSriastradhvoid intel_next_vertex(intel_screen_private *intel);
22003b705cfSriastradhstatic inline void intel_vertex_emit(intel_screen_private *intel, float v)
22103b705cfSriastradh{
22203b705cfSriastradh	intel->vertex_ptr[intel->vertex_used++] = v;
22303b705cfSriastradh}
22403b705cfSriastradh#define OUT_VERTEX(v) intel_vertex_emit(intel, v)
22503b705cfSriastradh
22603b705cfSriastradh#endif /* _INTEL_BATCHBUFFER_H */
227