1 #include "state_tracker/drm_driver.h" 2 #include "i915_drm_winsys.h" 3 #include "util/u_memory.h" 4 5 #include "i915_drm.h" 6 7 static char *i915_drm_type_to_name(enum i915_winsys_buffer_type type) 8 { 9 char *name; 10 11 if (type == I915_NEW_TEXTURE) { 12 name = "gallium3d_texture"; 13 } else if (type == I915_NEW_VERTEX) { 14 name = "gallium3d_vertex"; 15 } else if (type == I915_NEW_SCANOUT) { 16 name = "gallium3d_scanout"; 17 } else { 18 assert(0); 19 name = "gallium3d_unknown"; 20 } 21 22 return name; 23 } 24 25 static struct i915_winsys_buffer * 26 i915_drm_buffer_create(struct i915_winsys *iws, 27 unsigned size, 28 enum i915_winsys_buffer_type type) 29 { 30 struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer); 31 struct i915_drm_winsys *idws = i915_drm_winsys(iws); 32 33 if (!buf) 34 return NULL; 35 36 buf->magic = 0xDEAD1337; 37 buf->flinked = FALSE; 38 buf->flink = 0; 39 40 buf->bo = drm_intel_bo_alloc(idws->gem_manager, 41 i915_drm_type_to_name(type), size, 0); 42 43 if (!buf->bo) 44 goto err; 45 46 return (struct i915_winsys_buffer *)buf; 47 48 err: 49 assert(0); 50 FREE(buf); 51 return NULL; 52 } 53 54 static struct i915_winsys_buffer * 55 i915_drm_buffer_create_tiled(struct i915_winsys *iws, 56 unsigned *stride, unsigned height, 57 enum i915_winsys_buffer_tile *tiling, 58 enum i915_winsys_buffer_type type) 59 { 60 struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer); 61 struct i915_drm_winsys *idws = i915_drm_winsys(iws); 62 unsigned long pitch = 0; 63 uint32_t tiling_mode = *tiling; 64 65 if (!buf) 66 return NULL; 67 68 buf->magic = 0xDEAD1337; 69 buf->flinked = FALSE; 70 buf->flink = 0; 71 72 buf->bo = drm_intel_bo_alloc_tiled(idws->gem_manager, 73 i915_drm_type_to_name(type), 74 *stride, height, 1, 75 &tiling_mode, &pitch, 0); 76 77 if (!buf->bo) 78 goto err; 79 80 *stride = pitch; 81 *tiling = tiling_mode; 82 return (struct i915_winsys_buffer *)buf; 83 84 err: 85 assert(0); 86 FREE(buf); 87 return NULL; 88 } 89 90 static struct i915_winsys_buffer * 91 i915_drm_buffer_from_handle(struct i915_winsys *iws, 92 struct winsys_handle *whandle, 93 unsigned height, 94 enum i915_winsys_buffer_tile *tiling, 95 unsigned *stride) 96 { 97 struct i915_drm_winsys *idws = i915_drm_winsys(iws); 98 struct i915_drm_buffer *buf; 99 uint32_t tile = 0, swizzle = 0; 100 101 if ((whandle->type != DRM_API_HANDLE_TYPE_SHARED) && (whandle->type != DRM_API_HANDLE_TYPE_FD)) 102 return NULL; 103 104 if (whandle->offset != 0) 105 return NULL; 106 107 buf = CALLOC_STRUCT(i915_drm_buffer); 108 if (!buf) 109 return NULL; 110 111 buf->magic = 0xDEAD1337; 112 113 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) 114 buf->bo = drm_intel_bo_gem_create_from_name(idws->gem_manager, "gallium3d_from_handle", whandle->handle); 115 else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { 116 int fd = (int) whandle->handle; 117 buf->bo = drm_intel_bo_gem_create_from_prime(idws->gem_manager, fd, height * whandle->stride); 118 } 119 120 buf->flinked = TRUE; 121 buf->flink = whandle->handle; 122 123 if (!buf->bo) 124 goto err; 125 126 drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle); 127 128 *stride = whandle->stride; 129 *tiling = tile; 130 131 return (struct i915_winsys_buffer *)buf; 132 133 err: 134 FREE(buf); 135 return NULL; 136 } 137 138 static boolean 139 i915_drm_buffer_get_handle(struct i915_winsys *iws, 140 struct i915_winsys_buffer *buffer, 141 struct winsys_handle *whandle, 142 unsigned stride) 143 { 144 struct i915_drm_buffer *buf = i915_drm_buffer(buffer); 145 146 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { 147 if (!buf->flinked) { 148 if (drm_intel_bo_flink(buf->bo, &buf->flink)) 149 return FALSE; 150 buf->flinked = TRUE; 151 } 152 153 whandle->handle = buf->flink; 154 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { 155 whandle->handle = buf->bo->handle; 156 } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { 157 int fd; 158 159 if (drm_intel_bo_gem_export_to_prime(buf->bo, &fd)) 160 return FALSE; 161 whandle->handle = fd; 162 } else { 163 assert(!"unknown usage"); 164 return FALSE; 165 } 166 167 whandle->stride = stride; 168 return TRUE; 169 } 170 171 static void * 172 i915_drm_buffer_map(struct i915_winsys *iws, 173 struct i915_winsys_buffer *buffer, 174 boolean write) 175 { 176 struct i915_drm_buffer *buf = i915_drm_buffer(buffer); 177 drm_intel_bo *bo = intel_bo(buffer); 178 int ret = 0; 179 180 assert(bo); 181 182 if (buf->map_count) 183 goto out; 184 185 ret = drm_intel_gem_bo_map_gtt(bo); 186 187 buf->ptr = bo->virtual; 188 189 assert(ret == 0); 190 out: 191 if (ret) 192 return NULL; 193 194 buf->map_count++; 195 return buf->ptr; 196 } 197 198 static void 199 i915_drm_buffer_unmap(struct i915_winsys *iws, 200 struct i915_winsys_buffer *buffer) 201 { 202 struct i915_drm_buffer *buf = i915_drm_buffer(buffer); 203 204 if (--buf->map_count) 205 return; 206 207 drm_intel_gem_bo_unmap_gtt(intel_bo(buffer)); 208 } 209 210 static int 211 i915_drm_buffer_write(struct i915_winsys *iws, 212 struct i915_winsys_buffer *buffer, 213 size_t offset, 214 size_t size, 215 const void *data) 216 { 217 struct i915_drm_buffer *buf = i915_drm_buffer(buffer); 218 219 return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data); 220 } 221 222 static void 223 i915_drm_buffer_destroy(struct i915_winsys *iws, 224 struct i915_winsys_buffer *buffer) 225 { 226 drm_intel_bo_unreference(intel_bo(buffer)); 227 228 #ifdef DEBUG 229 i915_drm_buffer(buffer)->magic = 0; 230 i915_drm_buffer(buffer)->bo = NULL; 231 #endif 232 233 FREE(buffer); 234 } 235 236 static boolean 237 i915_drm_buffer_is_busy(struct i915_winsys *iws, 238 struct i915_winsys_buffer *buffer) 239 { 240 struct i915_drm_buffer* i915_buffer = i915_drm_buffer(buffer); 241 if (!i915_buffer) 242 return FALSE; 243 return drm_intel_bo_busy(i915_buffer->bo); 244 } 245 246 247 void 248 i915_drm_winsys_init_buffer_functions(struct i915_drm_winsys *idws) 249 { 250 idws->base.buffer_create = i915_drm_buffer_create; 251 idws->base.buffer_create_tiled = i915_drm_buffer_create_tiled; 252 idws->base.buffer_from_handle = i915_drm_buffer_from_handle; 253 idws->base.buffer_get_handle = i915_drm_buffer_get_handle; 254 idws->base.buffer_map = i915_drm_buffer_map; 255 idws->base.buffer_unmap = i915_drm_buffer_unmap; 256 idws->base.buffer_write = i915_drm_buffer_write; 257 idws->base.buffer_destroy = i915_drm_buffer_destroy; 258 idws->base.buffer_is_busy = i915_drm_buffer_is_busy; 259 } 260