1d722e3fbSopenharmony_ci/************************************************************************** 2d722e3fbSopenharmony_ci * 3d722e3fbSopenharmony_ci * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 4d722e3fbSopenharmony_ci * All Rights Reserved. 5d722e3fbSopenharmony_ci * 6d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the 8d722e3fbSopenharmony_ci * "Software"), to deal in the Software without restriction, including 9d722e3fbSopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10d722e3fbSopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11d722e3fbSopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12d722e3fbSopenharmony_ci * the following conditions: 13d722e3fbSopenharmony_ci * 14d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the 15d722e3fbSopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16d722e3fbSopenharmony_ci * of the Software. 17d722e3fbSopenharmony_ci * 18d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19d722e3fbSopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20d722e3fbSopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21d722e3fbSopenharmony_ci * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22d722e3fbSopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23d722e3fbSopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24d722e3fbSopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25d722e3fbSopenharmony_ci * 26d722e3fbSopenharmony_ci **************************************************************************/ 27d722e3fbSopenharmony_ci 28d722e3fbSopenharmony_ci/* Originally a fake version of the buffer manager so that we can 29d722e3fbSopenharmony_ci * prototype the changes in a driver fairly quickly, has been fleshed 30d722e3fbSopenharmony_ci * out to a fully functional interim solution. 31d722e3fbSopenharmony_ci * 32d722e3fbSopenharmony_ci * Basically wraps the old style memory management in the new 33d722e3fbSopenharmony_ci * programming interface, but is more expressive and avoids many of 34d722e3fbSopenharmony_ci * the bugs in the old texture manager. 35d722e3fbSopenharmony_ci */ 36d722e3fbSopenharmony_ci 37d722e3fbSopenharmony_ci#include <stdlib.h> 38d722e3fbSopenharmony_ci#include <string.h> 39d722e3fbSopenharmony_ci#include <assert.h> 40d722e3fbSopenharmony_ci#include <errno.h> 41d722e3fbSopenharmony_ci#include <strings.h> 42d722e3fbSopenharmony_ci#include <xf86drm.h> 43d722e3fbSopenharmony_ci#include <pthread.h> 44d722e3fbSopenharmony_ci#include "intel_bufmgr.h" 45d722e3fbSopenharmony_ci#include "intel_bufmgr_priv.h" 46d722e3fbSopenharmony_ci#include "drm.h" 47d722e3fbSopenharmony_ci#include "i915_drm.h" 48d722e3fbSopenharmony_ci#include "mm.h" 49d722e3fbSopenharmony_ci#include "libdrm_macros.h" 50d722e3fbSopenharmony_ci#include "libdrm_lists.h" 51d722e3fbSopenharmony_ci 52d722e3fbSopenharmony_ci#define DBG(...) do { \ 53d722e3fbSopenharmony_ci if (bufmgr_fake->bufmgr.debug) \ 54d722e3fbSopenharmony_ci drmMsg(__VA_ARGS__); \ 55d722e3fbSopenharmony_ci} while (0) 56d722e3fbSopenharmony_ci 57d722e3fbSopenharmony_ci/* Internal flags: 58d722e3fbSopenharmony_ci */ 59d722e3fbSopenharmony_ci#define BM_NO_BACKING_STORE 0x00000001 60d722e3fbSopenharmony_ci#define BM_NO_FENCE_SUBDATA 0x00000002 61d722e3fbSopenharmony_ci#define BM_PINNED 0x00000004 62d722e3fbSopenharmony_ci 63d722e3fbSopenharmony_ci/* Wrapper around mm.c's mem_block, which understands that you must 64d722e3fbSopenharmony_ci * wait for fences to expire before memory can be freed. This is 65d722e3fbSopenharmony_ci * specific to our use of memcpy for uploads - an upload that was 66d722e3fbSopenharmony_ci * processed through the command queue wouldn't need to care about 67d722e3fbSopenharmony_ci * fences. 68d722e3fbSopenharmony_ci */ 69d722e3fbSopenharmony_ci#define MAX_RELOCS 4096 70d722e3fbSopenharmony_ci 71d722e3fbSopenharmony_cistruct fake_buffer_reloc { 72d722e3fbSopenharmony_ci /** Buffer object that the relocation points at. */ 73d722e3fbSopenharmony_ci drm_intel_bo *target_buf; 74d722e3fbSopenharmony_ci /** Offset of the relocation entry within reloc_buf. */ 75d722e3fbSopenharmony_ci uint32_t offset; 76d722e3fbSopenharmony_ci /** 77d722e3fbSopenharmony_ci * Cached value of the offset when we last performed this relocation. 78d722e3fbSopenharmony_ci */ 79d722e3fbSopenharmony_ci uint32_t last_target_offset; 80d722e3fbSopenharmony_ci /** Value added to target_buf's offset to get the relocation entry. */ 81d722e3fbSopenharmony_ci uint32_t delta; 82d722e3fbSopenharmony_ci /** Cache domains the target buffer is read into. */ 83d722e3fbSopenharmony_ci uint32_t read_domains; 84d722e3fbSopenharmony_ci /** Cache domain the target buffer will have dirty cachelines in. */ 85d722e3fbSopenharmony_ci uint32_t write_domain; 86d722e3fbSopenharmony_ci}; 87d722e3fbSopenharmony_ci 88d722e3fbSopenharmony_cistruct block { 89d722e3fbSopenharmony_ci struct block *next, *prev; 90d722e3fbSopenharmony_ci struct mem_block *mem; /* BM_MEM_AGP */ 91d722e3fbSopenharmony_ci 92d722e3fbSopenharmony_ci /** 93d722e3fbSopenharmony_ci * Marks that the block is currently in the aperture and has yet to be 94d722e3fbSopenharmony_ci * fenced. 95d722e3fbSopenharmony_ci */ 96d722e3fbSopenharmony_ci unsigned on_hardware:1; 97d722e3fbSopenharmony_ci /** 98d722e3fbSopenharmony_ci * Marks that the block is currently fenced (being used by rendering) 99d722e3fbSopenharmony_ci * and can't be freed until @fence is passed. 100d722e3fbSopenharmony_ci */ 101d722e3fbSopenharmony_ci unsigned fenced:1; 102d722e3fbSopenharmony_ci 103d722e3fbSopenharmony_ci /** Fence cookie for the block. */ 104d722e3fbSopenharmony_ci unsigned fence; /* Split to read_fence, write_fence */ 105d722e3fbSopenharmony_ci 106d722e3fbSopenharmony_ci drm_intel_bo *bo; 107d722e3fbSopenharmony_ci void *virtual; 108d722e3fbSopenharmony_ci}; 109d722e3fbSopenharmony_ci 110d722e3fbSopenharmony_citypedef struct _bufmgr_fake { 111d722e3fbSopenharmony_ci drm_intel_bufmgr bufmgr; 112d722e3fbSopenharmony_ci 113d722e3fbSopenharmony_ci pthread_mutex_t lock; 114d722e3fbSopenharmony_ci 115d722e3fbSopenharmony_ci unsigned long low_offset; 116d722e3fbSopenharmony_ci unsigned long size; 117d722e3fbSopenharmony_ci void *virtual; 118d722e3fbSopenharmony_ci 119d722e3fbSopenharmony_ci struct mem_block *heap; 120d722e3fbSopenharmony_ci 121d722e3fbSopenharmony_ci unsigned buf_nr; /* for generating ids */ 122d722e3fbSopenharmony_ci 123d722e3fbSopenharmony_ci /** 124d722e3fbSopenharmony_ci * List of blocks which are currently in the GART but haven't been 125d722e3fbSopenharmony_ci * fenced yet. 126d722e3fbSopenharmony_ci */ 127d722e3fbSopenharmony_ci struct block on_hardware; 128d722e3fbSopenharmony_ci /** 129d722e3fbSopenharmony_ci * List of blocks which are in the GART and have an active fence on 130d722e3fbSopenharmony_ci * them. 131d722e3fbSopenharmony_ci */ 132d722e3fbSopenharmony_ci struct block fenced; 133d722e3fbSopenharmony_ci /** 134d722e3fbSopenharmony_ci * List of blocks which have an expired fence and are ready to be 135d722e3fbSopenharmony_ci * evicted. 136d722e3fbSopenharmony_ci */ 137d722e3fbSopenharmony_ci struct block lru; 138d722e3fbSopenharmony_ci 139d722e3fbSopenharmony_ci unsigned int last_fence; 140d722e3fbSopenharmony_ci 141d722e3fbSopenharmony_ci unsigned fail:1; 142d722e3fbSopenharmony_ci unsigned need_fence:1; 143d722e3fbSopenharmony_ci int thrashing; 144d722e3fbSopenharmony_ci 145d722e3fbSopenharmony_ci /** 146d722e3fbSopenharmony_ci * Driver callback to emit a fence, returning the cookie. 147d722e3fbSopenharmony_ci * 148d722e3fbSopenharmony_ci * This allows the driver to hook in a replacement for the DRM usage in 149d722e3fbSopenharmony_ci * bufmgr_fake. 150d722e3fbSopenharmony_ci * 151d722e3fbSopenharmony_ci * Currently, this also requires that a write flush be emitted before 152d722e3fbSopenharmony_ci * emitting the fence, but this should change. 153d722e3fbSopenharmony_ci */ 154d722e3fbSopenharmony_ci unsigned int (*fence_emit) (void *private); 155d722e3fbSopenharmony_ci /** Driver callback to wait for a fence cookie to have passed. */ 156d722e3fbSopenharmony_ci void (*fence_wait) (unsigned int fence, void *private); 157d722e3fbSopenharmony_ci void *fence_priv; 158d722e3fbSopenharmony_ci 159d722e3fbSopenharmony_ci /** 160d722e3fbSopenharmony_ci * Driver callback to execute a buffer. 161d722e3fbSopenharmony_ci * 162d722e3fbSopenharmony_ci * This allows the driver to hook in a replacement for the DRM usage in 163d722e3fbSopenharmony_ci * bufmgr_fake. 164d722e3fbSopenharmony_ci */ 165d722e3fbSopenharmony_ci int (*exec) (drm_intel_bo *bo, unsigned int used, void *priv); 166d722e3fbSopenharmony_ci void *exec_priv; 167d722e3fbSopenharmony_ci 168d722e3fbSopenharmony_ci /** Driver-supplied argument to driver callbacks */ 169d722e3fbSopenharmony_ci void *driver_priv; 170d722e3fbSopenharmony_ci /** 171d722e3fbSopenharmony_ci * Pointer to kernel-updated sarea data for the last completed user irq 172d722e3fbSopenharmony_ci */ 173d722e3fbSopenharmony_ci volatile int *last_dispatch; 174d722e3fbSopenharmony_ci 175d722e3fbSopenharmony_ci int fd; 176d722e3fbSopenharmony_ci 177d722e3fbSopenharmony_ci int debug; 178d722e3fbSopenharmony_ci 179d722e3fbSopenharmony_ci int performed_rendering; 180d722e3fbSopenharmony_ci} drm_intel_bufmgr_fake; 181d722e3fbSopenharmony_ci 182d722e3fbSopenharmony_citypedef struct _drm_intel_bo_fake { 183d722e3fbSopenharmony_ci drm_intel_bo bo; 184d722e3fbSopenharmony_ci 185d722e3fbSopenharmony_ci unsigned id; /* debug only */ 186d722e3fbSopenharmony_ci const char *name; 187d722e3fbSopenharmony_ci 188d722e3fbSopenharmony_ci unsigned dirty:1; 189d722e3fbSopenharmony_ci /** 190d722e3fbSopenharmony_ci * has the card written to this buffer - we make need to copy it back 191d722e3fbSopenharmony_ci */ 192d722e3fbSopenharmony_ci unsigned card_dirty:1; 193d722e3fbSopenharmony_ci unsigned int refcount; 194d722e3fbSopenharmony_ci /* Flags may consist of any of the DRM_BO flags, plus 195d722e3fbSopenharmony_ci * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the 196d722e3fbSopenharmony_ci * first two driver private flags. 197d722e3fbSopenharmony_ci */ 198d722e3fbSopenharmony_ci uint64_t flags; 199d722e3fbSopenharmony_ci /** Cache domains the target buffer is read into. */ 200d722e3fbSopenharmony_ci uint32_t read_domains; 201d722e3fbSopenharmony_ci /** Cache domain the target buffer will have dirty cachelines in. */ 202d722e3fbSopenharmony_ci uint32_t write_domain; 203d722e3fbSopenharmony_ci 204d722e3fbSopenharmony_ci unsigned int alignment; 205d722e3fbSopenharmony_ci int is_static, validated; 206d722e3fbSopenharmony_ci unsigned int map_count; 207d722e3fbSopenharmony_ci 208d722e3fbSopenharmony_ci /** relocation list */ 209d722e3fbSopenharmony_ci struct fake_buffer_reloc *relocs; 210d722e3fbSopenharmony_ci int nr_relocs; 211d722e3fbSopenharmony_ci /** 212d722e3fbSopenharmony_ci * Total size of the target_bos of this buffer. 213d722e3fbSopenharmony_ci * 214d722e3fbSopenharmony_ci * Used for estimation in check_aperture. 215d722e3fbSopenharmony_ci */ 216d722e3fbSopenharmony_ci unsigned int child_size; 217d722e3fbSopenharmony_ci 218d722e3fbSopenharmony_ci struct block *block; 219d722e3fbSopenharmony_ci void *backing_store; 220d722e3fbSopenharmony_ci void (*invalidate_cb) (drm_intel_bo *bo, void *ptr); 221d722e3fbSopenharmony_ci void *invalidate_ptr; 222d722e3fbSopenharmony_ci} drm_intel_bo_fake; 223d722e3fbSopenharmony_ci 224d722e3fbSopenharmony_cistatic int clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake, 225d722e3fbSopenharmony_ci unsigned int fence_cookie); 226d722e3fbSopenharmony_ci 227d722e3fbSopenharmony_ci#define MAXFENCE 0x7fffffff 228d722e3fbSopenharmony_ci 229d722e3fbSopenharmony_cistatic int 230d722e3fbSopenharmony_ciFENCE_LTE(unsigned a, unsigned b) 231d722e3fbSopenharmony_ci{ 232d722e3fbSopenharmony_ci if (a == b) 233d722e3fbSopenharmony_ci return 1; 234d722e3fbSopenharmony_ci 235d722e3fbSopenharmony_ci if (a < b && b - a < (1 << 24)) 236d722e3fbSopenharmony_ci return 1; 237d722e3fbSopenharmony_ci 238d722e3fbSopenharmony_ci if (a > b && MAXFENCE - a + b < (1 << 24)) 239d722e3fbSopenharmony_ci return 1; 240d722e3fbSopenharmony_ci 241d722e3fbSopenharmony_ci return 0; 242d722e3fbSopenharmony_ci} 243d722e3fbSopenharmony_ci 244d722e3fbSopenharmony_cidrm_public void 245d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr, 246d722e3fbSopenharmony_ci unsigned int (*emit) (void *priv), 247d722e3fbSopenharmony_ci void (*wait) (unsigned int fence, 248d722e3fbSopenharmony_ci void *priv), 249d722e3fbSopenharmony_ci void *priv) 250d722e3fbSopenharmony_ci{ 251d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 252d722e3fbSopenharmony_ci 253d722e3fbSopenharmony_ci bufmgr_fake->fence_emit = emit; 254d722e3fbSopenharmony_ci bufmgr_fake->fence_wait = wait; 255d722e3fbSopenharmony_ci bufmgr_fake->fence_priv = priv; 256d722e3fbSopenharmony_ci} 257d722e3fbSopenharmony_ci 258d722e3fbSopenharmony_cistatic unsigned int 259d722e3fbSopenharmony_ci_fence_emit_internal(drm_intel_bufmgr_fake *bufmgr_fake) 260d722e3fbSopenharmony_ci{ 261d722e3fbSopenharmony_ci struct drm_i915_irq_emit ie; 262d722e3fbSopenharmony_ci int ret, seq = 1; 263d722e3fbSopenharmony_ci 264d722e3fbSopenharmony_ci if (bufmgr_fake->fence_emit != NULL) { 265d722e3fbSopenharmony_ci seq = bufmgr_fake->fence_emit(bufmgr_fake->fence_priv); 266d722e3fbSopenharmony_ci return seq; 267d722e3fbSopenharmony_ci } 268d722e3fbSopenharmony_ci 269d722e3fbSopenharmony_ci ie.irq_seq = &seq; 270d722e3fbSopenharmony_ci ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT, 271d722e3fbSopenharmony_ci &ie, sizeof(ie)); 272d722e3fbSopenharmony_ci if (ret) { 273d722e3fbSopenharmony_ci drmMsg("%s: drm_i915_irq_emit: %d\n", __func__, ret); 274d722e3fbSopenharmony_ci abort(); 275d722e3fbSopenharmony_ci } 276d722e3fbSopenharmony_ci 277d722e3fbSopenharmony_ci DBG("emit 0x%08x\n", seq); 278d722e3fbSopenharmony_ci return seq; 279d722e3fbSopenharmony_ci} 280d722e3fbSopenharmony_ci 281d722e3fbSopenharmony_cistatic void 282d722e3fbSopenharmony_ci_fence_wait_internal(drm_intel_bufmgr_fake *bufmgr_fake, int seq) 283d722e3fbSopenharmony_ci{ 284d722e3fbSopenharmony_ci struct drm_i915_irq_wait iw; 285d722e3fbSopenharmony_ci int hw_seq, busy_count = 0; 286d722e3fbSopenharmony_ci int ret; 287d722e3fbSopenharmony_ci int kernel_lied; 288d722e3fbSopenharmony_ci 289d722e3fbSopenharmony_ci if (bufmgr_fake->fence_wait != NULL) { 290d722e3fbSopenharmony_ci bufmgr_fake->fence_wait(seq, bufmgr_fake->fence_priv); 291d722e3fbSopenharmony_ci clear_fenced(bufmgr_fake, seq); 292d722e3fbSopenharmony_ci return; 293d722e3fbSopenharmony_ci } 294d722e3fbSopenharmony_ci 295d722e3fbSopenharmony_ci iw.irq_seq = seq; 296d722e3fbSopenharmony_ci 297d722e3fbSopenharmony_ci DBG("wait 0x%08x\n", iw.irq_seq); 298d722e3fbSopenharmony_ci 299d722e3fbSopenharmony_ci /* The kernel IRQ_WAIT implementation is all sorts of broken. 300d722e3fbSopenharmony_ci * 1) It returns 1 to 0x7fffffff instead of using the full 32-bit 301d722e3fbSopenharmony_ci * unsigned range. 302d722e3fbSopenharmony_ci * 2) It returns 0 if hw_seq >= seq, not seq - hw_seq < 0 on the 32-bit 303d722e3fbSopenharmony_ci * signed range. 304d722e3fbSopenharmony_ci * 3) It waits if seq < hw_seq, not seq - hw_seq > 0 on the 32-bit 305d722e3fbSopenharmony_ci * signed range. 306d722e3fbSopenharmony_ci * 4) It returns -EBUSY in 3 seconds even if the hardware is still 307d722e3fbSopenharmony_ci * successfully chewing through buffers. 308d722e3fbSopenharmony_ci * 309d722e3fbSopenharmony_ci * Assume that in userland we treat sequence numbers as ints, which 310d722e3fbSopenharmony_ci * makes some of the comparisons convenient, since the sequence 311d722e3fbSopenharmony_ci * numbers are all positive signed integers. 312d722e3fbSopenharmony_ci * 313d722e3fbSopenharmony_ci * From this we get several cases we need to handle. Here's a timeline. 314d722e3fbSopenharmony_ci * 0x2 0x7 0x7ffffff8 0x7ffffffd 315d722e3fbSopenharmony_ci * | | | | 316d722e3fbSopenharmony_ci * ------------------------------------------------------------ 317d722e3fbSopenharmony_ci * 318d722e3fbSopenharmony_ci * A) Normal wait for hw to catch up 319d722e3fbSopenharmony_ci * hw_seq seq 320d722e3fbSopenharmony_ci * | | 321d722e3fbSopenharmony_ci * ------------------------------------------------------------ 322d722e3fbSopenharmony_ci * seq - hw_seq = 5. If we call IRQ_WAIT, it will wait for hw to 323d722e3fbSopenharmony_ci * catch up. 324d722e3fbSopenharmony_ci * 325d722e3fbSopenharmony_ci * B) Normal wait for a sequence number that's already passed. 326d722e3fbSopenharmony_ci * seq hw_seq 327d722e3fbSopenharmony_ci * | | 328d722e3fbSopenharmony_ci * ------------------------------------------------------------ 329d722e3fbSopenharmony_ci * seq - hw_seq = -5. If we call IRQ_WAIT, it returns 0 quickly. 330d722e3fbSopenharmony_ci * 331d722e3fbSopenharmony_ci * C) Hardware has already wrapped around ahead of us 332d722e3fbSopenharmony_ci * hw_seq seq 333d722e3fbSopenharmony_ci * | | 334d722e3fbSopenharmony_ci * ------------------------------------------------------------ 335d722e3fbSopenharmony_ci * seq - hw_seq = 0x80000000 - 5. If we called IRQ_WAIT, it would wait 336d722e3fbSopenharmony_ci * for hw_seq >= seq, which may never occur. Thus, we want to catch 337d722e3fbSopenharmony_ci * this in userland and return 0. 338d722e3fbSopenharmony_ci * 339d722e3fbSopenharmony_ci * D) We've wrapped around ahead of the hardware. 340d722e3fbSopenharmony_ci * seq hw_seq 341d722e3fbSopenharmony_ci * | | 342d722e3fbSopenharmony_ci * ------------------------------------------------------------ 343d722e3fbSopenharmony_ci * seq - hw_seq = -(0x80000000 - 5). If we called IRQ_WAIT, it would 344d722e3fbSopenharmony_ci * return 0 quickly because hw_seq >= seq, even though the hardware 345d722e3fbSopenharmony_ci * isn't caught up. Thus, we need to catch this early return in 346d722e3fbSopenharmony_ci * userland and bother the kernel until the hardware really does 347d722e3fbSopenharmony_ci * catch up. 348d722e3fbSopenharmony_ci * 349d722e3fbSopenharmony_ci * E) Hardware might wrap after we test in userland. 350d722e3fbSopenharmony_ci * hw_seq seq 351d722e3fbSopenharmony_ci * | | 352d722e3fbSopenharmony_ci * ------------------------------------------------------------ 353d722e3fbSopenharmony_ci * seq - hw_seq = 5. If we call IRQ_WAIT, it will likely see seq >= 354d722e3fbSopenharmony_ci * hw_seq and wait. However, suppose hw_seq wraps before we make it 355d722e3fbSopenharmony_ci * into the kernel. The kernel sees hw_seq >= seq and waits for 3 356d722e3fbSopenharmony_ci * seconds then returns -EBUSY. This is case C). We should catch 357d722e3fbSopenharmony_ci * this and then return successfully. 358d722e3fbSopenharmony_ci * 359d722e3fbSopenharmony_ci * F) Hardware might take a long time on a buffer. 360d722e3fbSopenharmony_ci * hw_seq seq 361d722e3fbSopenharmony_ci * | | 362d722e3fbSopenharmony_ci * ------------------------------------------------------------------- 363d722e3fbSopenharmony_ci * seq - hw_seq = 5. If we call IRQ_WAIT, if sequence 2 through 5 364d722e3fbSopenharmony_ci * take too long, it will return -EBUSY. Batchbuffers in the 365d722e3fbSopenharmony_ci * gltestperf demo were seen to take up to 7 seconds. We should 366d722e3fbSopenharmony_ci * catch early -EBUSY return and keep trying. 367d722e3fbSopenharmony_ci */ 368d722e3fbSopenharmony_ci 369d722e3fbSopenharmony_ci do { 370d722e3fbSopenharmony_ci /* Keep a copy of last_dispatch so that if the wait -EBUSYs 371d722e3fbSopenharmony_ci * because the hardware didn't catch up in 3 seconds, we can 372d722e3fbSopenharmony_ci * see if it at least made progress and retry. 373d722e3fbSopenharmony_ci */ 374d722e3fbSopenharmony_ci hw_seq = *bufmgr_fake->last_dispatch; 375d722e3fbSopenharmony_ci 376d722e3fbSopenharmony_ci /* Catch case C */ 377d722e3fbSopenharmony_ci if (seq - hw_seq > 0x40000000) 378d722e3fbSopenharmony_ci return; 379d722e3fbSopenharmony_ci 380d722e3fbSopenharmony_ci ret = drmCommandWrite(bufmgr_fake->fd, DRM_I915_IRQ_WAIT, 381d722e3fbSopenharmony_ci &iw, sizeof(iw)); 382d722e3fbSopenharmony_ci /* Catch case D */ 383d722e3fbSopenharmony_ci kernel_lied = (ret == 0) && (seq - *bufmgr_fake->last_dispatch < 384d722e3fbSopenharmony_ci -0x40000000); 385d722e3fbSopenharmony_ci 386d722e3fbSopenharmony_ci /* Catch case E */ 387d722e3fbSopenharmony_ci if (ret == -EBUSY 388d722e3fbSopenharmony_ci && (seq - *bufmgr_fake->last_dispatch > 0x40000000)) 389d722e3fbSopenharmony_ci ret = 0; 390d722e3fbSopenharmony_ci 391d722e3fbSopenharmony_ci /* Catch case F: Allow up to 15 seconds chewing on one buffer. */ 392d722e3fbSopenharmony_ci if ((ret == -EBUSY) && (hw_seq != *bufmgr_fake->last_dispatch)) 393d722e3fbSopenharmony_ci busy_count = 0; 394d722e3fbSopenharmony_ci else 395d722e3fbSopenharmony_ci busy_count++; 396d722e3fbSopenharmony_ci } while (kernel_lied || ret == -EAGAIN || ret == -EINTR || 397d722e3fbSopenharmony_ci (ret == -EBUSY && busy_count < 5)); 398d722e3fbSopenharmony_ci 399d722e3fbSopenharmony_ci if (ret != 0) { 400d722e3fbSopenharmony_ci drmMsg("%s:%d: Error waiting for fence: %s.\n", __FILE__, 401d722e3fbSopenharmony_ci __LINE__, strerror(-ret)); 402d722e3fbSopenharmony_ci abort(); 403d722e3fbSopenharmony_ci } 404d722e3fbSopenharmony_ci clear_fenced(bufmgr_fake, seq); 405d722e3fbSopenharmony_ci} 406d722e3fbSopenharmony_ci 407d722e3fbSopenharmony_cistatic int 408d722e3fbSopenharmony_ci_fence_test(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence) 409d722e3fbSopenharmony_ci{ 410d722e3fbSopenharmony_ci /* Slight problem with wrap-around: 411d722e3fbSopenharmony_ci */ 412d722e3fbSopenharmony_ci return fence == 0 || FENCE_LTE(fence, bufmgr_fake->last_fence); 413d722e3fbSopenharmony_ci} 414d722e3fbSopenharmony_ci 415d722e3fbSopenharmony_ci/** 416d722e3fbSopenharmony_ci * Allocate a memory manager block for the buffer. 417d722e3fbSopenharmony_ci */ 418d722e3fbSopenharmony_cistatic int 419d722e3fbSopenharmony_cialloc_block(drm_intel_bo *bo) 420d722e3fbSopenharmony_ci{ 421d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 422d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 423d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 424d722e3fbSopenharmony_ci struct block *block = (struct block *)calloc(sizeof *block, 1); 425d722e3fbSopenharmony_ci unsigned int align_log2 = ffs(bo_fake->alignment) - 1; 426d722e3fbSopenharmony_ci unsigned int sz; 427d722e3fbSopenharmony_ci 428d722e3fbSopenharmony_ci if (!block) 429d722e3fbSopenharmony_ci return 1; 430d722e3fbSopenharmony_ci 431d722e3fbSopenharmony_ci sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1); 432d722e3fbSopenharmony_ci 433d722e3fbSopenharmony_ci block->mem = mmAllocMem(bufmgr_fake->heap, sz, align_log2, 0); 434d722e3fbSopenharmony_ci if (!block->mem) { 435d722e3fbSopenharmony_ci free(block); 436d722e3fbSopenharmony_ci return 0; 437d722e3fbSopenharmony_ci } 438d722e3fbSopenharmony_ci 439d722e3fbSopenharmony_ci DRMINITLISTHEAD(block); 440d722e3fbSopenharmony_ci 441d722e3fbSopenharmony_ci /* Insert at head or at tail??? */ 442d722e3fbSopenharmony_ci DRMLISTADDTAIL(block, &bufmgr_fake->lru); 443d722e3fbSopenharmony_ci 444d722e3fbSopenharmony_ci block->virtual = (uint8_t *) bufmgr_fake->virtual + 445d722e3fbSopenharmony_ci block->mem->ofs - bufmgr_fake->low_offset; 446d722e3fbSopenharmony_ci block->bo = bo; 447d722e3fbSopenharmony_ci 448d722e3fbSopenharmony_ci bo_fake->block = block; 449d722e3fbSopenharmony_ci 450d722e3fbSopenharmony_ci return 1; 451d722e3fbSopenharmony_ci} 452d722e3fbSopenharmony_ci 453d722e3fbSopenharmony_ci/* Release the card storage associated with buf: 454d722e3fbSopenharmony_ci */ 455d722e3fbSopenharmony_cistatic void 456d722e3fbSopenharmony_cifree_block(drm_intel_bufmgr_fake *bufmgr_fake, struct block *block, 457d722e3fbSopenharmony_ci int skip_dirty_copy) 458d722e3fbSopenharmony_ci{ 459d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake; 460d722e3fbSopenharmony_ci DBG("free block %p %08x %d %d\n", block, block->mem->ofs, 461d722e3fbSopenharmony_ci block->on_hardware, block->fenced); 462d722e3fbSopenharmony_ci 463d722e3fbSopenharmony_ci if (!block) 464d722e3fbSopenharmony_ci return; 465d722e3fbSopenharmony_ci 466d722e3fbSopenharmony_ci bo_fake = (drm_intel_bo_fake *) block->bo; 467d722e3fbSopenharmony_ci 468d722e3fbSopenharmony_ci if (bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)) 469d722e3fbSopenharmony_ci skip_dirty_copy = 1; 470d722e3fbSopenharmony_ci 471d722e3fbSopenharmony_ci if (!skip_dirty_copy && (bo_fake->card_dirty == 1)) { 472d722e3fbSopenharmony_ci memcpy(bo_fake->backing_store, block->virtual, block->bo->size); 473d722e3fbSopenharmony_ci bo_fake->card_dirty = 0; 474d722e3fbSopenharmony_ci bo_fake->dirty = 1; 475d722e3fbSopenharmony_ci } 476d722e3fbSopenharmony_ci 477d722e3fbSopenharmony_ci if (block->on_hardware) { 478d722e3fbSopenharmony_ci block->bo = NULL; 479d722e3fbSopenharmony_ci } else if (block->fenced) { 480d722e3fbSopenharmony_ci block->bo = NULL; 481d722e3fbSopenharmony_ci } else { 482d722e3fbSopenharmony_ci DBG(" - free immediately\n"); 483d722e3fbSopenharmony_ci DRMLISTDEL(block); 484d722e3fbSopenharmony_ci 485d722e3fbSopenharmony_ci mmFreeMem(block->mem); 486d722e3fbSopenharmony_ci free(block); 487d722e3fbSopenharmony_ci } 488d722e3fbSopenharmony_ci} 489d722e3fbSopenharmony_ci 490d722e3fbSopenharmony_cistatic void 491d722e3fbSopenharmony_cialloc_backing_store(drm_intel_bo *bo) 492d722e3fbSopenharmony_ci{ 493d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 494d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 495d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 496d722e3fbSopenharmony_ci assert(!bo_fake->backing_store); 497d722e3fbSopenharmony_ci assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE))); 498d722e3fbSopenharmony_ci 499d722e3fbSopenharmony_ci bo_fake->backing_store = malloc(bo->size); 500d722e3fbSopenharmony_ci 501d722e3fbSopenharmony_ci DBG("alloc_backing - buf %d %p %lu\n", bo_fake->id, 502d722e3fbSopenharmony_ci bo_fake->backing_store, bo->size); 503d722e3fbSopenharmony_ci assert(bo_fake->backing_store); 504d722e3fbSopenharmony_ci} 505d722e3fbSopenharmony_ci 506d722e3fbSopenharmony_cistatic void 507d722e3fbSopenharmony_cifree_backing_store(drm_intel_bo *bo) 508d722e3fbSopenharmony_ci{ 509d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 510d722e3fbSopenharmony_ci 511d722e3fbSopenharmony_ci if (bo_fake->backing_store) { 512d722e3fbSopenharmony_ci assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE))); 513d722e3fbSopenharmony_ci free(bo_fake->backing_store); 514d722e3fbSopenharmony_ci bo_fake->backing_store = NULL; 515d722e3fbSopenharmony_ci } 516d722e3fbSopenharmony_ci} 517d722e3fbSopenharmony_ci 518d722e3fbSopenharmony_cistatic void 519d722e3fbSopenharmony_ciset_dirty(drm_intel_bo *bo) 520d722e3fbSopenharmony_ci{ 521d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 522d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 523d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 524d722e3fbSopenharmony_ci 525d722e3fbSopenharmony_ci if (bo_fake->flags & BM_NO_BACKING_STORE 526d722e3fbSopenharmony_ci && bo_fake->invalidate_cb != NULL) 527d722e3fbSopenharmony_ci bo_fake->invalidate_cb(bo, bo_fake->invalidate_ptr); 528d722e3fbSopenharmony_ci 529d722e3fbSopenharmony_ci assert(!(bo_fake->flags & BM_PINNED)); 530d722e3fbSopenharmony_ci 531d722e3fbSopenharmony_ci DBG("set_dirty - buf %d\n", bo_fake->id); 532d722e3fbSopenharmony_ci bo_fake->dirty = 1; 533d722e3fbSopenharmony_ci} 534d722e3fbSopenharmony_ci 535d722e3fbSopenharmony_cistatic int 536d722e3fbSopenharmony_cievict_lru(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int max_fence) 537d722e3fbSopenharmony_ci{ 538d722e3fbSopenharmony_ci struct block *block, *tmp; 539d722e3fbSopenharmony_ci 540d722e3fbSopenharmony_ci DBG("%s\n", __func__); 541d722e3fbSopenharmony_ci 542d722e3fbSopenharmony_ci DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { 543d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 544d722e3fbSopenharmony_ci 545d722e3fbSopenharmony_ci if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA)) 546d722e3fbSopenharmony_ci continue; 547d722e3fbSopenharmony_ci 548d722e3fbSopenharmony_ci if (block->fence && max_fence && !FENCE_LTE(block->fence, 549d722e3fbSopenharmony_ci max_fence)) 550d722e3fbSopenharmony_ci return 0; 551d722e3fbSopenharmony_ci 552d722e3fbSopenharmony_ci set_dirty(&bo_fake->bo); 553d722e3fbSopenharmony_ci bo_fake->block = NULL; 554d722e3fbSopenharmony_ci 555d722e3fbSopenharmony_ci free_block(bufmgr_fake, block, 0); 556d722e3fbSopenharmony_ci return 1; 557d722e3fbSopenharmony_ci } 558d722e3fbSopenharmony_ci 559d722e3fbSopenharmony_ci return 0; 560d722e3fbSopenharmony_ci} 561d722e3fbSopenharmony_ci 562d722e3fbSopenharmony_cistatic int 563d722e3fbSopenharmony_cievict_mru(drm_intel_bufmgr_fake *bufmgr_fake) 564d722e3fbSopenharmony_ci{ 565d722e3fbSopenharmony_ci struct block *block, *tmp; 566d722e3fbSopenharmony_ci 567d722e3fbSopenharmony_ci DBG("%s\n", __func__); 568d722e3fbSopenharmony_ci 569d722e3fbSopenharmony_ci DRMLISTFOREACHSAFEREVERSE(block, tmp, &bufmgr_fake->lru) { 570d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 571d722e3fbSopenharmony_ci 572d722e3fbSopenharmony_ci if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA)) 573d722e3fbSopenharmony_ci continue; 574d722e3fbSopenharmony_ci 575d722e3fbSopenharmony_ci set_dirty(&bo_fake->bo); 576d722e3fbSopenharmony_ci bo_fake->block = NULL; 577d722e3fbSopenharmony_ci 578d722e3fbSopenharmony_ci free_block(bufmgr_fake, block, 0); 579d722e3fbSopenharmony_ci return 1; 580d722e3fbSopenharmony_ci } 581d722e3fbSopenharmony_ci 582d722e3fbSopenharmony_ci return 0; 583d722e3fbSopenharmony_ci} 584d722e3fbSopenharmony_ci 585d722e3fbSopenharmony_ci/** 586d722e3fbSopenharmony_ci * Removes all objects from the fenced list older than the given fence. 587d722e3fbSopenharmony_ci */ 588d722e3fbSopenharmony_cistatic int 589d722e3fbSopenharmony_ciclear_fenced(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int fence_cookie) 590d722e3fbSopenharmony_ci{ 591d722e3fbSopenharmony_ci struct block *block, *tmp; 592d722e3fbSopenharmony_ci int ret = 0; 593d722e3fbSopenharmony_ci 594d722e3fbSopenharmony_ci bufmgr_fake->last_fence = fence_cookie; 595d722e3fbSopenharmony_ci DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->fenced) { 596d722e3fbSopenharmony_ci assert(block->fenced); 597d722e3fbSopenharmony_ci 598d722e3fbSopenharmony_ci if (_fence_test(bufmgr_fake, block->fence)) { 599d722e3fbSopenharmony_ci 600d722e3fbSopenharmony_ci block->fenced = 0; 601d722e3fbSopenharmony_ci 602d722e3fbSopenharmony_ci if (!block->bo) { 603d722e3fbSopenharmony_ci DBG("delayed free: offset %x sz %x\n", 604d722e3fbSopenharmony_ci block->mem->ofs, block->mem->size); 605d722e3fbSopenharmony_ci DRMLISTDEL(block); 606d722e3fbSopenharmony_ci mmFreeMem(block->mem); 607d722e3fbSopenharmony_ci free(block); 608d722e3fbSopenharmony_ci } else { 609d722e3fbSopenharmony_ci DBG("return to lru: offset %x sz %x\n", 610d722e3fbSopenharmony_ci block->mem->ofs, block->mem->size); 611d722e3fbSopenharmony_ci DRMLISTDEL(block); 612d722e3fbSopenharmony_ci DRMLISTADDTAIL(block, &bufmgr_fake->lru); 613d722e3fbSopenharmony_ci } 614d722e3fbSopenharmony_ci 615d722e3fbSopenharmony_ci ret = 1; 616d722e3fbSopenharmony_ci } else { 617d722e3fbSopenharmony_ci /* Blocks are ordered by fence, so if one fails, all 618d722e3fbSopenharmony_ci * from here will fail also: 619d722e3fbSopenharmony_ci */ 620d722e3fbSopenharmony_ci DBG("fence not passed: offset %x sz %x %d %d \n", 621d722e3fbSopenharmony_ci block->mem->ofs, block->mem->size, block->fence, 622d722e3fbSopenharmony_ci bufmgr_fake->last_fence); 623d722e3fbSopenharmony_ci break; 624d722e3fbSopenharmony_ci } 625d722e3fbSopenharmony_ci } 626d722e3fbSopenharmony_ci 627d722e3fbSopenharmony_ci DBG("%s: %d\n", __func__, ret); 628d722e3fbSopenharmony_ci return ret; 629d722e3fbSopenharmony_ci} 630d722e3fbSopenharmony_ci 631d722e3fbSopenharmony_cistatic void 632d722e3fbSopenharmony_cifence_blocks(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence) 633d722e3fbSopenharmony_ci{ 634d722e3fbSopenharmony_ci struct block *block, *tmp; 635d722e3fbSopenharmony_ci 636d722e3fbSopenharmony_ci DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) { 637d722e3fbSopenharmony_ci DBG("Fence block %p (sz 0x%x ofs %x buf %p) with fence %d\n", 638d722e3fbSopenharmony_ci block, block->mem->size, block->mem->ofs, block->bo, fence); 639d722e3fbSopenharmony_ci block->fence = fence; 640d722e3fbSopenharmony_ci 641d722e3fbSopenharmony_ci block->on_hardware = 0; 642d722e3fbSopenharmony_ci block->fenced = 1; 643d722e3fbSopenharmony_ci 644d722e3fbSopenharmony_ci /* Move to tail of pending list here 645d722e3fbSopenharmony_ci */ 646d722e3fbSopenharmony_ci DRMLISTDEL(block); 647d722e3fbSopenharmony_ci DRMLISTADDTAIL(block, &bufmgr_fake->fenced); 648d722e3fbSopenharmony_ci } 649d722e3fbSopenharmony_ci 650d722e3fbSopenharmony_ci assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware)); 651d722e3fbSopenharmony_ci} 652d722e3fbSopenharmony_ci 653d722e3fbSopenharmony_cistatic int 654d722e3fbSopenharmony_cievict_and_alloc_block(drm_intel_bo *bo) 655d722e3fbSopenharmony_ci{ 656d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 657d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 658d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 659d722e3fbSopenharmony_ci 660d722e3fbSopenharmony_ci assert(bo_fake->block == NULL); 661d722e3fbSopenharmony_ci 662d722e3fbSopenharmony_ci /* Search for already free memory: 663d722e3fbSopenharmony_ci */ 664d722e3fbSopenharmony_ci if (alloc_block(bo)) 665d722e3fbSopenharmony_ci return 1; 666d722e3fbSopenharmony_ci 667d722e3fbSopenharmony_ci /* If we're not thrashing, allow lru eviction to dig deeper into 668d722e3fbSopenharmony_ci * recently used textures. We'll probably be thrashing soon: 669d722e3fbSopenharmony_ci */ 670d722e3fbSopenharmony_ci if (!bufmgr_fake->thrashing) { 671d722e3fbSopenharmony_ci while (evict_lru(bufmgr_fake, 0)) 672d722e3fbSopenharmony_ci if (alloc_block(bo)) 673d722e3fbSopenharmony_ci return 1; 674d722e3fbSopenharmony_ci } 675d722e3fbSopenharmony_ci 676d722e3fbSopenharmony_ci /* Keep thrashing counter alive? 677d722e3fbSopenharmony_ci */ 678d722e3fbSopenharmony_ci if (bufmgr_fake->thrashing) 679d722e3fbSopenharmony_ci bufmgr_fake->thrashing = 20; 680d722e3fbSopenharmony_ci 681d722e3fbSopenharmony_ci /* Wait on any already pending fences - here we are waiting for any 682d722e3fbSopenharmony_ci * freed memory that has been submitted to hardware and fenced to 683d722e3fbSopenharmony_ci * become available: 684d722e3fbSopenharmony_ci */ 685d722e3fbSopenharmony_ci while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) { 686d722e3fbSopenharmony_ci uint32_t fence = bufmgr_fake->fenced.next->fence; 687d722e3fbSopenharmony_ci _fence_wait_internal(bufmgr_fake, fence); 688d722e3fbSopenharmony_ci 689d722e3fbSopenharmony_ci if (alloc_block(bo)) 690d722e3fbSopenharmony_ci return 1; 691d722e3fbSopenharmony_ci } 692d722e3fbSopenharmony_ci 693d722e3fbSopenharmony_ci if (!DRMLISTEMPTY(&bufmgr_fake->on_hardware)) { 694d722e3fbSopenharmony_ci while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) { 695d722e3fbSopenharmony_ci uint32_t fence = bufmgr_fake->fenced.next->fence; 696d722e3fbSopenharmony_ci _fence_wait_internal(bufmgr_fake, fence); 697d722e3fbSopenharmony_ci } 698d722e3fbSopenharmony_ci 699d722e3fbSopenharmony_ci if (!bufmgr_fake->thrashing) { 700d722e3fbSopenharmony_ci DBG("thrashing\n"); 701d722e3fbSopenharmony_ci } 702d722e3fbSopenharmony_ci bufmgr_fake->thrashing = 20; 703d722e3fbSopenharmony_ci 704d722e3fbSopenharmony_ci if (alloc_block(bo)) 705d722e3fbSopenharmony_ci return 1; 706d722e3fbSopenharmony_ci } 707d722e3fbSopenharmony_ci 708d722e3fbSopenharmony_ci while (evict_mru(bufmgr_fake)) 709d722e3fbSopenharmony_ci if (alloc_block(bo)) 710d722e3fbSopenharmony_ci return 1; 711d722e3fbSopenharmony_ci 712d722e3fbSopenharmony_ci DBG("%s 0x%lx bytes failed\n", __func__, bo->size); 713d722e3fbSopenharmony_ci 714d722e3fbSopenharmony_ci return 0; 715d722e3fbSopenharmony_ci} 716d722e3fbSopenharmony_ci 717d722e3fbSopenharmony_ci/*********************************************************************** 718d722e3fbSopenharmony_ci * Public functions 719d722e3fbSopenharmony_ci */ 720d722e3fbSopenharmony_ci 721d722e3fbSopenharmony_ci/** 722d722e3fbSopenharmony_ci * Wait for hardware idle by emitting a fence and waiting for it. 723d722e3fbSopenharmony_ci */ 724d722e3fbSopenharmony_cistatic void 725d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_wait_idle(drm_intel_bufmgr_fake *bufmgr_fake) 726d722e3fbSopenharmony_ci{ 727d722e3fbSopenharmony_ci unsigned int cookie; 728d722e3fbSopenharmony_ci 729d722e3fbSopenharmony_ci cookie = _fence_emit_internal(bufmgr_fake); 730d722e3fbSopenharmony_ci _fence_wait_internal(bufmgr_fake, cookie); 731d722e3fbSopenharmony_ci} 732d722e3fbSopenharmony_ci 733d722e3fbSopenharmony_ci/** 734d722e3fbSopenharmony_ci * Wait for rendering to a buffer to complete. 735d722e3fbSopenharmony_ci * 736d722e3fbSopenharmony_ci * It is assumed that the batchbuffer which performed the rendering included 737d722e3fbSopenharmony_ci * the necessary flushing. 738d722e3fbSopenharmony_ci */ 739d722e3fbSopenharmony_cistatic void 740d722e3fbSopenharmony_cidrm_intel_fake_bo_wait_rendering_locked(drm_intel_bo *bo) 741d722e3fbSopenharmony_ci{ 742d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 743d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 744d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 745d722e3fbSopenharmony_ci 746d722e3fbSopenharmony_ci if (bo_fake->block == NULL || !bo_fake->block->fenced) 747d722e3fbSopenharmony_ci return; 748d722e3fbSopenharmony_ci 749d722e3fbSopenharmony_ci _fence_wait_internal(bufmgr_fake, bo_fake->block->fence); 750d722e3fbSopenharmony_ci} 751d722e3fbSopenharmony_ci 752d722e3fbSopenharmony_cistatic void 753d722e3fbSopenharmony_cidrm_intel_fake_bo_wait_rendering(drm_intel_bo *bo) 754d722e3fbSopenharmony_ci{ 755d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 756d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 757d722e3fbSopenharmony_ci 758d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 759d722e3fbSopenharmony_ci drm_intel_fake_bo_wait_rendering_locked(bo); 760d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 761d722e3fbSopenharmony_ci} 762d722e3fbSopenharmony_ci 763d722e3fbSopenharmony_ci/* Specifically ignore texture memory sharing. 764d722e3fbSopenharmony_ci * -- just evict everything 765d722e3fbSopenharmony_ci * -- and wait for idle 766d722e3fbSopenharmony_ci */ 767d722e3fbSopenharmony_cidrm_public void 768d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr) 769d722e3fbSopenharmony_ci{ 770d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 771d722e3fbSopenharmony_ci struct block *block, *tmp; 772d722e3fbSopenharmony_ci 773d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 774d722e3fbSopenharmony_ci 775d722e3fbSopenharmony_ci bufmgr_fake->need_fence = 1; 776d722e3fbSopenharmony_ci bufmgr_fake->fail = 0; 777d722e3fbSopenharmony_ci 778d722e3fbSopenharmony_ci /* Wait for hardware idle. We don't know where acceleration has been 779d722e3fbSopenharmony_ci * happening, so we'll need to wait anyway before letting anything get 780d722e3fbSopenharmony_ci * put on the card again. 781d722e3fbSopenharmony_ci */ 782d722e3fbSopenharmony_ci drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 783d722e3fbSopenharmony_ci 784d722e3fbSopenharmony_ci /* Check that we hadn't released the lock without having fenced the last 785d722e3fbSopenharmony_ci * set of buffers. 786d722e3fbSopenharmony_ci */ 787d722e3fbSopenharmony_ci assert(DRMLISTEMPTY(&bufmgr_fake->fenced)); 788d722e3fbSopenharmony_ci assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware)); 789d722e3fbSopenharmony_ci 790d722e3fbSopenharmony_ci DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { 791d722e3fbSopenharmony_ci assert(_fence_test(bufmgr_fake, block->fence)); 792d722e3fbSopenharmony_ci set_dirty(block->bo); 793d722e3fbSopenharmony_ci } 794d722e3fbSopenharmony_ci 795d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 796d722e3fbSopenharmony_ci} 797d722e3fbSopenharmony_ci 798d722e3fbSopenharmony_cistatic drm_intel_bo * 799d722e3fbSopenharmony_cidrm_intel_fake_bo_alloc(drm_intel_bufmgr *bufmgr, 800d722e3fbSopenharmony_ci const char *name, 801d722e3fbSopenharmony_ci unsigned long size, 802d722e3fbSopenharmony_ci unsigned int alignment) 803d722e3fbSopenharmony_ci{ 804d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake; 805d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake; 806d722e3fbSopenharmony_ci 807d722e3fbSopenharmony_ci bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 808d722e3fbSopenharmony_ci 809d722e3fbSopenharmony_ci assert(size != 0); 810d722e3fbSopenharmony_ci 811d722e3fbSopenharmony_ci bo_fake = calloc(1, sizeof(*bo_fake)); 812d722e3fbSopenharmony_ci if (!bo_fake) 813d722e3fbSopenharmony_ci return NULL; 814d722e3fbSopenharmony_ci 815d722e3fbSopenharmony_ci bo_fake->bo.size = size; 816d722e3fbSopenharmony_ci bo_fake->bo.offset = -1; 817d722e3fbSopenharmony_ci bo_fake->bo.virtual = NULL; 818d722e3fbSopenharmony_ci bo_fake->bo.bufmgr = bufmgr; 819d722e3fbSopenharmony_ci bo_fake->refcount = 1; 820d722e3fbSopenharmony_ci 821d722e3fbSopenharmony_ci /* Alignment must be a power of two */ 822d722e3fbSopenharmony_ci assert((alignment & (alignment - 1)) == 0); 823d722e3fbSopenharmony_ci if (alignment == 0) 824d722e3fbSopenharmony_ci alignment = 1; 825d722e3fbSopenharmony_ci bo_fake->alignment = alignment; 826d722e3fbSopenharmony_ci bo_fake->id = ++bufmgr_fake->buf_nr; 827d722e3fbSopenharmony_ci bo_fake->name = name; 828d722e3fbSopenharmony_ci bo_fake->flags = 0; 829d722e3fbSopenharmony_ci bo_fake->is_static = 0; 830d722e3fbSopenharmony_ci 831d722e3fbSopenharmony_ci DBG("drm_bo_alloc: (buf %d: %s, %lu kb)\n", bo_fake->id, bo_fake->name, 832d722e3fbSopenharmony_ci bo_fake->bo.size / 1024); 833d722e3fbSopenharmony_ci 834d722e3fbSopenharmony_ci return &bo_fake->bo; 835d722e3fbSopenharmony_ci} 836d722e3fbSopenharmony_ci 837d722e3fbSopenharmony_cistatic drm_intel_bo * 838d722e3fbSopenharmony_cidrm_intel_fake_bo_alloc_tiled(drm_intel_bufmgr * bufmgr, 839d722e3fbSopenharmony_ci const char *name, 840d722e3fbSopenharmony_ci int x, int y, int cpp, 841d722e3fbSopenharmony_ci uint32_t *tiling_mode, 842d722e3fbSopenharmony_ci unsigned long *pitch, 843d722e3fbSopenharmony_ci unsigned long flags) 844d722e3fbSopenharmony_ci{ 845d722e3fbSopenharmony_ci unsigned long stride, aligned_y; 846d722e3fbSopenharmony_ci 847d722e3fbSopenharmony_ci /* No runtime tiling support for fake. */ 848d722e3fbSopenharmony_ci *tiling_mode = I915_TILING_NONE; 849d722e3fbSopenharmony_ci 850d722e3fbSopenharmony_ci /* Align it for being a render target. Shouldn't need anything else. */ 851d722e3fbSopenharmony_ci stride = x * cpp; 852d722e3fbSopenharmony_ci stride = ROUND_UP_TO(stride, 64); 853d722e3fbSopenharmony_ci 854d722e3fbSopenharmony_ci /* 965 subspan loading alignment */ 855d722e3fbSopenharmony_ci aligned_y = ALIGN(y, 2); 856d722e3fbSopenharmony_ci 857d722e3fbSopenharmony_ci *pitch = stride; 858d722e3fbSopenharmony_ci 859d722e3fbSopenharmony_ci return drm_intel_fake_bo_alloc(bufmgr, name, stride * aligned_y, 860d722e3fbSopenharmony_ci 4096); 861d722e3fbSopenharmony_ci} 862d722e3fbSopenharmony_ci 863d722e3fbSopenharmony_cidrm_public drm_intel_bo * 864d722e3fbSopenharmony_cidrm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr, 865d722e3fbSopenharmony_ci const char *name, 866d722e3fbSopenharmony_ci unsigned long offset, 867d722e3fbSopenharmony_ci unsigned long size, void *virtual) 868d722e3fbSopenharmony_ci{ 869d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake; 870d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake; 871d722e3fbSopenharmony_ci 872d722e3fbSopenharmony_ci bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 873d722e3fbSopenharmony_ci 874d722e3fbSopenharmony_ci assert(size != 0); 875d722e3fbSopenharmony_ci 876d722e3fbSopenharmony_ci bo_fake = calloc(1, sizeof(*bo_fake)); 877d722e3fbSopenharmony_ci if (!bo_fake) 878d722e3fbSopenharmony_ci return NULL; 879d722e3fbSopenharmony_ci 880d722e3fbSopenharmony_ci bo_fake->bo.size = size; 881d722e3fbSopenharmony_ci bo_fake->bo.offset = offset; 882d722e3fbSopenharmony_ci bo_fake->bo.virtual = virtual; 883d722e3fbSopenharmony_ci bo_fake->bo.bufmgr = bufmgr; 884d722e3fbSopenharmony_ci bo_fake->refcount = 1; 885d722e3fbSopenharmony_ci bo_fake->id = ++bufmgr_fake->buf_nr; 886d722e3fbSopenharmony_ci bo_fake->name = name; 887d722e3fbSopenharmony_ci bo_fake->flags = BM_PINNED; 888d722e3fbSopenharmony_ci bo_fake->is_static = 1; 889d722e3fbSopenharmony_ci 890d722e3fbSopenharmony_ci DBG("drm_bo_alloc_static: (buf %d: %s, %lu kb)\n", bo_fake->id, 891d722e3fbSopenharmony_ci bo_fake->name, bo_fake->bo.size / 1024); 892d722e3fbSopenharmony_ci 893d722e3fbSopenharmony_ci return &bo_fake->bo; 894d722e3fbSopenharmony_ci} 895d722e3fbSopenharmony_ci 896d722e3fbSopenharmony_cistatic void 897d722e3fbSopenharmony_cidrm_intel_fake_bo_reference(drm_intel_bo *bo) 898d722e3fbSopenharmony_ci{ 899d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 900d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 901d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 902d722e3fbSopenharmony_ci 903d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 904d722e3fbSopenharmony_ci bo_fake->refcount++; 905d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 906d722e3fbSopenharmony_ci} 907d722e3fbSopenharmony_ci 908d722e3fbSopenharmony_cistatic void 909d722e3fbSopenharmony_cidrm_intel_fake_bo_reference_locked(drm_intel_bo *bo) 910d722e3fbSopenharmony_ci{ 911d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 912d722e3fbSopenharmony_ci 913d722e3fbSopenharmony_ci bo_fake->refcount++; 914d722e3fbSopenharmony_ci} 915d722e3fbSopenharmony_ci 916d722e3fbSopenharmony_cistatic void 917d722e3fbSopenharmony_cidrm_intel_fake_bo_unreference_locked(drm_intel_bo *bo) 918d722e3fbSopenharmony_ci{ 919d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 920d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 921d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 922d722e3fbSopenharmony_ci int i; 923d722e3fbSopenharmony_ci 924d722e3fbSopenharmony_ci if (--bo_fake->refcount == 0) { 925d722e3fbSopenharmony_ci assert(bo_fake->map_count == 0); 926d722e3fbSopenharmony_ci /* No remaining references, so free it */ 927d722e3fbSopenharmony_ci if (bo_fake->block) 928d722e3fbSopenharmony_ci free_block(bufmgr_fake, bo_fake->block, 1); 929d722e3fbSopenharmony_ci free_backing_store(bo); 930d722e3fbSopenharmony_ci 931d722e3fbSopenharmony_ci for (i = 0; i < bo_fake->nr_relocs; i++) 932d722e3fbSopenharmony_ci drm_intel_fake_bo_unreference_locked(bo_fake->relocs[i]. 933d722e3fbSopenharmony_ci target_buf); 934d722e3fbSopenharmony_ci 935d722e3fbSopenharmony_ci DBG("drm_bo_unreference: free buf %d %s\n", bo_fake->id, 936d722e3fbSopenharmony_ci bo_fake->name); 937d722e3fbSopenharmony_ci 938d722e3fbSopenharmony_ci free(bo_fake->relocs); 939d722e3fbSopenharmony_ci free(bo); 940d722e3fbSopenharmony_ci } 941d722e3fbSopenharmony_ci} 942d722e3fbSopenharmony_ci 943d722e3fbSopenharmony_cistatic void 944d722e3fbSopenharmony_cidrm_intel_fake_bo_unreference(drm_intel_bo *bo) 945d722e3fbSopenharmony_ci{ 946d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 947d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 948d722e3fbSopenharmony_ci 949d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 950d722e3fbSopenharmony_ci drm_intel_fake_bo_unreference_locked(bo); 951d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 952d722e3fbSopenharmony_ci} 953d722e3fbSopenharmony_ci 954d722e3fbSopenharmony_ci/** 955d722e3fbSopenharmony_ci * Set the buffer as not requiring backing store, and instead get the callback 956d722e3fbSopenharmony_ci * invoked whenever it would be set dirty. 957d722e3fbSopenharmony_ci */ 958d722e3fbSopenharmony_cidrm_public void 959d722e3fbSopenharmony_cidrm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo, 960d722e3fbSopenharmony_ci void (*invalidate_cb) (drm_intel_bo *bo, 961d722e3fbSopenharmony_ci void *ptr), 962d722e3fbSopenharmony_ci void *ptr) 963d722e3fbSopenharmony_ci{ 964d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 965d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 966d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 967d722e3fbSopenharmony_ci 968d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 969d722e3fbSopenharmony_ci 970d722e3fbSopenharmony_ci if (bo_fake->backing_store) 971d722e3fbSopenharmony_ci free_backing_store(bo); 972d722e3fbSopenharmony_ci 973d722e3fbSopenharmony_ci bo_fake->flags |= BM_NO_BACKING_STORE; 974d722e3fbSopenharmony_ci 975d722e3fbSopenharmony_ci DBG("disable_backing_store set buf %d dirty\n", bo_fake->id); 976d722e3fbSopenharmony_ci bo_fake->dirty = 1; 977d722e3fbSopenharmony_ci bo_fake->invalidate_cb = invalidate_cb; 978d722e3fbSopenharmony_ci bo_fake->invalidate_ptr = ptr; 979d722e3fbSopenharmony_ci 980d722e3fbSopenharmony_ci /* Note that it is invalid right from the start. Also note 981d722e3fbSopenharmony_ci * invalidate_cb is called with the bufmgr locked, so cannot 982d722e3fbSopenharmony_ci * itself make bufmgr calls. 983d722e3fbSopenharmony_ci */ 984d722e3fbSopenharmony_ci if (invalidate_cb != NULL) 985d722e3fbSopenharmony_ci invalidate_cb(bo, ptr); 986d722e3fbSopenharmony_ci 987d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 988d722e3fbSopenharmony_ci} 989d722e3fbSopenharmony_ci 990d722e3fbSopenharmony_ci/** 991d722e3fbSopenharmony_ci * Map a buffer into bo->virtual, allocating either card memory space (If 992d722e3fbSopenharmony_ci * BM_NO_BACKING_STORE or BM_PINNED) or backing store, as necessary. 993d722e3fbSopenharmony_ci */ 994d722e3fbSopenharmony_cistatic int 995d722e3fbSopenharmony_ci drm_intel_fake_bo_map_locked(drm_intel_bo *bo, int write_enable) 996d722e3fbSopenharmony_ci{ 997d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 998d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 999d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1000d722e3fbSopenharmony_ci 1001d722e3fbSopenharmony_ci /* Static buffers are always mapped. */ 1002d722e3fbSopenharmony_ci if (bo_fake->is_static) { 1003d722e3fbSopenharmony_ci if (bo_fake->card_dirty) { 1004d722e3fbSopenharmony_ci drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 1005d722e3fbSopenharmony_ci bo_fake->card_dirty = 0; 1006d722e3fbSopenharmony_ci } 1007d722e3fbSopenharmony_ci return 0; 1008d722e3fbSopenharmony_ci } 1009d722e3fbSopenharmony_ci 1010d722e3fbSopenharmony_ci /* Allow recursive mapping. Mesa may recursively map buffers with 1011d722e3fbSopenharmony_ci * nested display loops, and it is used internally in bufmgr_fake 1012d722e3fbSopenharmony_ci * for relocation. 1013d722e3fbSopenharmony_ci */ 1014d722e3fbSopenharmony_ci if (bo_fake->map_count++ != 0) 1015d722e3fbSopenharmony_ci return 0; 1016d722e3fbSopenharmony_ci 1017d722e3fbSopenharmony_ci { 1018d722e3fbSopenharmony_ci DBG("drm_bo_map: (buf %d: %s, %lu kb)\n", bo_fake->id, 1019d722e3fbSopenharmony_ci bo_fake->name, bo_fake->bo.size / 1024); 1020d722e3fbSopenharmony_ci 1021d722e3fbSopenharmony_ci if (bo->virtual != NULL) { 1022d722e3fbSopenharmony_ci drmMsg("%s: already mapped\n", __func__); 1023d722e3fbSopenharmony_ci abort(); 1024d722e3fbSopenharmony_ci } else if (bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED)) { 1025d722e3fbSopenharmony_ci 1026d722e3fbSopenharmony_ci if (!bo_fake->block && !evict_and_alloc_block(bo)) { 1027d722e3fbSopenharmony_ci DBG("%s: alloc failed\n", __func__); 1028d722e3fbSopenharmony_ci bufmgr_fake->fail = 1; 1029d722e3fbSopenharmony_ci return 1; 1030d722e3fbSopenharmony_ci } else { 1031d722e3fbSopenharmony_ci assert(bo_fake->block); 1032d722e3fbSopenharmony_ci bo_fake->dirty = 0; 1033d722e3fbSopenharmony_ci 1034d722e3fbSopenharmony_ci if (!(bo_fake->flags & BM_NO_FENCE_SUBDATA) && 1035d722e3fbSopenharmony_ci bo_fake->block->fenced) { 1036d722e3fbSopenharmony_ci drm_intel_fake_bo_wait_rendering_locked 1037d722e3fbSopenharmony_ci (bo); 1038d722e3fbSopenharmony_ci } 1039d722e3fbSopenharmony_ci 1040d722e3fbSopenharmony_ci bo->virtual = bo_fake->block->virtual; 1041d722e3fbSopenharmony_ci } 1042d722e3fbSopenharmony_ci } else { 1043d722e3fbSopenharmony_ci if (write_enable) 1044d722e3fbSopenharmony_ci set_dirty(bo); 1045d722e3fbSopenharmony_ci 1046d722e3fbSopenharmony_ci if (bo_fake->backing_store == 0) 1047d722e3fbSopenharmony_ci alloc_backing_store(bo); 1048d722e3fbSopenharmony_ci 1049d722e3fbSopenharmony_ci if ((bo_fake->card_dirty == 1) && bo_fake->block) { 1050d722e3fbSopenharmony_ci if (bo_fake->block->fenced) 1051d722e3fbSopenharmony_ci drm_intel_fake_bo_wait_rendering_locked 1052d722e3fbSopenharmony_ci (bo); 1053d722e3fbSopenharmony_ci 1054d722e3fbSopenharmony_ci memcpy(bo_fake->backing_store, 1055d722e3fbSopenharmony_ci bo_fake->block->virtual, 1056d722e3fbSopenharmony_ci bo_fake->block->bo->size); 1057d722e3fbSopenharmony_ci bo_fake->card_dirty = 0; 1058d722e3fbSopenharmony_ci } 1059d722e3fbSopenharmony_ci 1060d722e3fbSopenharmony_ci bo->virtual = bo_fake->backing_store; 1061d722e3fbSopenharmony_ci } 1062d722e3fbSopenharmony_ci } 1063d722e3fbSopenharmony_ci 1064d722e3fbSopenharmony_ci return 0; 1065d722e3fbSopenharmony_ci} 1066d722e3fbSopenharmony_ci 1067d722e3fbSopenharmony_cistatic int 1068d722e3fbSopenharmony_ci drm_intel_fake_bo_map(drm_intel_bo *bo, int write_enable) 1069d722e3fbSopenharmony_ci{ 1070d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1071d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1072d722e3fbSopenharmony_ci int ret; 1073d722e3fbSopenharmony_ci 1074d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 1075d722e3fbSopenharmony_ci ret = drm_intel_fake_bo_map_locked(bo, write_enable); 1076d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1077d722e3fbSopenharmony_ci 1078d722e3fbSopenharmony_ci return ret; 1079d722e3fbSopenharmony_ci} 1080d722e3fbSopenharmony_ci 1081d722e3fbSopenharmony_cistatic int 1082d722e3fbSopenharmony_ci drm_intel_fake_bo_unmap_locked(drm_intel_bo *bo) 1083d722e3fbSopenharmony_ci{ 1084d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1085d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1086d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1087d722e3fbSopenharmony_ci 1088d722e3fbSopenharmony_ci /* Static buffers are always mapped. */ 1089d722e3fbSopenharmony_ci if (bo_fake->is_static) 1090d722e3fbSopenharmony_ci return 0; 1091d722e3fbSopenharmony_ci 1092d722e3fbSopenharmony_ci assert(bo_fake->map_count != 0); 1093d722e3fbSopenharmony_ci if (--bo_fake->map_count != 0) 1094d722e3fbSopenharmony_ci return 0; 1095d722e3fbSopenharmony_ci 1096d722e3fbSopenharmony_ci DBG("drm_bo_unmap: (buf %d: %s, %lu kb)\n", bo_fake->id, bo_fake->name, 1097d722e3fbSopenharmony_ci bo_fake->bo.size / 1024); 1098d722e3fbSopenharmony_ci 1099d722e3fbSopenharmony_ci bo->virtual = NULL; 1100d722e3fbSopenharmony_ci 1101d722e3fbSopenharmony_ci return 0; 1102d722e3fbSopenharmony_ci} 1103d722e3fbSopenharmony_ci 1104d722e3fbSopenharmony_cistatic int drm_intel_fake_bo_unmap(drm_intel_bo *bo) 1105d722e3fbSopenharmony_ci{ 1106d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1107d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1108d722e3fbSopenharmony_ci int ret; 1109d722e3fbSopenharmony_ci 1110d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 1111d722e3fbSopenharmony_ci ret = drm_intel_fake_bo_unmap_locked(bo); 1112d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1113d722e3fbSopenharmony_ci 1114d722e3fbSopenharmony_ci return ret; 1115d722e3fbSopenharmony_ci} 1116d722e3fbSopenharmony_ci 1117d722e3fbSopenharmony_cistatic int 1118d722e3fbSopenharmony_cidrm_intel_fake_bo_subdata(drm_intel_bo *bo, unsigned long offset, 1119d722e3fbSopenharmony_ci unsigned long size, const void *data) 1120d722e3fbSopenharmony_ci{ 1121d722e3fbSopenharmony_ci int ret; 1122d722e3fbSopenharmony_ci 1123d722e3fbSopenharmony_ci if (size == 0 || data == NULL) 1124d722e3fbSopenharmony_ci return 0; 1125d722e3fbSopenharmony_ci 1126d722e3fbSopenharmony_ci ret = drm_intel_bo_map(bo, 1); 1127d722e3fbSopenharmony_ci if (ret) 1128d722e3fbSopenharmony_ci return ret; 1129d722e3fbSopenharmony_ci memcpy((unsigned char *)bo->virtual + offset, data, size); 1130d722e3fbSopenharmony_ci drm_intel_bo_unmap(bo); 1131d722e3fbSopenharmony_ci return 0; 1132d722e3fbSopenharmony_ci} 1133d722e3fbSopenharmony_ci 1134d722e3fbSopenharmony_cistatic void 1135d722e3fbSopenharmony_ci drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake *bufmgr_fake) 1136d722e3fbSopenharmony_ci{ 1137d722e3fbSopenharmony_ci struct block *block, *tmp; 1138d722e3fbSopenharmony_ci 1139d722e3fbSopenharmony_ci bufmgr_fake->performed_rendering = 0; 1140d722e3fbSopenharmony_ci /* okay for ever BO that is on the HW kick it off. 1141d722e3fbSopenharmony_ci seriously not afraid of the POLICE right now */ 1142d722e3fbSopenharmony_ci DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) { 1143d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 1144d722e3fbSopenharmony_ci 1145d722e3fbSopenharmony_ci block->on_hardware = 0; 1146d722e3fbSopenharmony_ci free_block(bufmgr_fake, block, 0); 1147d722e3fbSopenharmony_ci bo_fake->block = NULL; 1148d722e3fbSopenharmony_ci bo_fake->validated = 0; 1149d722e3fbSopenharmony_ci if (!(bo_fake->flags & BM_NO_BACKING_STORE)) 1150d722e3fbSopenharmony_ci bo_fake->dirty = 1; 1151d722e3fbSopenharmony_ci } 1152d722e3fbSopenharmony_ci 1153d722e3fbSopenharmony_ci} 1154d722e3fbSopenharmony_ci 1155d722e3fbSopenharmony_cistatic int 1156d722e3fbSopenharmony_ci drm_intel_fake_bo_validate(drm_intel_bo *bo) 1157d722e3fbSopenharmony_ci{ 1158d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake; 1159d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1160d722e3fbSopenharmony_ci 1161d722e3fbSopenharmony_ci bufmgr_fake = (drm_intel_bufmgr_fake *) bo->bufmgr; 1162d722e3fbSopenharmony_ci 1163d722e3fbSopenharmony_ci DBG("drm_bo_validate: (buf %d: %s, %lu kb)\n", bo_fake->id, 1164d722e3fbSopenharmony_ci bo_fake->name, bo_fake->bo.size / 1024); 1165d722e3fbSopenharmony_ci 1166d722e3fbSopenharmony_ci /* Sanity check: Buffers should be unmapped before being validated. 1167d722e3fbSopenharmony_ci * This is not so much of a problem for bufmgr_fake, but TTM refuses, 1168d722e3fbSopenharmony_ci * and the problem is harder to debug there. 1169d722e3fbSopenharmony_ci */ 1170d722e3fbSopenharmony_ci assert(bo_fake->map_count == 0); 1171d722e3fbSopenharmony_ci 1172d722e3fbSopenharmony_ci if (bo_fake->is_static) { 1173d722e3fbSopenharmony_ci /* Add it to the needs-fence list */ 1174d722e3fbSopenharmony_ci bufmgr_fake->need_fence = 1; 1175d722e3fbSopenharmony_ci return 0; 1176d722e3fbSopenharmony_ci } 1177d722e3fbSopenharmony_ci 1178d722e3fbSopenharmony_ci /* Allocate the card memory */ 1179d722e3fbSopenharmony_ci if (!bo_fake->block && !evict_and_alloc_block(bo)) { 1180d722e3fbSopenharmony_ci bufmgr_fake->fail = 1; 1181d722e3fbSopenharmony_ci DBG("Failed to validate buf %d:%s\n", bo_fake->id, 1182d722e3fbSopenharmony_ci bo_fake->name); 1183d722e3fbSopenharmony_ci return -1; 1184d722e3fbSopenharmony_ci } 1185d722e3fbSopenharmony_ci 1186d722e3fbSopenharmony_ci assert(bo_fake->block); 1187d722e3fbSopenharmony_ci assert(bo_fake->block->bo == &bo_fake->bo); 1188d722e3fbSopenharmony_ci 1189d722e3fbSopenharmony_ci bo->offset = bo_fake->block->mem->ofs; 1190d722e3fbSopenharmony_ci 1191d722e3fbSopenharmony_ci /* Upload the buffer contents if necessary */ 1192d722e3fbSopenharmony_ci if (bo_fake->dirty) { 1193d722e3fbSopenharmony_ci DBG("Upload dirty buf %d:%s, sz %lu offset 0x%x\n", bo_fake->id, 1194d722e3fbSopenharmony_ci bo_fake->name, bo->size, bo_fake->block->mem->ofs); 1195d722e3fbSopenharmony_ci 1196d722e3fbSopenharmony_ci assert(!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED))); 1197d722e3fbSopenharmony_ci 1198d722e3fbSopenharmony_ci /* Actually, should be able to just wait for a fence on the 1199d722e3fbSopenharmony_ci * memory, which we would be tracking when we free it. Waiting 1200d722e3fbSopenharmony_ci * for idle is a sufficiently large hammer for now. 1201d722e3fbSopenharmony_ci */ 1202d722e3fbSopenharmony_ci drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 1203d722e3fbSopenharmony_ci 1204d722e3fbSopenharmony_ci /* we may never have mapped this BO so it might not have any 1205d722e3fbSopenharmony_ci * backing store if this happens it should be rare, but 0 the 1206d722e3fbSopenharmony_ci * card memory in any case */ 1207d722e3fbSopenharmony_ci if (bo_fake->backing_store) 1208d722e3fbSopenharmony_ci memcpy(bo_fake->block->virtual, bo_fake->backing_store, 1209d722e3fbSopenharmony_ci bo->size); 1210d722e3fbSopenharmony_ci else 1211d722e3fbSopenharmony_ci memset(bo_fake->block->virtual, 0, bo->size); 1212d722e3fbSopenharmony_ci 1213d722e3fbSopenharmony_ci bo_fake->dirty = 0; 1214d722e3fbSopenharmony_ci } 1215d722e3fbSopenharmony_ci 1216d722e3fbSopenharmony_ci bo_fake->block->fenced = 0; 1217d722e3fbSopenharmony_ci bo_fake->block->on_hardware = 1; 1218d722e3fbSopenharmony_ci DRMLISTDEL(bo_fake->block); 1219d722e3fbSopenharmony_ci DRMLISTADDTAIL(bo_fake->block, &bufmgr_fake->on_hardware); 1220d722e3fbSopenharmony_ci 1221d722e3fbSopenharmony_ci bo_fake->validated = 1; 1222d722e3fbSopenharmony_ci bufmgr_fake->need_fence = 1; 1223d722e3fbSopenharmony_ci 1224d722e3fbSopenharmony_ci return 0; 1225d722e3fbSopenharmony_ci} 1226d722e3fbSopenharmony_ci 1227d722e3fbSopenharmony_cistatic void 1228d722e3fbSopenharmony_cidrm_intel_fake_fence_validated(drm_intel_bufmgr *bufmgr) 1229d722e3fbSopenharmony_ci{ 1230d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1231d722e3fbSopenharmony_ci unsigned int cookie; 1232d722e3fbSopenharmony_ci 1233d722e3fbSopenharmony_ci cookie = _fence_emit_internal(bufmgr_fake); 1234d722e3fbSopenharmony_ci fence_blocks(bufmgr_fake, cookie); 1235d722e3fbSopenharmony_ci 1236d722e3fbSopenharmony_ci DBG("drm_fence_validated: 0x%08x cookie\n", cookie); 1237d722e3fbSopenharmony_ci} 1238d722e3fbSopenharmony_ci 1239d722e3fbSopenharmony_cistatic void 1240d722e3fbSopenharmony_cidrm_intel_fake_destroy(drm_intel_bufmgr *bufmgr) 1241d722e3fbSopenharmony_ci{ 1242d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1243d722e3fbSopenharmony_ci 1244d722e3fbSopenharmony_ci pthread_mutex_destroy(&bufmgr_fake->lock); 1245d722e3fbSopenharmony_ci mmDestroy(bufmgr_fake->heap); 1246d722e3fbSopenharmony_ci free(bufmgr); 1247d722e3fbSopenharmony_ci} 1248d722e3fbSopenharmony_ci 1249d722e3fbSopenharmony_cistatic int 1250d722e3fbSopenharmony_cidrm_intel_fake_emit_reloc(drm_intel_bo *bo, uint32_t offset, 1251d722e3fbSopenharmony_ci drm_intel_bo *target_bo, uint32_t target_offset, 1252d722e3fbSopenharmony_ci uint32_t read_domains, uint32_t write_domain) 1253d722e3fbSopenharmony_ci{ 1254d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1255d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1256d722e3fbSopenharmony_ci struct fake_buffer_reloc *r; 1257d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1258d722e3fbSopenharmony_ci drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *) target_bo; 1259d722e3fbSopenharmony_ci int i; 1260d722e3fbSopenharmony_ci 1261d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 1262d722e3fbSopenharmony_ci 1263d722e3fbSopenharmony_ci assert(bo); 1264d722e3fbSopenharmony_ci assert(target_bo); 1265d722e3fbSopenharmony_ci 1266d722e3fbSopenharmony_ci if (bo_fake->relocs == NULL) { 1267d722e3fbSopenharmony_ci bo_fake->relocs = 1268d722e3fbSopenharmony_ci malloc(sizeof(struct fake_buffer_reloc) * MAX_RELOCS); 1269d722e3fbSopenharmony_ci } 1270d722e3fbSopenharmony_ci 1271d722e3fbSopenharmony_ci r = &bo_fake->relocs[bo_fake->nr_relocs++]; 1272d722e3fbSopenharmony_ci 1273d722e3fbSopenharmony_ci assert(bo_fake->nr_relocs <= MAX_RELOCS); 1274d722e3fbSopenharmony_ci 1275d722e3fbSopenharmony_ci drm_intel_fake_bo_reference_locked(target_bo); 1276d722e3fbSopenharmony_ci 1277d722e3fbSopenharmony_ci if (!target_fake->is_static) { 1278d722e3fbSopenharmony_ci bo_fake->child_size += 1279d722e3fbSopenharmony_ci ALIGN(target_bo->size, target_fake->alignment); 1280d722e3fbSopenharmony_ci bo_fake->child_size += target_fake->child_size; 1281d722e3fbSopenharmony_ci } 1282d722e3fbSopenharmony_ci r->target_buf = target_bo; 1283d722e3fbSopenharmony_ci r->offset = offset; 1284d722e3fbSopenharmony_ci r->last_target_offset = target_bo->offset; 1285d722e3fbSopenharmony_ci r->delta = target_offset; 1286d722e3fbSopenharmony_ci r->read_domains = read_domains; 1287d722e3fbSopenharmony_ci r->write_domain = write_domain; 1288d722e3fbSopenharmony_ci 1289d722e3fbSopenharmony_ci if (bufmgr_fake->debug) { 1290d722e3fbSopenharmony_ci /* Check that a conflicting relocation hasn't already been 1291d722e3fbSopenharmony_ci * emitted. 1292d722e3fbSopenharmony_ci */ 1293d722e3fbSopenharmony_ci for (i = 0; i < bo_fake->nr_relocs - 1; i++) { 1294d722e3fbSopenharmony_ci struct fake_buffer_reloc *r2 = &bo_fake->relocs[i]; 1295d722e3fbSopenharmony_ci 1296d722e3fbSopenharmony_ci assert(r->offset != r2->offset); 1297d722e3fbSopenharmony_ci } 1298d722e3fbSopenharmony_ci } 1299d722e3fbSopenharmony_ci 1300d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1301d722e3fbSopenharmony_ci 1302d722e3fbSopenharmony_ci return 0; 1303d722e3fbSopenharmony_ci} 1304d722e3fbSopenharmony_ci 1305d722e3fbSopenharmony_ci/** 1306d722e3fbSopenharmony_ci * Incorporates the validation flags associated with each relocation into 1307d722e3fbSopenharmony_ci * the combined validation flags for the buffer on this batchbuffer submission. 1308d722e3fbSopenharmony_ci */ 1309d722e3fbSopenharmony_cistatic void 1310d722e3fbSopenharmony_cidrm_intel_fake_calculate_domains(drm_intel_bo *bo) 1311d722e3fbSopenharmony_ci{ 1312d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1313d722e3fbSopenharmony_ci int i; 1314d722e3fbSopenharmony_ci 1315d722e3fbSopenharmony_ci for (i = 0; i < bo_fake->nr_relocs; i++) { 1316d722e3fbSopenharmony_ci struct fake_buffer_reloc *r = &bo_fake->relocs[i]; 1317d722e3fbSopenharmony_ci drm_intel_bo_fake *target_fake = 1318d722e3fbSopenharmony_ci (drm_intel_bo_fake *) r->target_buf; 1319d722e3fbSopenharmony_ci 1320d722e3fbSopenharmony_ci /* Do the same for the tree of buffers we depend on */ 1321d722e3fbSopenharmony_ci drm_intel_fake_calculate_domains(r->target_buf); 1322d722e3fbSopenharmony_ci 1323d722e3fbSopenharmony_ci target_fake->read_domains |= r->read_domains; 1324d722e3fbSopenharmony_ci target_fake->write_domain |= r->write_domain; 1325d722e3fbSopenharmony_ci } 1326d722e3fbSopenharmony_ci} 1327d722e3fbSopenharmony_ci 1328d722e3fbSopenharmony_cistatic int 1329d722e3fbSopenharmony_cidrm_intel_fake_reloc_and_validate_buffer(drm_intel_bo *bo) 1330d722e3fbSopenharmony_ci{ 1331d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1332d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1333d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1334d722e3fbSopenharmony_ci int i, ret; 1335d722e3fbSopenharmony_ci 1336d722e3fbSopenharmony_ci assert(bo_fake->map_count == 0); 1337d722e3fbSopenharmony_ci 1338d722e3fbSopenharmony_ci for (i = 0; i < bo_fake->nr_relocs; i++) { 1339d722e3fbSopenharmony_ci struct fake_buffer_reloc *r = &bo_fake->relocs[i]; 1340d722e3fbSopenharmony_ci drm_intel_bo_fake *target_fake = 1341d722e3fbSopenharmony_ci (drm_intel_bo_fake *) r->target_buf; 1342d722e3fbSopenharmony_ci uint32_t reloc_data; 1343d722e3fbSopenharmony_ci 1344d722e3fbSopenharmony_ci /* Validate the target buffer if that hasn't been done. */ 1345d722e3fbSopenharmony_ci if (!target_fake->validated) { 1346d722e3fbSopenharmony_ci ret = 1347d722e3fbSopenharmony_ci drm_intel_fake_reloc_and_validate_buffer(r->target_buf); 1348d722e3fbSopenharmony_ci if (ret != 0) { 1349d722e3fbSopenharmony_ci if (bo->virtual != NULL) 1350d722e3fbSopenharmony_ci drm_intel_fake_bo_unmap_locked(bo); 1351d722e3fbSopenharmony_ci return ret; 1352d722e3fbSopenharmony_ci } 1353d722e3fbSopenharmony_ci } 1354d722e3fbSopenharmony_ci 1355d722e3fbSopenharmony_ci /* Calculate the value of the relocation entry. */ 1356d722e3fbSopenharmony_ci if (r->target_buf->offset != r->last_target_offset) { 1357d722e3fbSopenharmony_ci reloc_data = r->target_buf->offset + r->delta; 1358d722e3fbSopenharmony_ci 1359d722e3fbSopenharmony_ci if (bo->virtual == NULL) 1360d722e3fbSopenharmony_ci drm_intel_fake_bo_map_locked(bo, 1); 1361d722e3fbSopenharmony_ci 1362d722e3fbSopenharmony_ci *(uint32_t *) ((uint8_t *) bo->virtual + r->offset) = 1363d722e3fbSopenharmony_ci reloc_data; 1364d722e3fbSopenharmony_ci 1365d722e3fbSopenharmony_ci r->last_target_offset = r->target_buf->offset; 1366d722e3fbSopenharmony_ci } 1367d722e3fbSopenharmony_ci } 1368d722e3fbSopenharmony_ci 1369d722e3fbSopenharmony_ci if (bo->virtual != NULL) 1370d722e3fbSopenharmony_ci drm_intel_fake_bo_unmap_locked(bo); 1371d722e3fbSopenharmony_ci 1372d722e3fbSopenharmony_ci if (bo_fake->write_domain != 0) { 1373d722e3fbSopenharmony_ci if (!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED))) { 1374d722e3fbSopenharmony_ci if (bo_fake->backing_store == 0) 1375d722e3fbSopenharmony_ci alloc_backing_store(bo); 1376d722e3fbSopenharmony_ci } 1377d722e3fbSopenharmony_ci bo_fake->card_dirty = 1; 1378d722e3fbSopenharmony_ci bufmgr_fake->performed_rendering = 1; 1379d722e3fbSopenharmony_ci } 1380d722e3fbSopenharmony_ci 1381d722e3fbSopenharmony_ci return drm_intel_fake_bo_validate(bo); 1382d722e3fbSopenharmony_ci} 1383d722e3fbSopenharmony_ci 1384d722e3fbSopenharmony_cistatic void 1385d722e3fbSopenharmony_cidrm_intel_bo_fake_post_submit(drm_intel_bo *bo) 1386d722e3fbSopenharmony_ci{ 1387d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1388d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1389d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1390d722e3fbSopenharmony_ci int i; 1391d722e3fbSopenharmony_ci 1392d722e3fbSopenharmony_ci for (i = 0; i < bo_fake->nr_relocs; i++) { 1393d722e3fbSopenharmony_ci struct fake_buffer_reloc *r = &bo_fake->relocs[i]; 1394d722e3fbSopenharmony_ci drm_intel_bo_fake *target_fake = 1395d722e3fbSopenharmony_ci (drm_intel_bo_fake *) r->target_buf; 1396d722e3fbSopenharmony_ci 1397d722e3fbSopenharmony_ci if (target_fake->validated) 1398d722e3fbSopenharmony_ci drm_intel_bo_fake_post_submit(r->target_buf); 1399d722e3fbSopenharmony_ci 1400d722e3fbSopenharmony_ci DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n", 1401d722e3fbSopenharmony_ci bo_fake->name, (uint32_t) bo->offset, r->offset, 1402d722e3fbSopenharmony_ci target_fake->name, (uint32_t) r->target_buf->offset, 1403d722e3fbSopenharmony_ci r->delta); 1404d722e3fbSopenharmony_ci } 1405d722e3fbSopenharmony_ci 1406d722e3fbSopenharmony_ci assert(bo_fake->map_count == 0); 1407d722e3fbSopenharmony_ci bo_fake->validated = 0; 1408d722e3fbSopenharmony_ci bo_fake->read_domains = 0; 1409d722e3fbSopenharmony_ci bo_fake->write_domain = 0; 1410d722e3fbSopenharmony_ci} 1411d722e3fbSopenharmony_ci 1412d722e3fbSopenharmony_cidrm_public void 1413d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr, 1414d722e3fbSopenharmony_ci int (*exec) (drm_intel_bo *bo, 1415d722e3fbSopenharmony_ci unsigned int used, 1416d722e3fbSopenharmony_ci void *priv), 1417d722e3fbSopenharmony_ci void *priv) 1418d722e3fbSopenharmony_ci{ 1419d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1420d722e3fbSopenharmony_ci 1421d722e3fbSopenharmony_ci bufmgr_fake->exec = exec; 1422d722e3fbSopenharmony_ci bufmgr_fake->exec_priv = priv; 1423d722e3fbSopenharmony_ci} 1424d722e3fbSopenharmony_ci 1425d722e3fbSopenharmony_cistatic int 1426d722e3fbSopenharmony_cidrm_intel_fake_bo_exec(drm_intel_bo *bo, int used, 1427d722e3fbSopenharmony_ci drm_clip_rect_t * cliprects, int num_cliprects, int DR4) 1428d722e3fbSopenharmony_ci{ 1429d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1430d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo->bufmgr; 1431d722e3fbSopenharmony_ci drm_intel_bo_fake *batch_fake = (drm_intel_bo_fake *) bo; 1432d722e3fbSopenharmony_ci struct drm_i915_batchbuffer batch; 1433d722e3fbSopenharmony_ci int ret; 1434d722e3fbSopenharmony_ci int retry_count = 0; 1435d722e3fbSopenharmony_ci 1436d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 1437d722e3fbSopenharmony_ci 1438d722e3fbSopenharmony_ci bufmgr_fake->performed_rendering = 0; 1439d722e3fbSopenharmony_ci 1440d722e3fbSopenharmony_ci drm_intel_fake_calculate_domains(bo); 1441d722e3fbSopenharmony_ci 1442d722e3fbSopenharmony_ci batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND; 1443d722e3fbSopenharmony_ci 1444d722e3fbSopenharmony_ci /* we've ran out of RAM so blow the whole lot away and retry */ 1445d722e3fbSopenharmony_cirestart: 1446d722e3fbSopenharmony_ci ret = drm_intel_fake_reloc_and_validate_buffer(bo); 1447d722e3fbSopenharmony_ci if (bufmgr_fake->fail == 1) { 1448d722e3fbSopenharmony_ci if (retry_count == 0) { 1449d722e3fbSopenharmony_ci retry_count++; 1450d722e3fbSopenharmony_ci drm_intel_fake_kick_all_locked(bufmgr_fake); 1451d722e3fbSopenharmony_ci bufmgr_fake->fail = 0; 1452d722e3fbSopenharmony_ci goto restart; 1453d722e3fbSopenharmony_ci } else /* dump out the memory here */ 1454d722e3fbSopenharmony_ci mmDumpMemInfo(bufmgr_fake->heap); 1455d722e3fbSopenharmony_ci } 1456d722e3fbSopenharmony_ci 1457d722e3fbSopenharmony_ci assert(ret == 0); 1458d722e3fbSopenharmony_ci 1459d722e3fbSopenharmony_ci if (bufmgr_fake->exec != NULL) { 1460d722e3fbSopenharmony_ci ret = bufmgr_fake->exec(bo, used, bufmgr_fake->exec_priv); 1461d722e3fbSopenharmony_ci if (ret != 0) { 1462d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1463d722e3fbSopenharmony_ci return ret; 1464d722e3fbSopenharmony_ci } 1465d722e3fbSopenharmony_ci } else { 1466d722e3fbSopenharmony_ci batch.start = bo->offset; 1467d722e3fbSopenharmony_ci batch.used = used; 1468d722e3fbSopenharmony_ci batch.cliprects = cliprects; 1469d722e3fbSopenharmony_ci batch.num_cliprects = num_cliprects; 1470d722e3fbSopenharmony_ci batch.DR1 = 0; 1471d722e3fbSopenharmony_ci batch.DR4 = DR4; 1472d722e3fbSopenharmony_ci 1473d722e3fbSopenharmony_ci if (drmCommandWrite 1474d722e3fbSopenharmony_ci (bufmgr_fake->fd, DRM_I915_BATCHBUFFER, &batch, 1475d722e3fbSopenharmony_ci sizeof(batch))) { 1476d722e3fbSopenharmony_ci drmMsg("DRM_I915_BATCHBUFFER: %d\n", -errno); 1477d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1478d722e3fbSopenharmony_ci return -errno; 1479d722e3fbSopenharmony_ci } 1480d722e3fbSopenharmony_ci } 1481d722e3fbSopenharmony_ci 1482d722e3fbSopenharmony_ci drm_intel_fake_fence_validated(bo->bufmgr); 1483d722e3fbSopenharmony_ci 1484d722e3fbSopenharmony_ci drm_intel_bo_fake_post_submit(bo); 1485d722e3fbSopenharmony_ci 1486d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1487d722e3fbSopenharmony_ci 1488d722e3fbSopenharmony_ci return 0; 1489d722e3fbSopenharmony_ci} 1490d722e3fbSopenharmony_ci 1491d722e3fbSopenharmony_ci/** 1492d722e3fbSopenharmony_ci * Return an error if the list of BOs will exceed the aperture size. 1493d722e3fbSopenharmony_ci * 1494d722e3fbSopenharmony_ci * This is a rough guess and likely to fail, as during the validate sequence we 1495d722e3fbSopenharmony_ci * may place a buffer in an inopportune spot early on and then fail to fit 1496d722e3fbSopenharmony_ci * a set smaller than the aperture. 1497d722e3fbSopenharmony_ci */ 1498d722e3fbSopenharmony_cistatic int 1499d722e3fbSopenharmony_cidrm_intel_fake_check_aperture_space(drm_intel_bo ** bo_array, int count) 1500d722e3fbSopenharmony_ci{ 1501d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = 1502d722e3fbSopenharmony_ci (drm_intel_bufmgr_fake *) bo_array[0]->bufmgr; 1503d722e3fbSopenharmony_ci unsigned int sz = 0; 1504d722e3fbSopenharmony_ci int i; 1505d722e3fbSopenharmony_ci 1506d722e3fbSopenharmony_ci for (i = 0; i < count; i++) { 1507d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo_array[i]; 1508d722e3fbSopenharmony_ci 1509d722e3fbSopenharmony_ci if (bo_fake == NULL) 1510d722e3fbSopenharmony_ci continue; 1511d722e3fbSopenharmony_ci 1512d722e3fbSopenharmony_ci if (!bo_fake->is_static) 1513d722e3fbSopenharmony_ci sz += ALIGN(bo_array[i]->size, bo_fake->alignment); 1514d722e3fbSopenharmony_ci sz += bo_fake->child_size; 1515d722e3fbSopenharmony_ci } 1516d722e3fbSopenharmony_ci 1517d722e3fbSopenharmony_ci if (sz > bufmgr_fake->size) { 1518d722e3fbSopenharmony_ci DBG("check_space: overflowed bufmgr size, %ukb vs %lukb\n", 1519d722e3fbSopenharmony_ci sz / 1024, bufmgr_fake->size / 1024); 1520d722e3fbSopenharmony_ci return -1; 1521d722e3fbSopenharmony_ci } 1522d722e3fbSopenharmony_ci 1523d722e3fbSopenharmony_ci DBG("drm_check_space: sz %ukb vs bufgr %lukb\n", sz / 1024, 1524d722e3fbSopenharmony_ci bufmgr_fake->size / 1024); 1525d722e3fbSopenharmony_ci return 0; 1526d722e3fbSopenharmony_ci} 1527d722e3fbSopenharmony_ci 1528d722e3fbSopenharmony_ci/** 1529d722e3fbSopenharmony_ci * Evicts all buffers, waiting for fences to pass and copying contents out 1530d722e3fbSopenharmony_ci * as necessary. 1531d722e3fbSopenharmony_ci * 1532d722e3fbSopenharmony_ci * Used by the X Server on LeaveVT, when the card memory is no longer our 1533d722e3fbSopenharmony_ci * own. 1534d722e3fbSopenharmony_ci */ 1535d722e3fbSopenharmony_cidrm_public void 1536d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr) 1537d722e3fbSopenharmony_ci{ 1538d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1539d722e3fbSopenharmony_ci struct block *block, *tmp; 1540d722e3fbSopenharmony_ci 1541d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_fake->lock); 1542d722e3fbSopenharmony_ci 1543d722e3fbSopenharmony_ci bufmgr_fake->need_fence = 1; 1544d722e3fbSopenharmony_ci bufmgr_fake->fail = 0; 1545d722e3fbSopenharmony_ci 1546d722e3fbSopenharmony_ci /* Wait for hardware idle. We don't know where acceleration has been 1547d722e3fbSopenharmony_ci * happening, so we'll need to wait anyway before letting anything get 1548d722e3fbSopenharmony_ci * put on the card again. 1549d722e3fbSopenharmony_ci */ 1550d722e3fbSopenharmony_ci drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 1551d722e3fbSopenharmony_ci 1552d722e3fbSopenharmony_ci /* Check that we hadn't released the lock without having fenced the last 1553d722e3fbSopenharmony_ci * set of buffers. 1554d722e3fbSopenharmony_ci */ 1555d722e3fbSopenharmony_ci assert(DRMLISTEMPTY(&bufmgr_fake->fenced)); 1556d722e3fbSopenharmony_ci assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware)); 1557d722e3fbSopenharmony_ci 1558d722e3fbSopenharmony_ci DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { 1559d722e3fbSopenharmony_ci drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 1560d722e3fbSopenharmony_ci /* Releases the memory, and memcpys dirty contents out if 1561d722e3fbSopenharmony_ci * necessary. 1562d722e3fbSopenharmony_ci */ 1563d722e3fbSopenharmony_ci free_block(bufmgr_fake, block, 0); 1564d722e3fbSopenharmony_ci bo_fake->block = NULL; 1565d722e3fbSopenharmony_ci } 1566d722e3fbSopenharmony_ci 1567d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_fake->lock); 1568d722e3fbSopenharmony_ci} 1569d722e3fbSopenharmony_ci 1570d722e3fbSopenharmony_cidrm_public void 1571d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr, 1572d722e3fbSopenharmony_ci volatile unsigned int 1573d722e3fbSopenharmony_ci *last_dispatch) 1574d722e3fbSopenharmony_ci{ 1575d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1576d722e3fbSopenharmony_ci 1577d722e3fbSopenharmony_ci bufmgr_fake->last_dispatch = (volatile int *)last_dispatch; 1578d722e3fbSopenharmony_ci} 1579d722e3fbSopenharmony_ci 1580d722e3fbSopenharmony_cidrm_public drm_intel_bufmgr * 1581d722e3fbSopenharmony_cidrm_intel_bufmgr_fake_init(int fd, unsigned long low_offset, 1582d722e3fbSopenharmony_ci void *low_virtual, unsigned long size, 1583d722e3fbSopenharmony_ci volatile unsigned int *last_dispatch) 1584d722e3fbSopenharmony_ci{ 1585d722e3fbSopenharmony_ci drm_intel_bufmgr_fake *bufmgr_fake; 1586d722e3fbSopenharmony_ci 1587d722e3fbSopenharmony_ci bufmgr_fake = calloc(1, sizeof(*bufmgr_fake)); 1588d722e3fbSopenharmony_ci 1589d722e3fbSopenharmony_ci if (pthread_mutex_init(&bufmgr_fake->lock, NULL) != 0) { 1590d722e3fbSopenharmony_ci free(bufmgr_fake); 1591d722e3fbSopenharmony_ci return NULL; 1592d722e3fbSopenharmony_ci } 1593d722e3fbSopenharmony_ci 1594d722e3fbSopenharmony_ci /* Initialize allocator */ 1595d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bufmgr_fake->fenced); 1596d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bufmgr_fake->on_hardware); 1597d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bufmgr_fake->lru); 1598d722e3fbSopenharmony_ci 1599d722e3fbSopenharmony_ci bufmgr_fake->low_offset = low_offset; 1600d722e3fbSopenharmony_ci bufmgr_fake->virtual = low_virtual; 1601d722e3fbSopenharmony_ci bufmgr_fake->size = size; 1602d722e3fbSopenharmony_ci bufmgr_fake->heap = mmInit(low_offset, size); 1603d722e3fbSopenharmony_ci 1604d722e3fbSopenharmony_ci /* Hook in methods */ 1605d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_alloc = drm_intel_fake_bo_alloc; 1606d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_alloc_for_render = drm_intel_fake_bo_alloc; 1607d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_alloc_tiled = drm_intel_fake_bo_alloc_tiled; 1608d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_reference = drm_intel_fake_bo_reference; 1609d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_unreference = drm_intel_fake_bo_unreference; 1610d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_map = drm_intel_fake_bo_map; 1611d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_unmap = drm_intel_fake_bo_unmap; 1612d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_subdata = drm_intel_fake_bo_subdata; 1613d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_wait_rendering = 1614d722e3fbSopenharmony_ci drm_intel_fake_bo_wait_rendering; 1615d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_emit_reloc = drm_intel_fake_emit_reloc; 1616d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.destroy = drm_intel_fake_destroy; 1617d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.bo_exec = drm_intel_fake_bo_exec; 1618d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.check_aperture_space = 1619d722e3fbSopenharmony_ci drm_intel_fake_check_aperture_space; 1620d722e3fbSopenharmony_ci bufmgr_fake->bufmgr.debug = 0; 1621d722e3fbSopenharmony_ci 1622d722e3fbSopenharmony_ci bufmgr_fake->fd = fd; 1623d722e3fbSopenharmony_ci bufmgr_fake->last_dispatch = (volatile int *)last_dispatch; 1624d722e3fbSopenharmony_ci 1625d722e3fbSopenharmony_ci return &bufmgr_fake->bufmgr; 1626d722e3fbSopenharmony_ci} 1627