kgem.h revision 03b705cf
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 4003b705cfSriastradh#define DBG(x) ErrorF x 4103b705cfSriastradh#else 4203b705cfSriastradh#define DBG(x) 4303b705cfSriastradh#endif 4403b705cfSriastradh 4503b705cfSriastradhstruct kgem_bo { 4603b705cfSriastradh struct kgem_request *rq; 4703b705cfSriastradh#define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3)) 4803b705cfSriastradh#define RQ_RING(rq) ((uintptr_t)(rq) & 3) 4903b705cfSriastradh#define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT) 5003b705cfSriastradh struct drm_i915_gem_exec_object2 *exec; 5103b705cfSriastradh 5203b705cfSriastradh struct kgem_bo *proxy; 5303b705cfSriastradh 5403b705cfSriastradh struct list list; 5503b705cfSriastradh struct list request; 5603b705cfSriastradh struct list vma; 5703b705cfSriastradh 5803b705cfSriastradh void *map; 5903b705cfSriastradh#define IS_CPU_MAP(ptr) ((uintptr_t)(ptr) & 1) 6003b705cfSriastradh#define IS_GTT_MAP(ptr) (ptr && ((uintptr_t)(ptr) & 1) == 0) 6103b705cfSriastradh#define MAP(ptr) ((void*)((uintptr_t)(ptr) & ~3)) 6203b705cfSriastradh 6303b705cfSriastradh struct kgem_bo_binding { 6403b705cfSriastradh struct kgem_bo_binding *next; 6503b705cfSriastradh uint32_t format; 6603b705cfSriastradh uint16_t offset; 6703b705cfSriastradh } binding; 6803b705cfSriastradh 6903b705cfSriastradh uint32_t unique_id; 7003b705cfSriastradh uint32_t refcnt; 7103b705cfSriastradh uint32_t handle; 7203b705cfSriastradh uint32_t target_handle; 7303b705cfSriastradh uint32_t presumed_offset; 7403b705cfSriastradh uint32_t delta; 7503b705cfSriastradh union { 7603b705cfSriastradh struct { 7703b705cfSriastradh uint32_t count:27; 7803b705cfSriastradh#define PAGE_SIZE 4096 7903b705cfSriastradh uint32_t bucket:5; 8003b705cfSriastradh#define NUM_CACHE_BUCKETS 16 8103b705cfSriastradh#define MAX_CACHE_SIZE (1 << (NUM_CACHE_BUCKETS+12)) 8203b705cfSriastradh } pages; 8303b705cfSriastradh uint32_t bytes; 8403b705cfSriastradh } size; 8503b705cfSriastradh uint32_t pitch : 18; /* max 128k */ 8603b705cfSriastradh uint32_t tiling : 2; 8703b705cfSriastradh uint32_t reusable : 1; 8803b705cfSriastradh uint32_t gpu_dirty : 1; 8903b705cfSriastradh uint32_t gtt_dirty : 1; 9003b705cfSriastradh uint32_t domain : 2; 9103b705cfSriastradh uint32_t needs_flush : 1; 9203b705cfSriastradh uint32_t snoop : 1; 9303b705cfSriastradh uint32_t io : 1; 9403b705cfSriastradh uint32_t flush : 1; 9503b705cfSriastradh uint32_t scanout : 1; 9603b705cfSriastradh uint32_t purged : 1; 9703b705cfSriastradh}; 9803b705cfSriastradh#define DOMAIN_NONE 0 9903b705cfSriastradh#define DOMAIN_CPU 1 10003b705cfSriastradh#define DOMAIN_GTT 2 10103b705cfSriastradh#define DOMAIN_GPU 3 10203b705cfSriastradh 10303b705cfSriastradhstruct kgem_request { 10403b705cfSriastradh struct list list; 10503b705cfSriastradh struct kgem_bo *bo; 10603b705cfSriastradh struct list buffers; 10703b705cfSriastradh int ring; 10803b705cfSriastradh}; 10903b705cfSriastradh 11003b705cfSriastradhenum { 11103b705cfSriastradh MAP_GTT = 0, 11203b705cfSriastradh MAP_CPU, 11303b705cfSriastradh NUM_MAP_TYPES, 11403b705cfSriastradh}; 11503b705cfSriastradh 11603b705cfSriastradhstruct kgem { 11703b705cfSriastradh int fd; 11803b705cfSriastradh int wedged; 11903b705cfSriastradh unsigned gen; 12003b705cfSriastradh 12103b705cfSriastradh uint32_t unique_id; 12203b705cfSriastradh 12303b705cfSriastradh enum kgem_mode { 12403b705cfSriastradh /* order matches I915_EXEC_RING ordering */ 12503b705cfSriastradh KGEM_NONE = 0, 12603b705cfSriastradh KGEM_RENDER, 12703b705cfSriastradh KGEM_BSD, 12803b705cfSriastradh KGEM_BLT, 12903b705cfSriastradh } mode, ring; 13003b705cfSriastradh 13103b705cfSriastradh struct list flushing; 13203b705cfSriastradh struct list large; 13303b705cfSriastradh struct list large_inactive; 13403b705cfSriastradh struct list active[NUM_CACHE_BUCKETS][3]; 13503b705cfSriastradh struct list inactive[NUM_CACHE_BUCKETS]; 13603b705cfSriastradh struct list pinned_batches[2]; 13703b705cfSriastradh struct list snoop; 13803b705cfSriastradh struct list scanout; 13903b705cfSriastradh struct list batch_buffers, active_buffers; 14003b705cfSriastradh 14103b705cfSriastradh struct list requests[2]; 14203b705cfSriastradh struct kgem_request *next_request; 14303b705cfSriastradh struct kgem_request static_request; 14403b705cfSriastradh 14503b705cfSriastradh struct { 14603b705cfSriastradh struct list inactive[NUM_CACHE_BUCKETS]; 14703b705cfSriastradh int16_t count; 14803b705cfSriastradh } vma[NUM_MAP_TYPES]; 14903b705cfSriastradh 15003b705cfSriastradh uint32_t batch_flags; 15103b705cfSriastradh uint32_t batch_flags_base; 15203b705cfSriastradh#define I915_EXEC_SECURE (1<<9) 15303b705cfSriastradh#define LOCAL_EXEC_OBJECT_WRITE (1<<2) 15403b705cfSriastradh 15503b705cfSriastradh uint16_t nbatch; 15603b705cfSriastradh uint16_t surface; 15703b705cfSriastradh uint16_t nexec; 15803b705cfSriastradh uint16_t nreloc; 15903b705cfSriastradh uint16_t nreloc__self; 16003b705cfSriastradh uint16_t nfence; 16103b705cfSriastradh uint16_t batch_size; 16203b705cfSriastradh uint16_t min_alignment; 16303b705cfSriastradh 16403b705cfSriastradh uint32_t flush:1; 16503b705cfSriastradh uint32_t need_expire:1; 16603b705cfSriastradh uint32_t need_purge:1; 16703b705cfSriastradh uint32_t need_retire:1; 16803b705cfSriastradh uint32_t need_throttle:1; 16903b705cfSriastradh uint32_t scanout_busy:1; 17003b705cfSriastradh uint32_t busy:1; 17103b705cfSriastradh 17203b705cfSriastradh uint32_t has_create2 :1; 17303b705cfSriastradh uint32_t has_userptr :1; 17403b705cfSriastradh uint32_t has_blt :1; 17503b705cfSriastradh uint32_t has_relaxed_fencing :1; 17603b705cfSriastradh uint32_t has_relaxed_delta :1; 17703b705cfSriastradh uint32_t has_semaphores :1; 17803b705cfSriastradh uint32_t has_secure_batches :1; 17903b705cfSriastradh uint32_t has_pinned_batches :1; 18003b705cfSriastradh uint32_t has_caching :1; 18103b705cfSriastradh uint32_t has_llc :1; 18203b705cfSriastradh uint32_t has_wt :1; 18303b705cfSriastradh uint32_t has_no_reloc :1; 18403b705cfSriastradh uint32_t has_handle_lut :1; 18503b705cfSriastradh 18603b705cfSriastradh uint32_t can_blt_cpu :1; 18703b705cfSriastradh 18803b705cfSriastradh uint16_t fence_max; 18903b705cfSriastradh uint16_t half_cpu_cache_pages; 19003b705cfSriastradh uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable; 19103b705cfSriastradh uint32_t aperture, aperture_fenced; 19203b705cfSriastradh uint32_t max_upload_tile_size, max_copy_tile_size; 19303b705cfSriastradh uint32_t max_gpu_size, max_cpu_size; 19403b705cfSriastradh uint32_t large_object_size, max_object_size; 19503b705cfSriastradh uint32_t buffer_size; 19603b705cfSriastradh 19703b705cfSriastradh void (*context_switch)(struct kgem *kgem, int new_mode); 19803b705cfSriastradh void (*retire)(struct kgem *kgem); 19903b705cfSriastradh void (*expire)(struct kgem *kgem); 20003b705cfSriastradh 20103b705cfSriastradh void (*memcpy_to_tiled_x)(const void *src, void *dst, int bpp, 20203b705cfSriastradh int32_t src_stride, int32_t dst_stride, 20303b705cfSriastradh int16_t src_x, int16_t src_y, 20403b705cfSriastradh int16_t dst_x, int16_t dst_y, 20503b705cfSriastradh uint16_t width, uint16_t height); 20603b705cfSriastradh void (*memcpy_from_tiled_x)(const void *src, void *dst, int bpp, 20703b705cfSriastradh int32_t src_stride, int32_t dst_stride, 20803b705cfSriastradh int16_t src_x, int16_t src_y, 20903b705cfSriastradh int16_t dst_x, int16_t dst_y, 21003b705cfSriastradh uint16_t width, uint16_t height); 21103b705cfSriastradh 21203b705cfSriastradh uint16_t reloc__self[256]; 21303b705cfSriastradh uint32_t batch[64*1024-8] page_aligned; 21403b705cfSriastradh struct drm_i915_gem_exec_object2 exec[384] page_aligned; 21503b705cfSriastradh struct drm_i915_gem_relocation_entry reloc[8192] page_aligned; 21603b705cfSriastradh 21703b705cfSriastradh#ifdef DEBUG_MEMORY 21803b705cfSriastradh struct { 21903b705cfSriastradh int bo_allocs; 22003b705cfSriastradh size_t bo_bytes; 22103b705cfSriastradh } debug_memory; 22203b705cfSriastradh#endif 22303b705cfSriastradh}; 22403b705cfSriastradh 22503b705cfSriastradh#define KGEM_MAX_DEFERRED_VBO 16 22603b705cfSriastradh 22703b705cfSriastradh#define KGEM_BATCH_RESERVED 1 22803b705cfSriastradh#define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO) 22903b705cfSriastradh#define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO) 23003b705cfSriastradh 23103b705cfSriastradh#ifndef ARRAY_SIZE 23203b705cfSriastradh#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 23303b705cfSriastradh#endif 23403b705cfSriastradh 23503b705cfSriastradh#define KGEM_BATCH_SIZE(K) ((K)->batch_size-KGEM_BATCH_RESERVED) 23603b705cfSriastradh#define KGEM_EXEC_SIZE(K) (int)(ARRAY_SIZE((K)->exec)-KGEM_EXEC_RESERVED) 23703b705cfSriastradh#define KGEM_RELOC_SIZE(K) (int)(ARRAY_SIZE((K)->reloc)-KGEM_RELOC_RESERVED) 23803b705cfSriastradh 23903b705cfSriastradhvoid kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen); 24003b705cfSriastradhvoid kgem_reset(struct kgem *kgem); 24103b705cfSriastradh 24203b705cfSriastradhstruct kgem_bo *kgem_create_map(struct kgem *kgem, 24303b705cfSriastradh void *ptr, uint32_t size, 24403b705cfSriastradh bool read_only); 24503b705cfSriastradh 24603b705cfSriastradhstruct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name); 24703b705cfSriastradhstruct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size); 24803b705cfSriastradhint kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo); 24903b705cfSriastradh 25003b705cfSriastradhstruct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags); 25103b705cfSriastradhstruct kgem_bo *kgem_create_proxy(struct kgem *kgem, 25203b705cfSriastradh struct kgem_bo *target, 25303b705cfSriastradh int offset, int length); 25403b705cfSriastradh 25503b705cfSriastradhstruct kgem_bo *kgem_upload_source_image(struct kgem *kgem, 25603b705cfSriastradh const void *data, 25703b705cfSriastradh const BoxRec *box, 25803b705cfSriastradh int stride, int bpp); 25903b705cfSriastradhvoid kgem_proxy_bo_attach(struct kgem_bo *bo, struct kgem_bo **ptr); 26003b705cfSriastradh 26103b705cfSriastradhint kgem_choose_tiling(struct kgem *kgem, 26203b705cfSriastradh int tiling, int width, int height, int bpp); 26303b705cfSriastradhunsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth); 26403b705cfSriastradh#define KGEM_CAN_CREATE_GPU 0x1 26503b705cfSriastradh#define KGEM_CAN_CREATE_CPU 0x2 26603b705cfSriastradh#define KGEM_CAN_CREATE_LARGE 0x4 26703b705cfSriastradh#define KGEM_CAN_CREATE_GTT 0x8 26803b705cfSriastradh 26903b705cfSriastradhuint32_t kgem_get_unique_id(struct kgem *kgem); 27003b705cfSriastradh 27103b705cfSriastradhstruct kgem_bo * 27203b705cfSriastradhkgem_replace_bo(struct kgem *kgem, 27303b705cfSriastradh struct kgem_bo *src, 27403b705cfSriastradh uint32_t width, 27503b705cfSriastradh uint32_t height, 27603b705cfSriastradh uint32_t pitch, 27703b705cfSriastradh uint32_t bpp); 27803b705cfSriastradhenum { 27903b705cfSriastradh CREATE_EXACT = 0x1, 28003b705cfSriastradh CREATE_INACTIVE = 0x2, 28103b705cfSriastradh CREATE_CPU_MAP = 0x4, 28203b705cfSriastradh CREATE_GTT_MAP = 0x8, 28303b705cfSriastradh CREATE_SCANOUT = 0x10, 28403b705cfSriastradh CREATE_PRIME = 0x20, 28503b705cfSriastradh CREATE_TEMPORARY = 0x40, 28603b705cfSriastradh CREATE_CACHED = 0x80, 28703b705cfSriastradh CREATE_NO_RETIRE = 0x100, 28803b705cfSriastradh CREATE_NO_THROTTLE = 0x200, 28903b705cfSriastradh}; 29003b705cfSriastradhstruct kgem_bo *kgem_create_2d(struct kgem *kgem, 29103b705cfSriastradh int width, 29203b705cfSriastradh int height, 29303b705cfSriastradh int bpp, 29403b705cfSriastradh int tiling, 29503b705cfSriastradh uint32_t flags); 29603b705cfSriastradhstruct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem, 29703b705cfSriastradh int width, 29803b705cfSriastradh int height, 29903b705cfSriastradh int bpp, 30003b705cfSriastradh uint32_t flags); 30103b705cfSriastradh 30203b705cfSriastradhuint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format); 30303b705cfSriastradhvoid kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset); 30403b705cfSriastradh 30503b705cfSriastradhbool kgem_retire(struct kgem *kgem); 30603b705cfSriastradh 30703b705cfSriastradhbool __kgem_ring_is_idle(struct kgem *kgem, int ring); 30803b705cfSriastradhstatic inline bool kgem_ring_is_idle(struct kgem *kgem, int ring) 30903b705cfSriastradh{ 31003b705cfSriastradh ring = ring == KGEM_BLT; 31103b705cfSriastradh 31203b705cfSriastradh if (list_is_empty(&kgem->requests[ring])) 31303b705cfSriastradh return true; 31403b705cfSriastradh 31503b705cfSriastradh return __kgem_ring_is_idle(kgem, ring); 31603b705cfSriastradh} 31703b705cfSriastradh 31803b705cfSriastradhstatic inline bool kgem_is_idle(struct kgem *kgem) 31903b705cfSriastradh{ 32003b705cfSriastradh if (!kgem->need_retire) 32103b705cfSriastradh return true; 32203b705cfSriastradh 32303b705cfSriastradh return kgem_ring_is_idle(kgem, kgem->ring); 32403b705cfSriastradh} 32503b705cfSriastradh 32603b705cfSriastradhstatic inline bool __kgem_ring_empty(struct kgem *kgem) 32703b705cfSriastradh{ 32803b705cfSriastradh return list_is_empty(&kgem->requests[kgem->ring == KGEM_BLT]); 32903b705cfSriastradh} 33003b705cfSriastradh 33103b705cfSriastradhvoid _kgem_submit(struct kgem *kgem); 33203b705cfSriastradhstatic inline void kgem_submit(struct kgem *kgem) 33303b705cfSriastradh{ 33403b705cfSriastradh if (kgem->nbatch) 33503b705cfSriastradh _kgem_submit(kgem); 33603b705cfSriastradh} 33703b705cfSriastradh 33803b705cfSriastradhstatic inline bool kgem_flush(struct kgem *kgem, bool flush) 33903b705cfSriastradh{ 34003b705cfSriastradh if (kgem->nreloc == 0) 34103b705cfSriastradh return false; 34203b705cfSriastradh 34303b705cfSriastradh return (kgem->flush ^ flush) && kgem_ring_is_idle(kgem, kgem->ring); 34403b705cfSriastradh} 34503b705cfSriastradh 34603b705cfSriastradhstatic inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo) 34703b705cfSriastradh{ 34803b705cfSriastradh if (bo->exec) 34903b705cfSriastradh _kgem_submit(kgem); 35003b705cfSriastradh} 35103b705cfSriastradh 35203b705cfSriastradhvoid kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo); 35303b705cfSriastradh 35403b705cfSriastradhstatic inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo) 35503b705cfSriastradh{ 35603b705cfSriastradh assert(bo->refcnt); 35703b705cfSriastradh bo->refcnt++; 35803b705cfSriastradh return bo; 35903b705cfSriastradh} 36003b705cfSriastradh 36103b705cfSriastradhvoid _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo); 36203b705cfSriastradhstatic inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) 36303b705cfSriastradh{ 36403b705cfSriastradh assert(bo->refcnt); 36503b705cfSriastradh if (--bo->refcnt == 0) 36603b705cfSriastradh _kgem_bo_destroy(kgem, bo); 36703b705cfSriastradh} 36803b705cfSriastradh 36903b705cfSriastradhvoid kgem_clear_dirty(struct kgem *kgem); 37003b705cfSriastradh 37103b705cfSriastradhstatic inline void kgem_set_mode(struct kgem *kgem, 37203b705cfSriastradh enum kgem_mode mode, 37303b705cfSriastradh struct kgem_bo *bo) 37403b705cfSriastradh{ 37503b705cfSriastradh assert(!kgem->wedged); 37603b705cfSriastradh 37703b705cfSriastradh#if DEBUG_FLUSH_BATCH 37803b705cfSriastradh kgem_submit(kgem); 37903b705cfSriastradh#endif 38003b705cfSriastradh 38103b705cfSriastradh if (kgem->nreloc && bo->exec == NULL && kgem_ring_is_idle(kgem, kgem->ring)) 38203b705cfSriastradh _kgem_submit(kgem); 38303b705cfSriastradh 38403b705cfSriastradh if (kgem->mode == mode) 38503b705cfSriastradh return; 38603b705cfSriastradh 38703b705cfSriastradh kgem->context_switch(kgem, mode); 38803b705cfSriastradh kgem->mode = mode; 38903b705cfSriastradh} 39003b705cfSriastradh 39103b705cfSriastradhstatic inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode) 39203b705cfSriastradh{ 39303b705cfSriastradh assert(kgem->mode == KGEM_NONE); 39403b705cfSriastradh assert(kgem->nbatch == 0); 39503b705cfSriastradh assert(!kgem->wedged); 39603b705cfSriastradh kgem->context_switch(kgem, mode); 39703b705cfSriastradh kgem->mode = mode; 39803b705cfSriastradh} 39903b705cfSriastradh 40003b705cfSriastradhstatic inline bool kgem_check_batch(struct kgem *kgem, int num_dwords) 40103b705cfSriastradh{ 40203b705cfSriastradh assert(num_dwords > 0); 40303b705cfSriastradh assert(kgem->nbatch < kgem->surface); 40403b705cfSriastradh assert(kgem->surface <= kgem->batch_size); 40503b705cfSriastradh return likely(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED <= kgem->surface); 40603b705cfSriastradh} 40703b705cfSriastradh 40803b705cfSriastradhstatic inline bool kgem_check_reloc(struct kgem *kgem, int n) 40903b705cfSriastradh{ 41003b705cfSriastradh assert(kgem->nreloc <= KGEM_RELOC_SIZE(kgem)); 41103b705cfSriastradh return likely(kgem->nreloc + n <= KGEM_RELOC_SIZE(kgem)); 41203b705cfSriastradh} 41303b705cfSriastradh 41403b705cfSriastradhstatic inline bool kgem_check_exec(struct kgem *kgem, int n) 41503b705cfSriastradh{ 41603b705cfSriastradh assert(kgem->nexec <= KGEM_EXEC_SIZE(kgem)); 41703b705cfSriastradh return likely(kgem->nexec + n <= KGEM_EXEC_SIZE(kgem)); 41803b705cfSriastradh} 41903b705cfSriastradh 42003b705cfSriastradhstatic inline bool kgem_check_reloc_and_exec(struct kgem *kgem, int n) 42103b705cfSriastradh{ 42203b705cfSriastradh return kgem_check_reloc(kgem, n) && kgem_check_exec(kgem, n); 42303b705cfSriastradh} 42403b705cfSriastradh 42503b705cfSriastradhstatic inline bool kgem_check_batch_with_surfaces(struct kgem *kgem, 42603b705cfSriastradh int num_dwords, 42703b705cfSriastradh int num_surfaces) 42803b705cfSriastradh{ 42903b705cfSriastradh return (int)(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED) <= (int)(kgem->surface - num_surfaces*8) && 43003b705cfSriastradh kgem_check_reloc(kgem, num_surfaces) && 43103b705cfSriastradh kgem_check_exec(kgem, num_surfaces); 43203b705cfSriastradh} 43303b705cfSriastradh 43403b705cfSriastradhstatic inline uint32_t *kgem_get_batch(struct kgem *kgem) 43503b705cfSriastradh{ 43603b705cfSriastradh if (kgem->nreloc) { 43703b705cfSriastradh unsigned mode = kgem->mode; 43803b705cfSriastradh _kgem_submit(kgem); 43903b705cfSriastradh _kgem_set_mode(kgem, mode); 44003b705cfSriastradh } 44103b705cfSriastradh 44203b705cfSriastradh return kgem->batch + kgem->nbatch; 44303b705cfSriastradh} 44403b705cfSriastradh 44503b705cfSriastradhbool kgem_check_bo(struct kgem *kgem, ...) __attribute__((sentinel(0))); 44603b705cfSriastradhbool kgem_check_bo_fenced(struct kgem *kgem, struct kgem_bo *bo); 44703b705cfSriastradhbool kgem_check_many_bo_fenced(struct kgem *kgem, ...) __attribute__((sentinel(0))); 44803b705cfSriastradh 44903b705cfSriastradh#define KGEM_RELOC_FENCED 0x8000 45003b705cfSriastradhuint32_t kgem_add_reloc(struct kgem *kgem, 45103b705cfSriastradh uint32_t pos, 45203b705cfSriastradh struct kgem_bo *bo, 45303b705cfSriastradh uint32_t read_write_domains, 45403b705cfSriastradh uint32_t delta); 45503b705cfSriastradh 45603b705cfSriastradhvoid *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo); 45703b705cfSriastradhvoid *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo); 45803b705cfSriastradhvoid *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo); 45903b705cfSriastradhvoid kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo); 46003b705cfSriastradhvoid *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo); 46103b705cfSriastradhvoid *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo); 46203b705cfSriastradhvoid kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo); 46303b705cfSriastradhvoid kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write); 46403b705cfSriastradhvoid *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo); 46503b705cfSriastradhvoid __kgem_bo_unmap__cpu(struct kgem *kgem, struct kgem_bo *bo, void *ptr); 46603b705cfSriastradhuint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo); 46703b705cfSriastradh 46803b705cfSriastradhbool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo, 46903b705cfSriastradh const void *data, int length); 47003b705cfSriastradh 47103b705cfSriastradhint kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo); 47203b705cfSriastradhvoid kgem_get_tile_size(struct kgem *kgem, int tiling, 47303b705cfSriastradh int *tile_width, int *tile_height, int *tile_size); 47403b705cfSriastradh 47503b705cfSriastradhstatic inline int __kgem_buffer_size(struct kgem_bo *bo) 47603b705cfSriastradh{ 47703b705cfSriastradh assert(bo->proxy != NULL); 47803b705cfSriastradh return bo->size.bytes; 47903b705cfSriastradh} 48003b705cfSriastradh 48103b705cfSriastradhstatic inline int __kgem_bo_size(struct kgem_bo *bo) 48203b705cfSriastradh{ 48303b705cfSriastradh assert(bo->proxy == NULL); 48403b705cfSriastradh return PAGE_SIZE * bo->size.pages.count; 48503b705cfSriastradh} 48603b705cfSriastradh 48703b705cfSriastradhstatic inline int kgem_bo_size(struct kgem_bo *bo) 48803b705cfSriastradh{ 48903b705cfSriastradh if (bo->proxy) 49003b705cfSriastradh return __kgem_buffer_size(bo); 49103b705cfSriastradh else 49203b705cfSriastradh return __kgem_bo_size(bo); 49303b705cfSriastradh} 49403b705cfSriastradh 49503b705cfSriastradhstatic inline bool kgem_bo_blt_pitch_is_ok(struct kgem *kgem, 49603b705cfSriastradh struct kgem_bo *bo) 49703b705cfSriastradh{ 49803b705cfSriastradh int pitch = bo->pitch; 49903b705cfSriastradh if (kgem->gen >= 040 && bo->tiling) 50003b705cfSriastradh pitch /= 4; 50103b705cfSriastradh if (pitch > MAXSHORT) { 50203b705cfSriastradh DBG(("%s: can not blt to handle=%d, adjusted pitch=%d\n", 50303b705cfSriastradh __FUNCTION__, bo->handle, pitch)); 50403b705cfSriastradh return false; 50503b705cfSriastradh } 50603b705cfSriastradh 50703b705cfSriastradh return true; 50803b705cfSriastradh} 50903b705cfSriastradh 51003b705cfSriastradhstatic inline bool kgem_bo_can_blt(struct kgem *kgem, 51103b705cfSriastradh struct kgem_bo *bo) 51203b705cfSriastradh{ 51303b705cfSriastradh if (bo->tiling == I915_TILING_Y) { 51403b705cfSriastradh DBG(("%s: can not blt to handle=%d, tiling=Y\n", 51503b705cfSriastradh __FUNCTION__, bo->handle)); 51603b705cfSriastradh return false; 51703b705cfSriastradh } 51803b705cfSriastradh 51903b705cfSriastradh return kgem_bo_blt_pitch_is_ok(kgem, bo); 52003b705cfSriastradh} 52103b705cfSriastradh 52203b705cfSriastradhstatic inline bool __kgem_bo_is_mappable(struct kgem *kgem, 52303b705cfSriastradh struct kgem_bo *bo) 52403b705cfSriastradh{ 52503b705cfSriastradh if (bo->domain == DOMAIN_GTT) 52603b705cfSriastradh return true; 52703b705cfSriastradh 52803b705cfSriastradh if (kgem->gen < 040 && bo->tiling && 52903b705cfSriastradh bo->presumed_offset & (kgem_bo_fenced_size(kgem, bo) - 1)) 53003b705cfSriastradh return false; 53103b705cfSriastradh 53203b705cfSriastradh if (kgem->gen == 021 && bo->tiling == I915_TILING_Y) 53303b705cfSriastradh return false; 53403b705cfSriastradh 53503b705cfSriastradh if (kgem->has_llc && bo->tiling == I915_TILING_NONE) 53603b705cfSriastradh return true; 53703b705cfSriastradh 53803b705cfSriastradh if (!bo->presumed_offset) 53903b705cfSriastradh return kgem_bo_size(bo) <= kgem->aperture_mappable / 4; 54003b705cfSriastradh 54103b705cfSriastradh return bo->presumed_offset + kgem_bo_size(bo) <= kgem->aperture_mappable; 54203b705cfSriastradh} 54303b705cfSriastradh 54403b705cfSriastradhstatic inline bool kgem_bo_is_mappable(struct kgem *kgem, 54503b705cfSriastradh struct kgem_bo *bo) 54603b705cfSriastradh{ 54703b705cfSriastradh DBG(("%s: domain=%d, offset: %d size: %d\n", 54803b705cfSriastradh __FUNCTION__, bo->domain, bo->presumed_offset, kgem_bo_size(bo))); 54903b705cfSriastradh assert(bo->refcnt); 55003b705cfSriastradh return __kgem_bo_is_mappable(kgem, bo); 55103b705cfSriastradh} 55203b705cfSriastradh 55303b705cfSriastradhstatic inline bool kgem_bo_mapped(struct kgem *kgem, struct kgem_bo *bo) 55403b705cfSriastradh{ 55503b705cfSriastradh DBG(("%s: map=%p, tiling=%d, domain=%d\n", 55603b705cfSriastradh __FUNCTION__, bo->map, bo->tiling, bo->domain)); 55703b705cfSriastradh assert(bo->refcnt); 55803b705cfSriastradh 55903b705cfSriastradh if (bo->map == NULL) 56003b705cfSriastradh return bo->tiling == I915_TILING_NONE && bo->domain == DOMAIN_CPU; 56103b705cfSriastradh 56203b705cfSriastradh return IS_CPU_MAP(bo->map) == !bo->tiling; 56303b705cfSriastradh} 56403b705cfSriastradh 56503b705cfSriastradhstatic inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo) 56603b705cfSriastradh{ 56703b705cfSriastradh if (kgem_bo_mapped(kgem, bo)) 56803b705cfSriastradh return true; 56903b705cfSriastradh 57003b705cfSriastradh if (!bo->tiling && (kgem->has_llc || bo->domain == DOMAIN_CPU)) 57103b705cfSriastradh return true; 57203b705cfSriastradh 57303b705cfSriastradh if (kgem->gen == 021 && bo->tiling == I915_TILING_Y) 57403b705cfSriastradh return false; 57503b705cfSriastradh 57603b705cfSriastradh return kgem_bo_size(bo) <= kgem->aperture_mappable / 4; 57703b705cfSriastradh} 57803b705cfSriastradh 57903b705cfSriastradhstatic inline bool kgem_bo_can_map__cpu(struct kgem *kgem, 58003b705cfSriastradh struct kgem_bo *bo, 58103b705cfSriastradh bool write) 58203b705cfSriastradh{ 58303b705cfSriastradh if (bo->purged || (bo->scanout && write)) 58403b705cfSriastradh return false; 58503b705cfSriastradh 58603b705cfSriastradh if (kgem->has_llc) 58703b705cfSriastradh return true; 58803b705cfSriastradh 58903b705cfSriastradh if (bo->domain != DOMAIN_CPU) 59003b705cfSriastradh return false; 59103b705cfSriastradh 59203b705cfSriastradh return !write || bo->exec == NULL; 59303b705cfSriastradh} 59403b705cfSriastradh 59503b705cfSriastradhstatic inline bool kgem_bo_is_snoop(struct kgem_bo *bo) 59603b705cfSriastradh{ 59703b705cfSriastradh assert(bo->refcnt); 59803b705cfSriastradh while (bo->proxy) 59903b705cfSriastradh bo = bo->proxy; 60003b705cfSriastradh return bo->snoop; 60103b705cfSriastradh} 60203b705cfSriastradh 60303b705cfSriastradhvoid kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo); 60403b705cfSriastradh 60503b705cfSriastradhbool __kgem_busy(struct kgem *kgem, int handle); 60603b705cfSriastradh 60703b705cfSriastradhstatic inline void kgem_bo_mark_busy(struct kgem_bo *bo, int ring) 60803b705cfSriastradh{ 60903b705cfSriastradh bo->rq = (struct kgem_request *)((uintptr_t)bo->rq | ring); 61003b705cfSriastradh} 61103b705cfSriastradh 61203b705cfSriastradhinline static void __kgem_bo_clear_busy(struct kgem_bo *bo) 61303b705cfSriastradh{ 61403b705cfSriastradh bo->rq = NULL; 61503b705cfSriastradh list_del(&bo->request); 61603b705cfSriastradh 61703b705cfSriastradh bo->domain = DOMAIN_NONE; 61803b705cfSriastradh bo->needs_flush = false; 61903b705cfSriastradh bo->gtt_dirty = false; 62003b705cfSriastradh} 62103b705cfSriastradh 62203b705cfSriastradhstatic inline bool kgem_bo_is_busy(struct kgem_bo *bo) 62303b705cfSriastradh{ 62403b705cfSriastradh DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, 62503b705cfSriastradh bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL)); 62603b705cfSriastradh assert(bo->refcnt); 62703b705cfSriastradh return bo->rq; 62803b705cfSriastradh} 62903b705cfSriastradh 63003b705cfSriastradhstatic inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo) 63103b705cfSriastradh{ 63203b705cfSriastradh DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__, 63303b705cfSriastradh bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL)); 63403b705cfSriastradh assert(bo->refcnt); 63503b705cfSriastradh 63603b705cfSriastradh if (bo->exec) 63703b705cfSriastradh return true; 63803b705cfSriastradh 63903b705cfSriastradh if (kgem_flush(kgem, bo->flush)) 64003b705cfSriastradh kgem_submit(kgem); 64103b705cfSriastradh 64203b705cfSriastradh if (bo->rq && !__kgem_busy(kgem, bo->handle)) 64303b705cfSriastradh __kgem_bo_clear_busy(bo); 64403b705cfSriastradh 64503b705cfSriastradh return kgem_bo_is_busy(bo); 64603b705cfSriastradh} 64703b705cfSriastradh 64803b705cfSriastradhstatic inline bool kgem_bo_is_render(struct kgem_bo *bo) 64903b705cfSriastradh{ 65003b705cfSriastradh DBG(("%s: handle=%d, rq? %d [%d]\n", __FUNCTION__, 65103b705cfSriastradh bo->handle, bo->rq != NULL, RQ_RING(bo->rq))); 65203b705cfSriastradh assert(bo->refcnt); 65303b705cfSriastradh return bo->rq && RQ_RING(bo->rq) == I915_EXEC_RENDER; 65403b705cfSriastradh} 65503b705cfSriastradh 65603b705cfSriastradhstatic inline void kgem_bo_mark_unreusable(struct kgem_bo *bo) 65703b705cfSriastradh{ 65803b705cfSriastradh while (bo->proxy) { 65903b705cfSriastradh bo->flush = true; 66003b705cfSriastradh bo = bo->proxy; 66103b705cfSriastradh } 66203b705cfSriastradh bo->flush = true; 66303b705cfSriastradh bo->reusable = false; 66403b705cfSriastradh} 66503b705cfSriastradh 66603b705cfSriastradhstatic inline bool kgem_bo_is_dirty(struct kgem_bo *bo) 66703b705cfSriastradh{ 66803b705cfSriastradh if (bo == NULL) 66903b705cfSriastradh return false; 67003b705cfSriastradh 67103b705cfSriastradh assert(bo->refcnt); 67203b705cfSriastradh return bo->gpu_dirty; 67303b705cfSriastradh} 67403b705cfSriastradh 67503b705cfSriastradhstatic inline void kgem_bo_unclean(struct kgem *kgem, struct kgem_bo *bo) 67603b705cfSriastradh{ 67703b705cfSriastradh /* The bo is outside of our control, so presume it is written to */ 67803b705cfSriastradh bo->needs_flush = true; 67903b705cfSriastradh if (bo->rq == NULL) 68003b705cfSriastradh bo->rq = (void *)kgem; 68103b705cfSriastradh 68203b705cfSriastradh if (bo->domain != DOMAIN_GPU) 68303b705cfSriastradh bo->domain = DOMAIN_NONE; 68403b705cfSriastradh} 68503b705cfSriastradh 68603b705cfSriastradhstatic inline void __kgem_bo_mark_dirty(struct kgem_bo *bo) 68703b705cfSriastradh{ 68803b705cfSriastradh DBG(("%s: handle=%d (proxy? %d)\n", __FUNCTION__, 68903b705cfSriastradh bo->handle, bo->proxy != NULL)); 69003b705cfSriastradh 69103b705cfSriastradh bo->exec->flags |= LOCAL_EXEC_OBJECT_WRITE; 69203b705cfSriastradh bo->needs_flush = bo->gpu_dirty = true; 69303b705cfSriastradh list_move(&bo->request, &RQ(bo->rq)->buffers); 69403b705cfSriastradh} 69503b705cfSriastradh 69603b705cfSriastradhstatic inline void kgem_bo_mark_dirty(struct kgem_bo *bo) 69703b705cfSriastradh{ 69803b705cfSriastradh assert(bo->refcnt); 69903b705cfSriastradh do { 70003b705cfSriastradh assert(bo->exec); 70103b705cfSriastradh assert(bo->rq); 70203b705cfSriastradh 70303b705cfSriastradh if (bo->gpu_dirty) 70403b705cfSriastradh return; 70503b705cfSriastradh 70603b705cfSriastradh __kgem_bo_mark_dirty(bo); 70703b705cfSriastradh } while ((bo = bo->proxy)); 70803b705cfSriastradh} 70903b705cfSriastradh 71003b705cfSriastradh#define KGEM_BUFFER_WRITE 0x1 71103b705cfSriastradh#define KGEM_BUFFER_INPLACE 0x2 71203b705cfSriastradh#define KGEM_BUFFER_LAST 0x4 71303b705cfSriastradh 71403b705cfSriastradh#define KGEM_BUFFER_WRITE_INPLACE (KGEM_BUFFER_WRITE | KGEM_BUFFER_INPLACE) 71503b705cfSriastradh 71603b705cfSriastradhstruct kgem_bo *kgem_create_buffer(struct kgem *kgem, 71703b705cfSriastradh uint32_t size, uint32_t flags, 71803b705cfSriastradh void **ret); 71903b705cfSriastradhstruct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem, 72003b705cfSriastradh int width, int height, int bpp, 72103b705cfSriastradh uint32_t flags, 72203b705cfSriastradh void **ret); 72303b705cfSriastradhbool kgem_buffer_is_inplace(struct kgem_bo *bo); 72403b705cfSriastradhvoid kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo); 72503b705cfSriastradh 72603b705cfSriastradhvoid kgem_throttle(struct kgem *kgem); 72703b705cfSriastradh#define MAX_INACTIVE_TIME 10 72803b705cfSriastradhbool kgem_expire_cache(struct kgem *kgem); 72903b705cfSriastradhvoid kgem_purge_cache(struct kgem *kgem); 73003b705cfSriastradhvoid kgem_cleanup_cache(struct kgem *kgem); 73103b705cfSriastradh 73203b705cfSriastradhvoid kgem_clean_scanout_cache(struct kgem *kgem); 73303b705cfSriastradhvoid kgem_clean_large_cache(struct kgem *kgem); 73403b705cfSriastradh 73503b705cfSriastradh#if HAS_DEBUG_FULL 73603b705cfSriastradhvoid __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch); 73703b705cfSriastradh#else 73803b705cfSriastradhstatic inline void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) 73903b705cfSriastradh{ 74003b705cfSriastradh (void)kgem; 74103b705cfSriastradh (void)nbatch; 74203b705cfSriastradh} 74303b705cfSriastradh#endif 74403b705cfSriastradh 74503b705cfSriastradhstatic inline void 74603b705cfSriastradhmemcpy_to_tiled_x(struct kgem *kgem, 74703b705cfSriastradh const void *src, void *dst, int bpp, 74803b705cfSriastradh int32_t src_stride, int32_t dst_stride, 74903b705cfSriastradh int16_t src_x, int16_t src_y, 75003b705cfSriastradh int16_t dst_x, int16_t dst_y, 75103b705cfSriastradh uint16_t width, uint16_t height) 75203b705cfSriastradh{ 75303b705cfSriastradh return kgem->memcpy_to_tiled_x(src, dst, bpp, 75403b705cfSriastradh src_stride, dst_stride, 75503b705cfSriastradh src_x, src_y, 75603b705cfSriastradh dst_x, dst_y, 75703b705cfSriastradh width, height); 75803b705cfSriastradh} 75903b705cfSriastradh 76003b705cfSriastradhstatic inline void 76103b705cfSriastradhmemcpy_from_tiled_x(struct kgem *kgem, 76203b705cfSriastradh const void *src, void *dst, int bpp, 76303b705cfSriastradh int32_t src_stride, int32_t dst_stride, 76403b705cfSriastradh int16_t src_x, int16_t src_y, 76503b705cfSriastradh int16_t dst_x, int16_t dst_y, 76603b705cfSriastradh uint16_t width, uint16_t height) 76703b705cfSriastradh{ 76803b705cfSriastradh return kgem->memcpy_from_tiled_x(src, dst, bpp, 76903b705cfSriastradh src_stride, dst_stride, 77003b705cfSriastradh src_x, src_y, 77103b705cfSriastradh dst_x, dst_y, 77203b705cfSriastradh width, height); 77303b705cfSriastradh} 77403b705cfSriastradh 77503b705cfSriastradhvoid choose_memcpy_tiled_x(struct kgem *kgem, int swizzling); 77603b705cfSriastradh 77703b705cfSriastradh#endif /* KGEM_H */ 778