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 enum i915_winsys_flush_flags flags) 164 { 165 struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); 166 unsigned used; 167 int ret; 168 169 /* MI_BATCH_BUFFER_END */ 170 i915_winsys_batchbuffer_dword_unchecked(ibatch, (0xA<<23)); 171 172 used = batch->base.ptr - batch->base.map; 173 if (used & 4) { 174 /* MI_NOOP */ 175 i915_winsys_batchbuffer_dword_unchecked(ibatch, 0); 176 used += 4; 177 } 178 179 /* Do the sending to HW */ 180 ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map); 181 if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd) 182 ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); 183 184 if (flags & I915_FLUSH_END_OF_FRAME) 185 i915_drm_throttle(i915_drm_winsys(ibatch->iws)); 186 187 if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) { 188 i915_dump_batchbuffer(ibatch); 189 assert(ret == 0); 190 } 191 192 if (i915_drm_winsys(ibatch->iws)->dump_raw_file) { 193 FILE *file = fopen(i915_drm_winsys(ibatch->iws)->dump_raw_file, "a"); 194 if (file) { 195 fwrite(batch->base.map, used, 1, file); 196 fclose(file); 197 } 198 } 199 200 #ifdef INTEL_RUN_SYNC 201 drm_intel_bo_wait_rendering(batch->bo); 202 #endif 203 204 if (fence) { 205 ibatch->iws->fence_reference(ibatch->iws, fence, NULL); 206 207 #ifdef INTEL_RUN_SYNC 208 /* we run synced to GPU so just pass null */ 209 (*fence) = i915_drm_fence_create(NULL); 210 #else 211 (*fence) = i915_drm_fence_create(batch->bo); 212 #endif 213 } 214 215 i915_drm_batchbuffer_reset(batch); 216 } 217 218 static void 219 i915_drm_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch) 220 { 221 struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); 222 223 if (batch->bo) 224 drm_intel_bo_unreference(batch->bo); 225 226 FREE(batch->base.map); 227 FREE(batch); 228 } 229 230 void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws) 231 { 232 idws->base.batchbuffer_create = i915_drm_batchbuffer_create; 233 idws->base.validate_buffers = i915_drm_batchbuffer_validate_buffers; 234 idws->base.batchbuffer_reloc = i915_drm_batchbuffer_reloc; 235 idws->base.batchbuffer_flush = i915_drm_batchbuffer_flush; 236 idws->base.batchbuffer_destroy = i915_drm_batchbuffer_destroy; 237 } 238