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 8static 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 26static struct i915_winsys_buffer * 27i915_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 49err: 50 assert(0); 51 FREE(buf); 52 return NULL; 53} 54 55static struct i915_winsys_buffer * 56i915_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 85err: 86 assert(0); 87 FREE(buf); 88 return NULL; 89} 90 91static struct i915_winsys_buffer * 92i915_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 119err: 120 FREE(buf); 121 return NULL; 122} 123 124static boolean 125i915_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 151static void * 152i915_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); 170out: 171 if (ret) 172 return NULL; 173 174 buf->map_count++; 175 return buf->ptr; 176} 177 178static void 179i915_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 190static int 191i915_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 202static void 203i915_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 216static boolean 217i915_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 227void 228i915_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