1 2 #include "i915_drm_winsys.h" 3 #include "util/u_memory.h" 4 5 #include "i915_drm.h" 6 #include "i915/i915_debug.h" 7 #include <xf86drm.h> 8 #include <stdio.h> 9 10 #define BATCH_RESERVED 16 11 12 #define INTEL_DEFAULT_RELOCS 100 13 #define INTEL_MAX_RELOCS 400 14 15 #define INTEL_BATCH_NO_CLIPRECTS 0x1 16 #define INTEL_BATCH_CLIPRECTS 0x2 17 18 #undef INTEL_RUN_SYNC 19 20 struct i915_drm_batchbuffer 21 { 22 struct i915_winsys_batchbuffer base; 23 24 size_t actual_size; 25 26 drm_intel_bo *bo; 27 }; 28 29 static INLINE struct i915_drm_batchbuffer * 30 i915_drm_batchbuffer(struct i915_winsys_batchbuffer *batch) 31 { 32 return (struct i915_drm_batchbuffer *)batch; 33 } 34 35 static void 36 i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch) 37 { 38 struct i915_drm_winsys *idws = i915_drm_winsys(batch->base.iws); 39 40 if (batch->bo) 41 drm_intel_bo_unreference(batch->bo); 42 batch->bo = drm_intel_bo_alloc(idws->gem_manager, 43 "gallium3d_batchbuffer", 44 batch->actual_size, 45 4096); 46 47 memset(batch->base.map, 0, batch->actual_size); 48 batch->base.ptr = batch->base.map; 49 batch->base.size = batch->actual_size - BATCH_RESERVED; 50 batch->base.relocs = 0; 51 } 52 53 static struct i915_winsys_batchbuffer * 54 i915_drm_batchbuffer_create(struct i915_winsys *iws) 55 { 56 struct i915_drm_winsys *idws = i915_drm_winsys(iws); 57 struct i915_drm_batchbuffer *batch = CALLOC_STRUCT(i915_drm_batchbuffer); 58 59 batch->actual_size = idws->max_batch_size; 60 61 batch->base.map = MALLOC(batch->actual_size); 62 batch->base.ptr = NULL; 63 batch->base.size = 0; 64 65 batch->base.relocs = 0; 66 67 batch->base.iws = iws; 68 69 i915_drm_batchbuffer_reset(batch); 70 71 return &batch->base; 72 } 73 74 static boolean 75 i915_drm_batchbuffer_validate_buffers(struct i915_winsys_batchbuffer *batch, 76 struct i915_winsys_buffer **buffer, 77 int num_of_buffers) 78 { 79 struct i915_drm_batchbuffer *drm_batch = i915_drm_batchbuffer(batch); 80 drm_intel_bo *bos[num_of_buffers + 1]; 81 int i, ret; 82 83 bos[0] = drm_batch->bo; 84 for (i = 0; i < num_of_buffers; i++) 85 bos[i+1] = intel_bo(buffer[i]); 86 87 ret = drm_intel_bufmgr_check_aperture_space(bos, num_of_buffers); 88 if (ret != 0) 89 return FALSE; 90 91 return TRUE; 92 } 93 94 static int 95 i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, 96 struct i915_winsys_buffer *buffer, 97 enum i915_winsys_buffer_usage usage, 98 unsigned pre_add, boolean fenced) 99 { 100 struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); 101 unsigned write_domain = 0; 102 unsigned read_domain = 0; 103 unsigned offset; 104 int ret = 0; 105 106 switch (usage) { 107 case I915_USAGE_SAMPLER: 108 write_domain = 0; 109 read_domain = I915_GEM_DOMAIN_SAMPLER; 110 break; 111 case I915_USAGE_RENDER: 112 write_domain = I915_GEM_DOMAIN_RENDER; 113 read_domain = I915_GEM_DOMAIN_RENDER; 114 break; 115 case I915_USAGE_2D_TARGET: 116 write_domain = I915_GEM_DOMAIN_RENDER; 117 read_domain = I915_GEM_DOMAIN_RENDER; 118 break; 119 case I915_USAGE_2D_SOURCE: 120 write_domain = 0; 121 read_domain = I915_GEM_DOMAIN_RENDER; 122 break; 123 case I915_USAGE_VERTEX: 124 write_domain = 0; 125 read_domain = I915_GEM_DOMAIN_VERTEX; 126 break; 127 default: 128 assert(0); 129 return -1; 130 } 131 132 offset = (unsigned)(batch->base.ptr - batch->base.map); 133 134 if (fenced) 135 ret = drm_intel_bo_emit_reloc_fence(batch->bo, offset, 136 intel_bo(buffer), pre_add, 137 read_domain, 138 write_domain); 139 else 140 ret = drm_intel_bo_emit_reloc(batch->bo, offset, 141 intel_bo(buffer), pre_add, 142 read_domain, 143 write_domain); 144 145 ((uint32_t*)batch->base.ptr)[0] = intel_bo(buffer)->offset + pre_add; 146 batch->base.ptr += 4; 147 148 if (!ret) 149 batch->base.relocs++; 150 151 return ret; 152 } 153 154 static void 155 i915_drm_throttle(struct i915_drm_winsys *idws) 156 { 157 drmIoctl(idws->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL); 158 } 159 160 static void 161 i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, 162 struct pipe_fence_handle **fence) 163 { 164 struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); 165 unsigned used; 166 int ret; 167 168 /* MI_BATCH_BUFFER_END */ 169 i915_winsys_batchbuffer_dword_unchecked(ibatch, (0xA<<23)); 170 171 used = batch->base.ptr - batch->base.map; 172 if (used & 4) { 173 /* MI_NOOP */ 174 i915_winsys_batchbuffer_dword_unchecked(ibatch, 0); 175 used += 4; 176 } 177 178 /* Do the sending to HW */ 179 ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map); 180 if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd) 181 ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); 182 183 i915_drm_throttle(i915_drm_winsys(ibatch->iws)); 184 185 if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) { 186 i915_dump_batchbuffer(ibatch); 187 assert(ret == 0); 188 } 189 190 if (i915_drm_winsys(ibatch->iws)->dump_raw_file) { 191 FILE *file = fopen(i915_drm_winsys(ibatch->iws)->dump_raw_file, "a"); 192 if (file) { 193 fwrite(batch->base.map, used, 1, file); 194 fclose(file); 195 } 196 } 197 198 #ifdef INTEL_RUN_SYNC 199 drm_intel_bo_wait_rendering(batch->bo); 200 #endif 201 202 if (fence) { 203 ibatch->iws->fence_reference(ibatch->iws, fence, NULL); 204 205 #ifdef INTEL_RUN_SYNC 206 /* we run synced to GPU so just pass null */ 207 (*fence) = i915_drm_fence_create(NULL); 208 #else 209 (*fence) = i915_drm_fence_create(batch->bo); 210 #endif 211 } 212 213 i915_drm_batchbuffer_reset(batch); 214 } 215 216 static void 217 i915_drm_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch) 218 { 219 struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); 220 221 if (batch->bo) 222 drm_intel_bo_unreference(batch->bo); 223 224 FREE(batch->base.map); 225 FREE(batch); 226 } 227 228 void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws) 229 { 230 idws->base.batchbuffer_create = i915_drm_batchbuffer_create; 231 idws->base.validate_buffers = i915_drm_batchbuffer_validate_buffers; 232 idws->base.batchbuffer_reloc = i915_drm_batchbuffer_reloc; 233 idws->base.batchbuffer_flush = i915_drm_batchbuffer_flush; 234 idws->base.batchbuffer_destroy = i915_drm_batchbuffer_destroy; 235 } 236