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