kgem.h revision 42542f5f
103b705cfSriastradh/*
203b705cfSriastradh * Copyright (c) 2011 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Authors:
2403b705cfSriastradh *    Chris Wilson <chris@chris-wilson.co.uk>
2503b705cfSriastradh *
2603b705cfSriastradh */
2703b705cfSriastradh
2803b705cfSriastradh#ifndef KGEM_H
2903b705cfSriastradh#define KGEM_H
3003b705cfSriastradh
3103b705cfSriastradh#include <stdint.h>
3203b705cfSriastradh#include <stdbool.h>
3303b705cfSriastradh#include <stdarg.h>
3403b705cfSriastradh
3503b705cfSriastradh#include <i915_drm.h>
3603b705cfSriastradh
3703b705cfSriastradh#include "compiler.h"
3803b705cfSriastradh
3903b705cfSriastradh#if HAS_DEBUG_FULL
4042542f5fSchristosvoid LogF(const char *f, ...);
4142542f5fSchristos#define DBG(x) LogF x
4242542f5fSchristos#define ERR(x) ErrorF x
4303b705cfSriastradh#else
4403b705cfSriastradh#define DBG(x)
4542542f5fSchristos#define ERR(x)
4603b705cfSriastradh#endif
4703b705cfSriastradh
4803b705cfSriastradhstruct kgem_bo {
4903b705cfSriastradh	struct kgem_request *rq;
5003b705cfSriastradh#define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3))
5103b705cfSriastradh#define RQ_RING(rq) ((uintptr_t)(rq) & 3)
5203b705cfSriastradh#define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT)
5342542f5fSchristos#define MAKE_REQUEST(rq, ring) ((struct kgem_request *)((uintptr_t)(rq) | (ring)))
5442542f5fSchristos
5503b705cfSriastradh	struct drm_i915_gem_exec_object2 *exec;
5603b705cfSriastradh
5703b705cfSriastradh	struct kgem_bo *proxy;
5803b705cfSriastradh
5903b705cfSriastradh	struct list list;
6003b705cfSriastradh	struct list request;
6103b705cfSriastradh	struct list vma;
6203b705cfSriastradh
6342542f5fSchristos	void *map__cpu;
6442542f5fSchristos	void *map__gtt;
6503b705cfSriastradh#define MAP(ptr) ((void*)((uintptr_t)(ptr) & ~3))
6603b705cfSriastradh
6703b705cfSriastradh	struct kgem_bo_binding {
6803b705cfSriastradh		struct kgem_bo_binding *next;
6903b705cfSriastradh		uint32_t format;
7003b705cfSriastradh		uint16_t offset;
7103b705cfSriastradh	} binding;
7203b705cfSriastradh
7342542f5fSchristos	uint64_t presumed_offset;
7403b705cfSriastradh	uint32_t unique_id;
7503b705cfSriastradh	uint32_t refcnt;
7603b705cfSriastradh	uint32_t handle;
7703b705cfSriastradh	uint32_t target_handle;
7803b705cfSriastradh	uint32_t delta;
7942542f5fSchristos	uint32_t active_scanout;
8003b705cfSriastradh	union {
8103b705cfSriastradh		struct {
8203b705cfSriastradh			uint32_t count:27;
8303b705cfSriastradh#define PAGE_SIZE 4096
8403b705cfSriastradh			uint32_t bucket:5;
8503b705cfSriastradh#define NUM_CACHE_BUCKETS 16
8603b705cfSriastradh#define MAX_CACHE_SIZE (1 << (NUM_CACHE_BUCKETS+12))
8703b705cfSriastradh		} pages;
8803b705cfSriastradh		uint32_t bytes;
8903b705cfSriastradh	} size;
9003b705cfSriastradh	uint32_t pitch : 18; /* max 128k */
9103b705cfSriastradh	uint32_t tiling : 2;
9203b705cfSriastradh	uint32_t reusable : 1;
9303b705cfSriastradh	uint32_t gpu_dirty : 1;
9403b705cfSriastradh	uint32_t gtt_dirty : 1;
9503b705cfSriastradh	uint32_t domain : 2;
9603b705cfSriastradh	uint32_t needs_flush : 1;
9703b705cfSriastradh	uint32_t snoop : 1;
9803b705cfSriastradh	uint32_t io : 1;
9903b705cfSriastradh	uint32_t flush : 1;
10003b705cfSriastradh	uint32_t scanout : 1;
10142542f5fSchristos	uint32_t prime : 1;
10203b705cfSriastradh	uint32_t purged : 1;
10303b705cfSriastradh};
10403b705cfSriastradh#define DOMAIN_NONE 0
10503b705cfSriastradh#define DOMAIN_CPU 1
10603b705cfSriastradh#define DOMAIN_GTT 2
10703b705cfSriastradh#define DOMAIN_GPU 3
10803b705cfSriastradh
10903b705cfSriastradhstruct kgem_request {
11003b705cfSriastradh	struct list list;
11103b705cfSriastradh	struct kgem_bo *bo;
11203b705cfSriastradh	struct list buffers;
11303b705cfSriastradh	int ring;
11403b705cfSriastradh};
11503b705cfSriastradh
11603b705cfSriastradhenum {
11703b705cfSriastradh	MAP_GTT = 0,
11803b705cfSriastradh	MAP_CPU,
11903b705cfSriastradh	NUM_MAP_TYPES,
12003b705cfSriastradh};
12103b705cfSriastradh
12203b705cfSriastradhstruct kgem {
12303b705cfSriastradh	int fd;
12442542f5fSchristos	unsigned wedged;
12503b705cfSriastradh	unsigned gen;
12603b705cfSriastradh
12703b705cfSriastradh	uint32_t unique_id;
12803b705cfSriastradh
12903b705cfSriastradh	enum kgem_mode {
13003b705cfSriastradh		/* order matches I915_EXEC_RING ordering */
13103b705cfSriastradh		KGEM_NONE = 0,
13203b705cfSriastradh		KGEM_RENDER,
13303b705cfSriastradh		KGEM_BSD,
13403b705cfSriastradh		KGEM_BLT,
13503b705cfSriastradh	} mode, ring;
13603b705cfSriastradh
13703b705cfSriastradh	struct list flushing;
13803b705cfSriastradh	struct list large;
13903b705cfSriastradh	struct list large_inactive;
14003b705cfSriastradh	struct list active[NUM_CACHE_BUCKETS][3];
14103b705cfSriastradh	struct list inactive[NUM_CACHE_BUCKETS];
14203b705cfSriastradh	struct list pinned_batches[2];
14303b705cfSriastradh	struct list snoop;
14403b705cfSriastradh	struct list scanout;
14503b705cfSriastradh	struct list batch_buffers, active_buffers;
14603b705cfSriastradh
14703b705cfSriastradh	struct list requests[2];
14803b705cfSriastradh	struct kgem_request *next_request;
14903b705cfSriastradh	struct kgem_request static_request;
15003b705cfSriastradh
15103b705cfSriastradh	struct {
15203b705cfSriastradh		struct list inactive[NUM_CACHE_BUCKETS];
15303b705cfSriastradh		int16_t count;
15403b705cfSriastradh	} vma[NUM_MAP_TYPES];
15503b705cfSriastradh
15603b705cfSriastradh	uint32_t batch_flags;
15703b705cfSriastradh	uint32_t batch_flags_base;
15803b705cfSriastradh#define I915_EXEC_SECURE (1<<9)
15903b705cfSriastradh#define LOCAL_EXEC_OBJECT_WRITE (1<<2)
16003b705cfSriastradh
16103b705cfSriastradh	uint16_t nbatch;
16203b705cfSriastradh	uint16_t surface;
16303b705cfSriastradh	uint16_t nexec;
16403b705cfSriastradh	uint16_t nreloc;
16503b705cfSriastradh	uint16_t nreloc__self;
16603b705cfSriastradh	uint16_t nfence;
16703b705cfSriastradh	uint16_t batch_size;
16803b705cfSriastradh
16903b705cfSriastradh	uint32_t flush:1;
17003b705cfSriastradh	uint32_t need_expire:1;
17103b705cfSriastradh	uint32_t need_purge:1;
17203b705cfSriastradh	uint32_t need_retire:1;
17303b705cfSriastradh	uint32_t need_throttle:1;
17442542f5fSchristos	uint32_t needs_semaphore:1;
17542542f5fSchristos	uint32_t needs_reservation:1;
17603b705cfSriastradh	uint32_t scanout_busy:1;
17703b705cfSriastradh	uint32_t busy:1;
17803b705cfSriastradh
17903b705cfSriastradh	uint32_t has_create2 :1;
18003b705cfSriastradh	uint32_t has_userptr :1;
18103b705cfSriastradh	uint32_t has_blt :1;
18203b705cfSriastradh	uint32_t has_relaxed_fencing :1;
18303b705cfSriastradh	uint32_t has_relaxed_delta :1;
18403b705cfSriastradh	uint32_t has_semaphores :1;
18503b705cfSriastradh	uint32_t has_secure_batches :1;
18603b705cfSriastradh	uint32_t has_pinned_batches :1;
18703b705cfSriastradh	uint32_t has_caching :1;
18803b705cfSriastradh	uint32_t has_llc :1;
18903b705cfSriastradh	uint32_t has_wt :1;
19003b705cfSriastradh	uint32_t has_no_reloc :1;
19103b705cfSriastradh	uint32_t has_handle_lut :1;
19203b705cfSriastradh
19303b705cfSriastradh	uint32_t can_blt_cpu :1;
19442542f5fSchristos	uint32_t can_render_y :1;
19503b705cfSriastradh
19603b705cfSriastradh	uint16_t fence_max;
19703b705cfSriastradh	uint16_t half_cpu_cache_pages;
19842542f5fSchristos	uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable, aperture_fenceable;
19942542f5fSchristos	uint32_t aperture, aperture_fenced, aperture_max_fence;
20003b705cfSriastradh	uint32_t max_upload_tile_size, max_copy_tile_size;
20103b705cfSriastradh	uint32_t max_gpu_size, max_cpu_size;
20203b705cfSriastradh	uint32_t large_object_size, max_object_size;
20303b705cfSriastradh	uint32_t buffer_size;
20403b705cfSriastradh
20503b705cfSriastradh	void (*context_switch)(struct kgem *kgem, int new_mode);
20603b705cfSriastradh	void (*retire)(struct kgem *kgem);
20703b705cfSriastradh	void (*expire)(struct kgem *kgem);
20803b705cfSriastradh
20903b705cfSriastradh	void (*memcpy_to_tiled_x)(const void *src, void *dst, int bpp,
21003b705cfSriastradh				  int32_t src_stride, int32_t dst_stride,
21103b705cfSriastradh				  int16_t src_x, int16_t src_y,
21203b705cfSriastradh				  int16_t dst_x, int16_t dst_y,
21303b705cfSriastradh				  uint16_t width, uint16_t height);
21403b705cfSriastradh	void (*memcpy_from_tiled_x)(const void *src, void *dst, int bpp,
21503b705cfSriastradh				    int32_t src_stride, int32_t dst_stride,
21603b705cfSriastradh				    int16_t src_x, int16_t src_y,
21703b705cfSriastradh				    int16_t dst_x, int16_t dst_y,
21803b705cfSriastradh				    uint16_t width, uint16_t height);
21903b705cfSriastradh
22003b705cfSriastradh	uint16_t reloc__self[256];
22103b705cfSriastradh	uint32_t batch[64*1024-8] page_aligned;
22203b705cfSriastradh	struct drm_i915_gem_exec_object2 exec[384] page_aligned;
22303b705cfSriastradh	struct drm_i915_gem_relocation_entry reloc[8192] page_aligned;
22403b705cfSriastradh
22503b705cfSriastradh#ifdef DEBUG_MEMORY
22603b705cfSriastradh	struct {
22703b705cfSriastradh		int bo_allocs;
22803b705cfSriastradh		size_t bo_bytes;
22903b705cfSriastradh	} debug_memory;
23003b705cfSriastradh#endif
23103b705cfSriastradh};
23203b705cfSriastradh
23303b705cfSriastradh#define KGEM_MAX_DEFERRED_VBO 16
23403b705cfSriastradh
23503b705cfSriastradh#define KGEM_BATCH_RESERVED 1
23603b705cfSriastradh#define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO)
23703b705cfSriastradh#define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO)
23803b705cfSriastradh
23903b705cfSriastradh#ifndef ARRAY_SIZE
24003b705cfSriastradh#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
24103b705cfSriastradh#endif
24203b705cfSriastradh
24303b705cfSriastradh#define KGEM_BATCH_SIZE(K) ((K)->batch_size-KGEM_BATCH_RESERVED)
24403b705cfSriastradh#define KGEM_EXEC_SIZE(K) (int)(ARRAY_SIZE((K)->exec)-KGEM_EXEC_RESERVED)
24503b705cfSriastradh#define KGEM_RELOC_SIZE(K) (int)(ARRAY_SIZE((K)->reloc)-KGEM_RELOC_RESERVED)
24603b705cfSriastradh
24703b705cfSriastradhvoid kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen);
24803b705cfSriastradhvoid kgem_reset(struct kgem *kgem);
24903b705cfSriastradh
25003b705cfSriastradhstruct kgem_bo *kgem_create_map(struct kgem *kgem,
25103b705cfSriastradh				void *ptr, uint32_t size,
25203b705cfSriastradh				bool read_only);
25303b705cfSriastradh
25403b705cfSriastradhstruct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name);
25503b705cfSriastradhstruct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size);
25603b705cfSriastradhint kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo);
25703b705cfSriastradh
25803b705cfSriastradhstruct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags);
25903b705cfSriastradhstruct kgem_bo *kgem_create_proxy(struct kgem *kgem,
26003b705cfSriastradh				  struct kgem_bo *target,
26103b705cfSriastradh				  int offset, int length);
26203b705cfSriastradh
26303b705cfSriastradhstruct kgem_bo *kgem_upload_source_image(struct kgem *kgem,
26403b705cfSriastradh					 const void *data,
26503b705cfSriastradh					 const BoxRec *box,
26603b705cfSriastradh					 int stride, int bpp);
26703b705cfSriastradhvoid kgem_proxy_bo_attach(struct kgem_bo *bo, struct kgem_bo **ptr);
26803b705cfSriastradh
26903b705cfSriastradhint kgem_choose_tiling(struct kgem *kgem,
27003b705cfSriastradh		       int tiling, int width, int height, int bpp);
27103b705cfSriastradhunsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth);
27203b705cfSriastradh#define KGEM_CAN_CREATE_GPU	0x1
27303b705cfSriastradh#define KGEM_CAN_CREATE_CPU	0x2
27403b705cfSriastradh#define KGEM_CAN_CREATE_LARGE	0x4
27503b705cfSriastradh#define KGEM_CAN_CREATE_GTT	0x8
27642542f5fSchristos#define KGEM_CAN_CREATE_TILED	0x10
27703b705cfSriastradh
27842542f5fSchristosbool kgem_check_surface_size(struct kgem *kgem,
27942542f5fSchristos			     uint32_t width,
28042542f5fSchristos			     uint32_t height,
28142542f5fSchristos			     uint32_t bpp,
28242542f5fSchristos			     uint32_t tiling,
28342542f5fSchristos			     uint32_t pitch,
28442542f5fSchristos			     uint32_t size);
28503b705cfSriastradh
28603b705cfSriastradhstruct kgem_bo *
28703b705cfSriastradhkgem_replace_bo(struct kgem *kgem,
28803b705cfSriastradh		struct kgem_bo *src,
28903b705cfSriastradh		uint32_t width,
29003b705cfSriastradh		uint32_t height,
29103b705cfSriastradh		uint32_t pitch,
29203b705cfSriastradh		uint32_t bpp);
29303b705cfSriastradhenum {
29403b705cfSriastradh	CREATE_EXACT = 0x1,
29503b705cfSriastradh	CREATE_INACTIVE = 0x2,
29603b705cfSriastradh	CREATE_CPU_MAP = 0x4,
29703b705cfSriastradh	CREATE_GTT_MAP = 0x8,
29803b705cfSriastradh	CREATE_SCANOUT = 0x10,
29903b705cfSriastradh	CREATE_PRIME = 0x20,
30003b705cfSriastradh	CREATE_TEMPORARY = 0x40,
30103b705cfSriastradh	CREATE_CACHED = 0x80,
30203b705cfSriastradh	CREATE_NO_RETIRE = 0x100,
30303b705cfSriastradh	CREATE_NO_THROTTLE = 0x200,
30403b705cfSriastradh};
30503b705cfSriastradhstruct kgem_bo *kgem_create_2d(struct kgem *kgem,
30603b705cfSriastradh			       int width,
30703b705cfSriastradh			       int height,
30803b705cfSriastradh			       int bpp,
30903b705cfSriastradh			       int tiling,
31003b705cfSriastradh			       uint32_t flags);
31103b705cfSriastradhstruct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem,
31203b705cfSriastradh				   int width,
31303b705cfSriastradh				   int height,
31403b705cfSriastradh				   int bpp,
31503b705cfSriastradh				   uint32_t flags);
31603b705cfSriastradh
31742542f5fSchristosbool kgem_bo_convert_to_gpu(struct kgem *kgem,
31842542f5fSchristos			    struct kgem_bo *bo,
31942542f5fSchristos			    unsigned flags);
32042542f5fSchristos
32103b705cfSriastradhuint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format);
32203b705cfSriastradhvoid kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset);
32303b705cfSriastradh
32403b705cfSriastradhbool kgem_retire(struct kgem *kgem);
32542542f5fSchristosvoid kgem_retire__buffers(struct kgem *kgem);
32642542f5fSchristos
32742542f5fSchristosstatic inline bool kgem_bo_discard_cache(struct kgem_bo *bo, bool force)
32842542f5fSchristos{
32942542f5fSchristos	if (bo == NULL || bo->proxy == NULL)
33042542f5fSchristos		return false;
33142542f5fSchristos
33242542f5fSchristos	if (force)
33342542f5fSchristos		return true;
33442542f5fSchristos
33542542f5fSchristos	if (bo->proxy->rq)
33642542f5fSchristos		return false;
33742542f5fSchristos
33842542f5fSchristos	return bo->snoop;
33942542f5fSchristos}
34003b705cfSriastradh
34103b705cfSriastradhbool __kgem_ring_is_idle(struct kgem *kgem, int ring);
34203b705cfSriastradhstatic inline bool kgem_ring_is_idle(struct kgem *kgem, int ring)
34303b705cfSriastradh{
34403b705cfSriastradh	ring = ring == KGEM_BLT;
34503b705cfSriastradh
34603b705cfSriastradh	if (list_is_empty(&kgem->requests[ring]))
34703b705cfSriastradh		return true;
34803b705cfSriastradh
34903b705cfSriastradh	return __kgem_ring_is_idle(kgem, ring);
35003b705cfSriastradh}
35103b705cfSriastradh
35203b705cfSriastradhstatic inline bool kgem_is_idle(struct kgem *kgem)
35303b705cfSriastradh{
35403b705cfSriastradh	if (!kgem->need_retire)
35503b705cfSriastradh		return true;
35603b705cfSriastradh
35703b705cfSriastradh	return kgem_ring_is_idle(kgem, kgem->ring);
35803b705cfSriastradh}
35903b705cfSriastradh
36003b705cfSriastradhstatic inline bool __kgem_ring_empty(struct kgem *kgem)
36103b705cfSriastradh{
36203b705cfSriastradh	return list_is_empty(&kgem->requests[kgem->ring == KGEM_BLT]);
36303b705cfSriastradh}
36403b705cfSriastradh
36503b705cfSriastradhvoid _kgem_submit(struct kgem *kgem);
36603b705cfSriastradhstatic inline void kgem_submit(struct kgem *kgem)
36703b705cfSriastradh{
36803b705cfSriastradh	if (kgem->nbatch)
36903b705cfSriastradh		_kgem_submit(kgem);
37003b705cfSriastradh}
37103b705cfSriastradh
37203b705cfSriastradhstatic inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo)
37303b705cfSriastradh{
37442542f5fSchristos	if (bo->exec == NULL)
37542542f5fSchristos		return;
37642542f5fSchristos
37742542f5fSchristos	assert(bo->refcnt);
37842542f5fSchristos	_kgem_submit(kgem);
37903b705cfSriastradh}
38003b705cfSriastradh
38103b705cfSriastradhvoid kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo);
38203b705cfSriastradh
38303b705cfSriastradhstatic inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo)
38403b705cfSriastradh{
38503b705cfSriastradh	assert(bo->refcnt);
38603b705cfSriastradh	bo->refcnt++;
38703b705cfSriastradh	return bo;
38803b705cfSriastradh}
38903b705cfSriastradh
39003b705cfSriastradhvoid _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo);
39103b705cfSriastradhstatic inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
39203b705cfSriastradh{
39303b705cfSriastradh	assert(bo->refcnt);
39403b705cfSriastradh	if (--bo->refcnt == 0)
39503b705cfSriastradh		_kgem_bo_destroy(kgem, bo);
39603b705cfSriastradh}
39703b705cfSriastradh
39803b705cfSriastradhvoid kgem_clear_dirty(struct kgem *kgem);
39903b705cfSriastradh
40003b705cfSriastradhstatic inline void kgem_set_mode(struct kgem *kgem,
40103b705cfSriastradh				 enum kgem_mode mode,
40203b705cfSriastradh				 struct kgem_bo *bo)
40303b705cfSriastradh{
40403b705cfSriastradh	assert(!kgem->wedged);
40503b705cfSriastradh
40603b705cfSriastradh#if DEBUG_FLUSH_BATCH
40703b705cfSriastradh	kgem_submit(kgem);
40803b705cfSriastradh#endif
40903b705cfSriastradh
41042542f5fSchristos	if (kgem->nreloc && bo->exec == NULL && kgem_ring_is_idle(kgem, kgem->ring)) {
41142542f5fSchristos		DBG(("%s: flushing before new bo\n", __FUNCTION__));
41203b705cfSriastradh		_kgem_submit(kgem);
41342542f5fSchristos	}
41403b705cfSriastradh
41503b705cfSriastradh	if (kgem->mode == mode)
41603b705cfSriastradh		return;
41703b705cfSriastradh
41803b705cfSriastradh	kgem->context_switch(kgem, mode);
41903b705cfSriastradh	kgem->mode = mode;
42003b705cfSriastradh}
42103b705cfSriastradh
42203b705cfSriastradhstatic inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode)
42303b705cfSriastradh{
42403b705cfSriastradh	assert(kgem->mode == KGEM_NONE);
42503b705cfSriastradh	assert(kgem->nbatch == 0);
42603b705cfSriastradh	assert(!kgem->wedged);
42703b705cfSriastradh	kgem->context_switch(kgem, mode);
42803b705cfSriastradh	kgem->mode = mode;
42903b705cfSriastradh}
43003b705cfSriastradh
43103b705cfSriastradhstatic inline bool kgem_check_batch(struct kgem *kgem, int num_dwords)
43203b705cfSriastradh{
43303b705cfSriastradh	assert(num_dwords > 0);
43403b705cfSriastradh	assert(kgem->nbatch < kgem->surface);
43503b705cfSriastradh	assert(kgem->surface <= kgem->batch_size);
43603b705cfSriastradh	return likely(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED <= kgem->surface);
43703b705cfSriastradh}
43803b705cfSriastradh
43903b705cfSriastradhstatic inline bool kgem_check_reloc(struct kgem *kgem, int n)
44003b705cfSriastradh{
44103b705cfSriastradh	assert(kgem->nreloc <= KGEM_RELOC_SIZE(kgem));
44203b705cfSriastradh	return likely(kgem->nreloc + n <= KGEM_RELOC_SIZE(kgem));
44303b705cfSriastradh}
44403b705cfSriastradh
44503b705cfSriastradhstatic inline bool kgem_check_exec(struct kgem *kgem, int n)
44603b705cfSriastradh{
44703b705cfSriastradh	assert(kgem->nexec <= KGEM_EXEC_SIZE(kgem));
44803b705cfSriastradh	return likely(kgem->nexec + n <= KGEM_EXEC_SIZE(kgem));
44903b705cfSriastradh}
45003b705cfSriastradh
45103b705cfSriastradhstatic inline bool kgem_check_reloc_and_exec(struct kgem *kgem, int n)
45203b705cfSriastradh{
45303b705cfSriastradh	return kgem_check_reloc(kgem, n) && kgem_check_exec(kgem, n);
45403b705cfSriastradh}
45503b705cfSriastradh
45603b705cfSriastradhstatic inline bool kgem_check_batch_with_surfaces(struct kgem *kgem,
45703b705cfSriastradh						  int num_dwords,
45803b705cfSriastradh						  int num_surfaces)
45903b705cfSriastradh{
46003b705cfSriastradh	return (int)(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED) <= (int)(kgem->surface - num_surfaces*8) &&
46103b705cfSriastradh		kgem_check_reloc(kgem, num_surfaces) &&
46203b705cfSriastradh		kgem_check_exec(kgem, num_surfaces);
46303b705cfSriastradh}
46403b705cfSriastradh
46503b705cfSriastradhstatic inline uint32_t *kgem_get_batch(struct kgem *kgem)
46603b705cfSriastradh{
46703b705cfSriastradh	if (kgem->nreloc) {
46803b705cfSriastradh		unsigned mode = kgem->mode;
46903b705cfSriastradh		_kgem_submit(kgem);
47003b705cfSriastradh		_kgem_set_mode(kgem, mode);
47103b705cfSriastradh	}
47203b705cfSriastradh
47303b705cfSriastradh	return kgem->batch + kgem->nbatch;
47403b705cfSriastradh}
47503b705cfSriastradh
47603b705cfSriastradhbool kgem_check_bo(struct kgem *kgem, ...) __attribute__((sentinel(0)));
47703b705cfSriastradhbool kgem_check_bo_fenced(struct kgem *kgem, struct kgem_bo *bo);
47803b705cfSriastradhbool kgem_check_many_bo_fenced(struct kgem *kgem, ...) __attribute__((sentinel(0)));
47903b705cfSriastradh
48003b705cfSriastradh#define KGEM_RELOC_FENCED 0x8000
48103b705cfSriastradhuint32_t kgem_add_reloc(struct kgem *kgem,
48203b705cfSriastradh			uint32_t pos,
48303b705cfSriastradh			struct kgem_bo *bo,
48403b705cfSriastradh			uint32_t read_write_domains,
48503b705cfSriastradh			uint32_t delta);
48642542f5fSchristosuint64_t kgem_add_reloc64(struct kgem *kgem,
48742542f5fSchristos			  uint32_t pos,
48842542f5fSchristos			  struct kgem_bo *bo,
48942542f5fSchristos			  uint32_t read_write_domains,
49042542f5fSchristos			  uint64_t delta);
49103b705cfSriastradh
49203b705cfSriastradhvoid *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo);
49303b705cfSriastradhvoid *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo);
49403b705cfSriastradhvoid *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo);
49503b705cfSriastradhvoid kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo);
49603b705cfSriastradhvoid *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo);
49703b705cfSriastradhvoid *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo);
49803b705cfSriastradhvoid kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo);
49903b705cfSriastradhvoid kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write);
50003b705cfSriastradhuint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo);
50103b705cfSriastradh
50203b705cfSriastradhbool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo,
50303b705cfSriastradh		   const void *data, int length);
50403b705cfSriastradh
50503b705cfSriastradhint kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo);
50642542f5fSchristosvoid kgem_get_tile_size(struct kgem *kgem, int tiling, int pitch,
50703b705cfSriastradh			int *tile_width, int *tile_height, int *tile_size);
50803b705cfSriastradh
50903b705cfSriastradhstatic inline int __kgem_buffer_size(struct kgem_bo *bo)
51003b705cfSriastradh{
51103b705cfSriastradh	assert(bo->proxy != NULL);
51203b705cfSriastradh	return bo->size.bytes;
51303b705cfSriastradh}
51403b705cfSriastradh
51503b705cfSriastradhstatic inline int __kgem_bo_size(struct kgem_bo *bo)
51603b705cfSriastradh{
51703b705cfSriastradh	assert(bo->proxy == NULL);
51803b705cfSriastradh	return PAGE_SIZE * bo->size.pages.count;
51903b705cfSriastradh}
52003b705cfSriastradh
52142542f5fSchristosstatic inline int __kgem_bo_num_pages(struct kgem_bo *bo)
52242542f5fSchristos{
52342542f5fSchristos	assert(bo->proxy == NULL);
52442542f5fSchristos	return bo->size.pages.count;
52542542f5fSchristos}
52642542f5fSchristos
52703b705cfSriastradhstatic inline int kgem_bo_size(struct kgem_bo *bo)
52803b705cfSriastradh{
52903b705cfSriastradh	if (bo->proxy)
53003b705cfSriastradh		return __kgem_buffer_size(bo);
53103b705cfSriastradh	else
53203b705cfSriastradh		return __kgem_bo_size(bo);
53303b705cfSriastradh}
53403b705cfSriastradh
53503b705cfSriastradhstatic inline bool kgem_bo_blt_pitch_is_ok(struct kgem *kgem,
53603b705cfSriastradh					   struct kgem_bo *bo)
53703b705cfSriastradh{
53803b705cfSriastradh	int pitch = bo->pitch;
53903b705cfSriastradh	if (kgem->gen >= 040 && bo->tiling)
54003b705cfSriastradh		pitch /= 4;
54103b705cfSriastradh	if (pitch > MAXSHORT) {
54203b705cfSriastradh		DBG(("%s: can not blt to handle=%d, adjusted pitch=%d\n",
54303b705cfSriastradh		     __FUNCTION__, bo->handle, pitch));
54403b705cfSriastradh		return false;
54503b705cfSriastradh	}
54603b705cfSriastradh
54703b705cfSriastradh	return true;
54803b705cfSriastradh}
54903b705cfSriastradh
55003b705cfSriastradhstatic inline bool kgem_bo_can_blt(struct kgem *kgem,
55103b705cfSriastradh				   struct kgem_bo *bo)
55203b705cfSriastradh{
55342542f5fSchristos	assert(bo->refcnt);
55442542f5fSchristos
55503b705cfSriastradh	if (bo->tiling == I915_TILING_Y) {
55603b705cfSriastradh		DBG(("%s: can not blt to handle=%d, tiling=Y\n",
55703b705cfSriastradh		     __FUNCTION__, bo->handle));
55803b705cfSriastradh		return false;
55903b705cfSriastradh	}
56003b705cfSriastradh
56103b705cfSriastradh	return kgem_bo_blt_pitch_is_ok(kgem, bo);
56203b705cfSriastradh}
56303b705cfSriastradh
56403b705cfSriastradhstatic inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
56503b705cfSriastradh{
56603b705cfSriastradh	assert(bo->refcnt);
56703b705cfSriastradh	while (bo->proxy)
56803b705cfSriastradh		bo = bo->proxy;
56903b705cfSriastradh	return bo->snoop;
57003b705cfSriastradh}
57103b705cfSriastradh
57203b705cfSriastradhvoid kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo);
57342542f5fSchristosvoid kgem_bo_pair_undo(struct kgem *kgem, struct kgem_bo *a, struct kgem_bo *b);
57403b705cfSriastradh
57503b705cfSriastradhbool __kgem_busy(struct kgem *kgem, int handle);
57603b705cfSriastradh
57742542f5fSchristosstatic inline void kgem_bo_mark_busy(struct kgem *kgem, struct kgem_bo *bo, int ring)
57803b705cfSriastradh{
57942542f5fSchristos	assert(bo->refcnt);
58042542f5fSchristos	bo->needs_flush = true;
58142542f5fSchristos	if (bo->rq) {
58242542f5fSchristos		bo->rq = MAKE_REQUEST(RQ(bo->rq), ring);
58342542f5fSchristos	} else {
58442542f5fSchristos		bo->rq = MAKE_REQUEST(kgem, ring);
58542542f5fSchristos		list_add(&bo->request, &kgem->flushing);
58642542f5fSchristos		kgem->need_retire = true;
58742542f5fSchristos	}
58803b705cfSriastradh}
58903b705cfSriastradh
59003b705cfSriastradhinline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
59103b705cfSriastradh{
59242542f5fSchristos	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
59303b705cfSriastradh	bo->rq = NULL;
59403b705cfSriastradh	list_del(&bo->request);
59503b705cfSriastradh
59603b705cfSriastradh	bo->domain = DOMAIN_NONE;
59703b705cfSriastradh	bo->needs_flush = false;
59803b705cfSriastradh	bo->gtt_dirty = false;
59903b705cfSriastradh}
60003b705cfSriastradh
60103b705cfSriastradhstatic inline bool kgem_bo_is_busy(struct kgem_bo *bo)
60203b705cfSriastradh{
60303b705cfSriastradh	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
60403b705cfSriastradh	     bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL));
60503b705cfSriastradh	assert(bo->refcnt);
60603b705cfSriastradh	return bo->rq;
60703b705cfSriastradh}
60803b705cfSriastradh
60903b705cfSriastradhstatic inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
61003b705cfSriastradh{
61103b705cfSriastradh	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
61203b705cfSriastradh	     bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL));
61303b705cfSriastradh	assert(bo->refcnt);
61403b705cfSriastradh
61503b705cfSriastradh	if (bo->exec)
61603b705cfSriastradh		return true;
61703b705cfSriastradh
61803b705cfSriastradh	if (bo->rq && !__kgem_busy(kgem, bo->handle))
61903b705cfSriastradh		__kgem_bo_clear_busy(bo);
62003b705cfSriastradh
62103b705cfSriastradh	return kgem_bo_is_busy(bo);
62203b705cfSriastradh}
62303b705cfSriastradh
62403b705cfSriastradhstatic inline bool kgem_bo_is_render(struct kgem_bo *bo)
62503b705cfSriastradh{
62603b705cfSriastradh	DBG(("%s: handle=%d, rq? %d [%d]\n", __FUNCTION__,
62742542f5fSchristos	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
62803b705cfSriastradh	assert(bo->refcnt);
62903b705cfSriastradh	return bo->rq && RQ_RING(bo->rq) == I915_EXEC_RENDER;
63003b705cfSriastradh}
63103b705cfSriastradh
63203b705cfSriastradhstatic inline void kgem_bo_mark_unreusable(struct kgem_bo *bo)
63303b705cfSriastradh{
63442542f5fSchristos	assert(bo->refcnt);
63503b705cfSriastradh	while (bo->proxy) {
63603b705cfSriastradh		bo->flush = true;
63703b705cfSriastradh		bo = bo->proxy;
63842542f5fSchristos		assert(bo->refcnt);
63903b705cfSriastradh	}
64003b705cfSriastradh	bo->flush = true;
64103b705cfSriastradh	bo->reusable = false;
64203b705cfSriastradh}
64303b705cfSriastradh
64403b705cfSriastradhstatic inline bool kgem_bo_is_dirty(struct kgem_bo *bo)
64503b705cfSriastradh{
64603b705cfSriastradh	if (bo == NULL)
64703b705cfSriastradh		return false;
64803b705cfSriastradh
64903b705cfSriastradh	assert(bo->refcnt);
65003b705cfSriastradh	return bo->gpu_dirty;
65103b705cfSriastradh}
65203b705cfSriastradh
65303b705cfSriastradhstatic inline void kgem_bo_unclean(struct kgem *kgem, struct kgem_bo *bo)
65403b705cfSriastradh{
65503b705cfSriastradh	/* The bo is outside of our control, so presume it is written to */
65603b705cfSriastradh	bo->needs_flush = true;
65703b705cfSriastradh	if (bo->rq == NULL)
65803b705cfSriastradh		bo->rq = (void *)kgem;
65903b705cfSriastradh
66003b705cfSriastradh	if (bo->domain != DOMAIN_GPU)
66103b705cfSriastradh		bo->domain = DOMAIN_NONE;
66203b705cfSriastradh}
66303b705cfSriastradh
66403b705cfSriastradhstatic inline void __kgem_bo_mark_dirty(struct kgem_bo *bo)
66503b705cfSriastradh{
66603b705cfSriastradh	DBG(("%s: handle=%d (proxy? %d)\n", __FUNCTION__,
66703b705cfSriastradh	     bo->handle, bo->proxy != NULL));
66803b705cfSriastradh
66942542f5fSchristos	assert(bo->refcnt);
67042542f5fSchristos	assert(bo->exec);
67142542f5fSchristos	assert(bo->rq);
67242542f5fSchristos
67303b705cfSriastradh	bo->exec->flags |= LOCAL_EXEC_OBJECT_WRITE;
67403b705cfSriastradh	bo->needs_flush = bo->gpu_dirty = true;
67503b705cfSriastradh	list_move(&bo->request, &RQ(bo->rq)->buffers);
67603b705cfSriastradh}
67703b705cfSriastradh
67803b705cfSriastradhstatic inline void kgem_bo_mark_dirty(struct kgem_bo *bo)
67903b705cfSriastradh{
68003b705cfSriastradh	assert(bo->refcnt);
68103b705cfSriastradh	do {
68203b705cfSriastradh		assert(bo->exec);
68303b705cfSriastradh		assert(bo->rq);
68403b705cfSriastradh
68503b705cfSriastradh		if (bo->gpu_dirty)
68603b705cfSriastradh			return;
68703b705cfSriastradh
68803b705cfSriastradh		__kgem_bo_mark_dirty(bo);
68903b705cfSriastradh	} while ((bo = bo->proxy));
69003b705cfSriastradh}
69103b705cfSriastradh
69242542f5fSchristosstatic inline bool kgem_bo_mapped(struct kgem *kgem, struct kgem_bo *bo)
69342542f5fSchristos{
69442542f5fSchristos	DBG(("%s: handle=%d, map=%p:%p, tiling=%d, domain=%d\n",
69542542f5fSchristos	     __FUNCTION__, bo->handle, bo->map__gtt, bo->map__cpu, bo->tiling, bo->domain));
69642542f5fSchristos	assert(bo->proxy == NULL);
69742542f5fSchristos
69842542f5fSchristos	if (bo->tiling == I915_TILING_NONE && (bo->domain == DOMAIN_CPU || kgem->has_llc))
69942542f5fSchristos		return bo->map__cpu != NULL;
70042542f5fSchristos
70142542f5fSchristos	return bo->map__gtt != NULL;
70242542f5fSchristos}
70342542f5fSchristos
70442542f5fSchristosstatic inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo)
70542542f5fSchristos{
70642542f5fSchristos	DBG(("%s: handle=%d, map=%p:%p, tiling=%d, domain=%d, offset=%ld\n",
70742542f5fSchristos	     __FUNCTION__, bo->handle, bo->map__gtt, bo->map__cpu, bo->tiling, bo->domain, (long)bo->presumed_offset));
70842542f5fSchristos
70942542f5fSchristos	if (!bo->tiling && (kgem->has_llc || bo->domain == DOMAIN_CPU))
71042542f5fSchristos		return true;
71142542f5fSchristos
71242542f5fSchristos	assert(bo->proxy == NULL);
71342542f5fSchristos
71442542f5fSchristos	if (bo->map__gtt != NULL)
71542542f5fSchristos		return true;
71642542f5fSchristos
71742542f5fSchristos	if (kgem->gen == 021 && bo->tiling == I915_TILING_Y)
71842542f5fSchristos		return false;
71942542f5fSchristos
72042542f5fSchristos	return __kgem_bo_num_pages(bo) <= kgem->aperture_mappable / 4;
72142542f5fSchristos}
72242542f5fSchristos
72342542f5fSchristosstatic inline bool kgem_bo_can_map__cpu(struct kgem *kgem,
72442542f5fSchristos					struct kgem_bo *bo,
72542542f5fSchristos					bool write)
72642542f5fSchristos{
72742542f5fSchristos	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
72842542f5fSchristos	assert(bo->refcnt);
72942542f5fSchristos
73042542f5fSchristos	if (bo->purged || (bo->scanout && write)) {
73142542f5fSchristos		DBG(("%s: no, writing to scanout? %d, or is stolen [inaccessible via CPU]? %d\n",
73242542f5fSchristos		     __FUNCTION__, bo->scanout && write, bo->purged));
73342542f5fSchristos		return false;
73442542f5fSchristos	}
73542542f5fSchristos
73642542f5fSchristos	if (kgem->has_llc) {
73742542f5fSchristos		DBG(("%s: yes, has LLC and target is in LLC\n", __FUNCTION__));
73842542f5fSchristos		return true;
73942542f5fSchristos	}
74042542f5fSchristos
74142542f5fSchristos	DBG(("%s: non-LLC - CPU domain? %d, clean? %d\n",
74242542f5fSchristos	     __FUNCTION__, bo->domain == DOMAIN_CPU, !write || bo->exec == NULL));
74342542f5fSchristos	if (bo->domain != DOMAIN_CPU)
74442542f5fSchristos		return false;
74542542f5fSchristos
74642542f5fSchristos	return !write || bo->exec == NULL;
74742542f5fSchristos}
74842542f5fSchristos
74903b705cfSriastradh#define KGEM_BUFFER_WRITE	0x1
75003b705cfSriastradh#define KGEM_BUFFER_INPLACE	0x2
75103b705cfSriastradh#define KGEM_BUFFER_LAST	0x4
75203b705cfSriastradh
75303b705cfSriastradh#define KGEM_BUFFER_WRITE_INPLACE (KGEM_BUFFER_WRITE | KGEM_BUFFER_INPLACE)
75403b705cfSriastradh
75503b705cfSriastradhstruct kgem_bo *kgem_create_buffer(struct kgem *kgem,
75603b705cfSriastradh				   uint32_t size, uint32_t flags,
75703b705cfSriastradh				   void **ret);
75803b705cfSriastradhstruct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem,
75903b705cfSriastradh				      int width, int height, int bpp,
76003b705cfSriastradh				      uint32_t flags,
76103b705cfSriastradh				      void **ret);
76203b705cfSriastradhbool kgem_buffer_is_inplace(struct kgem_bo *bo);
76303b705cfSriastradhvoid kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo);
76403b705cfSriastradh
76542542f5fSchristosint kgem_is_wedged(struct kgem *kgem);
76603b705cfSriastradhvoid kgem_throttle(struct kgem *kgem);
76703b705cfSriastradh#define MAX_INACTIVE_TIME 10
76803b705cfSriastradhbool kgem_expire_cache(struct kgem *kgem);
76942542f5fSchristosbool kgem_cleanup_cache(struct kgem *kgem);
77003b705cfSriastradh
77103b705cfSriastradhvoid kgem_clean_scanout_cache(struct kgem *kgem);
77203b705cfSriastradhvoid kgem_clean_large_cache(struct kgem *kgem);
77303b705cfSriastradh
77403b705cfSriastradh#if HAS_DEBUG_FULL
77503b705cfSriastradhvoid __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch);
77603b705cfSriastradh#else
77703b705cfSriastradhstatic inline void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch)
77803b705cfSriastradh{
77903b705cfSriastradh	(void)kgem;
78003b705cfSriastradh	(void)nbatch;
78103b705cfSriastradh}
78203b705cfSriastradh#endif
78303b705cfSriastradh
78403b705cfSriastradhstatic inline void
78503b705cfSriastradhmemcpy_to_tiled_x(struct kgem *kgem,
78603b705cfSriastradh		  const void *src, void *dst, int bpp,
78703b705cfSriastradh		  int32_t src_stride, int32_t dst_stride,
78803b705cfSriastradh		  int16_t src_x, int16_t src_y,
78903b705cfSriastradh		  int16_t dst_x, int16_t dst_y,
79003b705cfSriastradh		  uint16_t width, uint16_t height)
79103b705cfSriastradh{
79242542f5fSchristos	assert(kgem->memcpy_to_tiled_x);
79342542f5fSchristos	assert(src_x >= 0 && src_y >= 0);
79442542f5fSchristos	assert(dst_x >= 0 && dst_y >= 0);
79542542f5fSchristos	assert(8*src_stride >= (src_x+width) * bpp);
79642542f5fSchristos	assert(8*dst_stride >= (dst_x+width) * bpp);
79703b705cfSriastradh	return kgem->memcpy_to_tiled_x(src, dst, bpp,
79803b705cfSriastradh				       src_stride, dst_stride,
79903b705cfSriastradh				       src_x, src_y,
80003b705cfSriastradh				       dst_x, dst_y,
80103b705cfSriastradh				       width, height);
80203b705cfSriastradh}
80303b705cfSriastradh
80403b705cfSriastradhstatic inline void
80503b705cfSriastradhmemcpy_from_tiled_x(struct kgem *kgem,
80603b705cfSriastradh		    const void *src, void *dst, int bpp,
80703b705cfSriastradh		    int32_t src_stride, int32_t dst_stride,
80803b705cfSriastradh		    int16_t src_x, int16_t src_y,
80903b705cfSriastradh		    int16_t dst_x, int16_t dst_y,
81003b705cfSriastradh		    uint16_t width, uint16_t height)
81103b705cfSriastradh{
81242542f5fSchristos	assert(kgem->memcpy_from_tiled_x);
81342542f5fSchristos	assert(src_x >= 0 && src_y >= 0);
81442542f5fSchristos	assert(dst_x >= 0 && dst_y >= 0);
81542542f5fSchristos	assert(8*src_stride >= (src_x+width) * bpp);
81642542f5fSchristos	assert(8*dst_stride >= (dst_x+width) * bpp);
81703b705cfSriastradh	return kgem->memcpy_from_tiled_x(src, dst, bpp,
81803b705cfSriastradh					 src_stride, dst_stride,
81903b705cfSriastradh					 src_x, src_y,
82003b705cfSriastradh					 dst_x, dst_y,
82103b705cfSriastradh					 width, height);
82203b705cfSriastradh}
82303b705cfSriastradh
82403b705cfSriastradhvoid choose_memcpy_tiled_x(struct kgem *kgem, int swizzling);
82503b705cfSriastradh
82603b705cfSriastradh#endif /* KGEM_H */
827