i915g: Implement EGL_EXT_image_dma_buf_import
[mesa.git] / src / gallium / winsys / i915 / drm / i915_drm_buffer.c
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 buf = CALLOC_STRUCT(i915_drm_buffer);
105 if (!buf)
106 return NULL;
107
108 buf->magic = 0xDEAD1337;
109
110 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED)
111 buf->bo = drm_intel_bo_gem_create_from_name(idws->gem_manager, "gallium3d_from_handle", whandle->handle);
112 else if (whandle->type == DRM_API_HANDLE_TYPE_FD) {
113 int fd = (int) whandle->handle;
114 buf->bo = drm_intel_bo_gem_create_from_prime(idws->gem_manager, fd, height * whandle->stride);
115 }
116
117 buf->flinked = TRUE;
118 buf->flink = whandle->handle;
119
120 if (!buf->bo)
121 goto err;
122
123 drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle);
124
125 *stride = whandle->stride;
126 *tiling = tile;
127
128 return (struct i915_winsys_buffer *)buf;
129
130 err:
131 FREE(buf);
132 return NULL;
133 }
134
135 static boolean
136 i915_drm_buffer_get_handle(struct i915_winsys *iws,
137 struct i915_winsys_buffer *buffer,
138 struct winsys_handle *whandle,
139 unsigned stride)
140 {
141 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
142
143 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
144 if (!buf->flinked) {
145 if (drm_intel_bo_flink(buf->bo, &buf->flink))
146 return FALSE;
147 buf->flinked = TRUE;
148 }
149
150 whandle->handle = buf->flink;
151 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
152 whandle->handle = buf->bo->handle;
153 } else {
154 assert(!"unknown usage");
155 return FALSE;
156 }
157
158 whandle->stride = stride;
159 return TRUE;
160 }
161
162 static void *
163 i915_drm_buffer_map(struct i915_winsys *iws,
164 struct i915_winsys_buffer *buffer,
165 boolean write)
166 {
167 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
168 drm_intel_bo *bo = intel_bo(buffer);
169 int ret = 0;
170
171 assert(bo);
172
173 if (buf->map_count)
174 goto out;
175
176 ret = drm_intel_gem_bo_map_gtt(bo);
177
178 buf->ptr = bo->virtual;
179
180 assert(ret == 0);
181 out:
182 if (ret)
183 return NULL;
184
185 buf->map_count++;
186 return buf->ptr;
187 }
188
189 static void
190 i915_drm_buffer_unmap(struct i915_winsys *iws,
191 struct i915_winsys_buffer *buffer)
192 {
193 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
194
195 if (--buf->map_count)
196 return;
197
198 drm_intel_gem_bo_unmap_gtt(intel_bo(buffer));
199 }
200
201 static int
202 i915_drm_buffer_write(struct i915_winsys *iws,
203 struct i915_winsys_buffer *buffer,
204 size_t offset,
205 size_t size,
206 const void *data)
207 {
208 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
209
210 return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
211 }
212
213 static void
214 i915_drm_buffer_destroy(struct i915_winsys *iws,
215 struct i915_winsys_buffer *buffer)
216 {
217 drm_intel_bo_unreference(intel_bo(buffer));
218
219 #ifdef DEBUG
220 i915_drm_buffer(buffer)->magic = 0;
221 i915_drm_buffer(buffer)->bo = NULL;
222 #endif
223
224 FREE(buffer);
225 }
226
227 static boolean
228 i915_drm_buffer_is_busy(struct i915_winsys *iws,
229 struct i915_winsys_buffer *buffer)
230 {
231 struct i915_drm_buffer* i915_buffer = i915_drm_buffer(buffer);
232 if (!i915_buffer)
233 return FALSE;
234 return drm_intel_bo_busy(i915_buffer->bo);
235 }
236
237
238 void
239 i915_drm_winsys_init_buffer_functions(struct i915_drm_winsys *idws)
240 {
241 idws->base.buffer_create = i915_drm_buffer_create;
242 idws->base.buffer_create_tiled = i915_drm_buffer_create_tiled;
243 idws->base.buffer_from_handle = i915_drm_buffer_from_handle;
244 idws->base.buffer_get_handle = i915_drm_buffer_get_handle;
245 idws->base.buffer_map = i915_drm_buffer_map;
246 idws->base.buffer_unmap = i915_drm_buffer_unmap;
247 idws->base.buffer_write = i915_drm_buffer_write;
248 idws->base.buffer_destroy = i915_drm_buffer_destroy;
249 idws->base.buffer_is_busy = i915_drm_buffer_is_busy;
250 }