You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
10 KiB
358 lines
10 KiB
#ifndef INTEL_BATCHBUFFER_H
|
|
#define INTEL_BATCHBUFFER_H
|
|
|
|
#include <stdint.h>
|
|
#include <intel_bufmgr.h>
|
|
#include <i915_drm.h>
|
|
|
|
#include "igt_core.h"
|
|
#include "intel_reg.h"
|
|
|
|
#define BATCH_SZ 4096
|
|
#define BATCH_RESERVED 16
|
|
|
|
struct intel_batchbuffer {
|
|
drm_intel_bufmgr *bufmgr;
|
|
uint32_t devid;
|
|
int gen;
|
|
|
|
drm_intel_context *ctx;
|
|
drm_intel_bo *bo;
|
|
|
|
uint8_t buffer[BATCH_SZ];
|
|
uint8_t *ptr, *end;
|
|
};
|
|
|
|
struct intel_batchbuffer *intel_batchbuffer_alloc(drm_intel_bufmgr *bufmgr,
|
|
uint32_t devid);
|
|
|
|
void intel_batchbuffer_set_context(struct intel_batchbuffer *batch,
|
|
drm_intel_context *ctx);
|
|
|
|
|
|
void intel_batchbuffer_free(struct intel_batchbuffer *batch);
|
|
|
|
|
|
void intel_batchbuffer_flush(struct intel_batchbuffer *batch);
|
|
void intel_batchbuffer_flush_on_ring(struct intel_batchbuffer *batch, int ring);
|
|
void intel_batchbuffer_flush_with_context(struct intel_batchbuffer *batch,
|
|
drm_intel_context *context);
|
|
|
|
void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
|
|
|
|
uint32_t intel_batchbuffer_copy_data(struct intel_batchbuffer *batch,
|
|
const void *data, unsigned int bytes,
|
|
uint32_t align);
|
|
|
|
void intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
|
|
drm_intel_bo *buffer,
|
|
uint64_t delta,
|
|
uint32_t read_domains,
|
|
uint32_t write_domain,
|
|
int fenced);
|
|
|
|
uint32_t
|
|
intel_batchbuffer_align(struct intel_batchbuffer *batch, uint32_t align);
|
|
|
|
void *
|
|
intel_batchbuffer_subdata_alloc(struct intel_batchbuffer *batch,
|
|
uint32_t size, uint32_t align);
|
|
|
|
uint32_t
|
|
intel_batchbuffer_subdata_offset(struct intel_batchbuffer *batch, void *ptr);
|
|
|
|
/* 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...
|
|
*/
|
|
#pragma GCC diagnostic ignored "-Winline"
|
|
static inline unsigned int
|
|
intel_batchbuffer_space(struct intel_batchbuffer *batch)
|
|
{
|
|
return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->buffer);
|
|
}
|
|
|
|
|
|
static inline void
|
|
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, uint32_t dword)
|
|
{
|
|
igt_assert(intel_batchbuffer_space(batch) >= 4);
|
|
*(uint32_t *) (batch->ptr) = dword;
|
|
batch->ptr += 4;
|
|
}
|
|
|
|
static inline void
|
|
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
|
|
unsigned int sz)
|
|
{
|
|
igt_assert(sz < BATCH_SZ - BATCH_RESERVED);
|
|
if (intel_batchbuffer_space(batch) < sz)
|
|
intel_batchbuffer_flush(batch);
|
|
}
|
|
|
|
/**
|
|
* BEGIN_BATCH:
|
|
* @n: number of DWORDS to emit
|
|
* @r: number of RELOCS to emit
|
|
*
|
|
* Prepares a batch to emit @n DWORDS, flushing it if there's not enough space
|
|
* available.
|
|
*
|
|
* This macro needs a pointer to an #intel_batchbuffer structure called batch in
|
|
* scope.
|
|
*/
|
|
#define BEGIN_BATCH(n, r) do { \
|
|
int __n = (n); \
|
|
igt_assert(batch->end == NULL); \
|
|
if (batch->gen >= 8) __n += r; \
|
|
__n *= 4; \
|
|
intel_batchbuffer_require_space(batch, __n); \
|
|
batch->end = batch->ptr + __n; \
|
|
} while (0)
|
|
|
|
/**
|
|
* OUT_BATCH:
|
|
* @d: DWORD to emit
|
|
*
|
|
* Emits @d into a batch.
|
|
*
|
|
* This macro needs a pointer to an #intel_batchbuffer structure called batch in
|
|
* scope.
|
|
*/
|
|
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(batch, d)
|
|
|
|
/**
|
|
* OUT_RELOC_FENCED:
|
|
* @buf: relocation target libdrm buffer object
|
|
* @read_domains: gem domain bits for the relocation
|
|
* @write_domain: gem domain bit for the relocation
|
|
* @delta: delta value to add to @buffer's gpu address
|
|
*
|
|
* Emits a fenced relocation into a batch.
|
|
*
|
|
* This macro needs a pointer to an #intel_batchbuffer structure called batch in
|
|
* scope.
|
|
*/
|
|
#define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \
|
|
igt_assert((delta) >= 0); \
|
|
intel_batchbuffer_emit_reloc(batch, buf, delta, \
|
|
read_domains, write_domain, 1); \
|
|
} while (0)
|
|
|
|
/**
|
|
* OUT_RELOC:
|
|
* @buf: relocation target libdrm buffer object
|
|
* @read_domains: gem domain bits for the relocation
|
|
* @write_domain: gem domain bit for the relocation
|
|
* @delta: delta value to add to @buffer's gpu address
|
|
*
|
|
* Emits a normal, unfenced relocation into a batch.
|
|
*
|
|
* This macro needs a pointer to an #intel_batchbuffer structure called batch in
|
|
* scope.
|
|
*/
|
|
#define OUT_RELOC(buf, read_domains, write_domain, delta) do { \
|
|
igt_assert((delta) >= 0); \
|
|
intel_batchbuffer_emit_reloc(batch, buf, delta, \
|
|
read_domains, write_domain, 0); \
|
|
} while (0)
|
|
|
|
/**
|
|
* ADVANCE_BATCH:
|
|
*
|
|
* Completes the batch command emission sequence started with #BEGIN_BATCH.
|
|
*
|
|
* This macro needs a pointer to an #intel_batchbuffer structure called batch in
|
|
* scope.
|
|
*/
|
|
#define ADVANCE_BATCH() do { \
|
|
igt_assert(batch->ptr == batch->end); \
|
|
batch->end = NULL; \
|
|
} while(0)
|
|
|
|
#define BLIT_COPY_BATCH_START(flags) do { \
|
|
BEGIN_BATCH(8, 2); \
|
|
OUT_BATCH(XY_SRC_COPY_BLT_CMD | \
|
|
XY_SRC_COPY_BLT_WRITE_ALPHA | \
|
|
XY_SRC_COPY_BLT_WRITE_RGB | \
|
|
(flags) | \
|
|
(6 + 2*(batch->gen >= 8))); \
|
|
} while(0)
|
|
|
|
#define COLOR_BLIT_COPY_BATCH_START(flags) do { \
|
|
BEGIN_BATCH(6, 1); \
|
|
OUT_BATCH(XY_COLOR_BLT_CMD_NOLEN | \
|
|
COLOR_BLT_WRITE_ALPHA | \
|
|
XY_COLOR_BLT_WRITE_RGB | \
|
|
(flags) | \
|
|
(4 + (batch->gen >= 8))); \
|
|
} while(0)
|
|
|
|
void
|
|
intel_blt_copy(struct intel_batchbuffer *batch,
|
|
drm_intel_bo *src_bo, int src_x1, int src_y1, int src_pitch,
|
|
drm_intel_bo *dst_bo, int dst_x1, int dst_y1, int dst_pitch,
|
|
int width, int height, int bpp);
|
|
void intel_copy_bo(struct intel_batchbuffer *batch,
|
|
drm_intel_bo *dst_bo, drm_intel_bo *src_bo,
|
|
long int size);
|
|
|
|
/*
|
|
* Yf/Ys tiling
|
|
*
|
|
* Tiling mode in the I915_TILING_... namespace for new tiling modes which are
|
|
* defined in the kernel. (They are not fenceable so the kernel does not need
|
|
* to know about them.)
|
|
*
|
|
* They are to be used the the blitting routines below.
|
|
*/
|
|
#define I915_TILING_Yf 3
|
|
#define I915_TILING_Ys 4
|
|
|
|
/**
|
|
* igt_buf:
|
|
* @bo: underlying libdrm buffer object
|
|
* @stride: stride of the buffer
|
|
* @tiling: tiling mode bits
|
|
* @bpp: bits per pixel, 8, 16 or 32.
|
|
* @data: pointer to the memory mapping of the buffer
|
|
* @size: size of the buffer object
|
|
*
|
|
* This is a i-g-t buffer object wrapper structure which augments the baseline
|
|
* libdrm buffer object with suitable data needed by the render copy and the
|
|
* fill functions.
|
|
*/
|
|
struct igt_buf {
|
|
drm_intel_bo *bo;
|
|
uint32_t stride;
|
|
uint32_t tiling;
|
|
uint32_t bpp;
|
|
uint32_t *data;
|
|
uint32_t size;
|
|
struct {
|
|
uint32_t offset;
|
|
uint32_t stride;
|
|
} aux;
|
|
/*< private >*/
|
|
unsigned num_tiles;
|
|
};
|
|
|
|
unsigned igt_buf_width(const struct igt_buf *buf);
|
|
unsigned igt_buf_height(const struct igt_buf *buf);
|
|
|
|
void igt_blitter_fast_copy(struct intel_batchbuffer *batch,
|
|
const struct igt_buf *src, unsigned src_delta,
|
|
unsigned src_x, unsigned src_y,
|
|
unsigned width, unsigned height,
|
|
int bpp,
|
|
const struct igt_buf *dst, unsigned dst_delta,
|
|
unsigned dst_x, unsigned dst_y);
|
|
|
|
void igt_blitter_fast_copy__raw(int fd,
|
|
/* src */
|
|
uint32_t src_handle,
|
|
unsigned int src_delta,
|
|
unsigned int src_stride,
|
|
unsigned int src_tiling,
|
|
unsigned int src_x, unsigned src_y,
|
|
|
|
/* size */
|
|
unsigned int width, unsigned int height,
|
|
|
|
/* bpp */
|
|
int bpp,
|
|
|
|
/* dst */
|
|
uint32_t dst_handle,
|
|
unsigned int dst_delta,
|
|
unsigned int dst_stride,
|
|
unsigned int dst_tiling,
|
|
unsigned int dst_x, unsigned dst_y);
|
|
|
|
/**
|
|
* igt_render_copyfunc_t:
|
|
* @batch: batchbuffer object
|
|
* @context: libdrm hardware context to use
|
|
* @src: source i-g-t buffer object
|
|
* @src_x: source pixel x-coordination
|
|
* @src_y: source pixel y-coordination
|
|
* @width: width of the copied rectangle
|
|
* @height: height of the copied rectangle
|
|
* @dst: destination i-g-t buffer object
|
|
* @dst_x: destination pixel x-coordination
|
|
* @dst_y: destination pixel y-coordination
|
|
*
|
|
* This is the type of the per-platform render copy functions. The
|
|
* platform-specific implementation can be obtained by calling
|
|
* igt_get_render_copyfunc().
|
|
*
|
|
* A render copy function will emit a batchbuffer to the kernel which executes
|
|
* the specified blit copy operation using the render engine. @context is
|
|
* optional and can be NULL.
|
|
*/
|
|
typedef void (*igt_render_copyfunc_t)(struct intel_batchbuffer *batch,
|
|
drm_intel_context *context,
|
|
const struct igt_buf *src, unsigned src_x, unsigned src_y,
|
|
unsigned width, unsigned height,
|
|
const struct igt_buf *dst, unsigned dst_x, unsigned dst_y);
|
|
|
|
igt_render_copyfunc_t igt_get_render_copyfunc(int devid);
|
|
|
|
/**
|
|
* igt_fillfunc_t:
|
|
* @batch: batchbuffer object
|
|
* @dst: destination i-g-t buffer object
|
|
* @x: destination pixel x-coordination
|
|
* @y: destination pixel y-coordination
|
|
* @width: width of the filled rectangle
|
|
* @height: height of the filled rectangle
|
|
* @color: fill color to use
|
|
*
|
|
* This is the type of the per-platform fill functions using media
|
|
* or gpgpu pipeline. The platform-specific implementation can be obtained
|
|
* by calling igt_get_media_fillfunc() or igt_get_gpgpu_fillfunc().
|
|
*
|
|
* A fill function will emit a batchbuffer to the kernel which executes
|
|
* the specified blit fill operation using the media/gpgpu engine.
|
|
*/
|
|
typedef void (*igt_fillfunc_t)(struct intel_batchbuffer *batch,
|
|
const struct igt_buf *dst,
|
|
unsigned x, unsigned y,
|
|
unsigned width, unsigned height,
|
|
uint8_t color);
|
|
|
|
igt_fillfunc_t igt_get_media_fillfunc(int devid);
|
|
igt_fillfunc_t igt_get_gpgpu_fillfunc(int devid);
|
|
|
|
typedef void (*igt_vme_func_t)(struct intel_batchbuffer *batch,
|
|
const struct igt_buf *src,
|
|
unsigned int width, unsigned int height,
|
|
const struct igt_buf *dst);
|
|
|
|
igt_vme_func_t igt_get_media_vme_func(int devid);
|
|
|
|
/**
|
|
* igt_media_spinfunc_t:
|
|
* @batch: batchbuffer object
|
|
* @dst: destination i-g-t buffer object
|
|
* @spins: number of loops to execute
|
|
*
|
|
* This is the type of the per-platform media spin functions. The
|
|
* platform-specific implementation can be obtained by calling
|
|
* igt_get_media_spinfunc().
|
|
*
|
|
* The media spin function emits a batchbuffer for the render engine with
|
|
* the media pipeline selected. The workload consists of a single thread
|
|
* which spins in a tight loop the requested number of times. Each spin
|
|
* increments a counter whose final 32-bit value is written to the
|
|
* destination buffer on completion. This utility provides a simple way
|
|
* to keep the render engine busy for a set time for various tests.
|
|
*/
|
|
typedef void (*igt_media_spinfunc_t)(struct intel_batchbuffer *batch,
|
|
const struct igt_buf *dst, uint32_t spins);
|
|
|
|
igt_media_spinfunc_t igt_get_media_spinfunc(int devid);
|
|
|
|
#endif
|