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