2 * Copyright 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
11 #include <intel_bufmgr.h>
20 static struct supported_combination combos[19] = {
21 {DRM_FORMAT_ARGB1555, DRM_FORMAT_MOD_NONE,
22 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
23 {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_NONE,
24 BO_USE_RENDERING | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
25 {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_NONE,
26 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
27 {DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_NONE,
28 BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
29 {DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_NONE,
30 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
31 {DRM_FORMAT_GR88, DRM_FORMAT_MOD_NONE,
32 BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
33 {DRM_FORMAT_R8, DRM_FORMAT_MOD_NONE,
34 BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
35 {DRM_FORMAT_RGB565, DRM_FORMAT_MOD_NONE,
36 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
37 {DRM_FORMAT_UYVY, DRM_FORMAT_MOD_NONE,
38 BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
39 {DRM_FORMAT_UYVY, DRM_FORMAT_MOD_NONE,
40 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
41 {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_NONE,
42 BO_USE_RENDERING | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
43 {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_NONE,
44 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
45 {DRM_FORMAT_XRGB1555, DRM_FORMAT_MOD_NONE,
46 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
47 {DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE,
48 BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
49 {DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE,
50 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
51 {DRM_FORMAT_YUYV, DRM_FORMAT_MOD_NONE,
52 BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
53 {DRM_FORMAT_YUYV, DRM_FORMAT_MOD_NONE,
54 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
55 {DRM_FORMAT_YVU420, DRM_FORMAT_MOD_NONE,
56 BO_USE_RENDERING | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY},
57 {DRM_FORMAT_YVU420, DRM_FORMAT_MOD_NONE,
58 BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN},
64 drm_intel_bufmgr *mgr;
70 drm_intel_bo *ibos[DRV_MAX_PLANES];
73 static int get_gen(int device_id)
75 const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
76 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
78 for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
79 if (gen3_ids[i] == device_id)
85 static void i915_align_dimensions(struct driver *drv, uint32_t tiling_mode,
86 uint32_t *width, uint32_t *height, int bpp)
88 struct i915_device *i915_dev = (struct i915_device *)drv->priv;
89 uint32_t width_alignment = 4, height_alignment = 4;
91 switch (tiling_mode) {
93 case I915_TILING_NONE:
94 width_alignment = 64 / bpp;
98 width_alignment = 512 / bpp;
103 if (i915_dev->gen == 3) {
104 width_alignment = 512 / bpp;
105 height_alignment = 8;
107 width_alignment = 128 / bpp;
108 height_alignment = 32;
113 if (i915_dev->gen > 3) {
114 *width = ALIGN(*width, width_alignment);
115 *height = ALIGN(*height, height_alignment);
118 for (w = width_alignment; w < *width; w <<= 1)
121 *height = ALIGN(*height, height_alignment);
125 static int i915_verify_dimensions(struct driver *drv, uint32_t stride,
128 struct i915_device *i915_dev = (struct i915_device *)drv->priv;
129 if (i915_dev->gen <= 3 && stride > 8192)
135 static int i915_init(struct driver *drv)
137 struct i915_device *i915_dev;
138 drm_i915_getparam_t get_param;
142 i915_dev = calloc(1, sizeof(*i915_dev));
146 memset(&get_param, 0, sizeof(get_param));
147 get_param.param = I915_PARAM_CHIPSET_ID;
148 get_param.value = &device_id;
149 ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
151 fprintf(stderr, "drv: DRM_IOCTL_I915_GETPARAM failed\n");
156 i915_dev->gen = get_gen(device_id);
159 i915_dev->mgr = drm_intel_bufmgr_gem_init(drv->fd, 16 * 1024);
160 if (!i915_dev->mgr) {
161 fprintf(stderr, "drv: drm_intel_bufmgr_gem_init failed\n");
166 drv->priv = i915_dev;
168 drv_insert_combinations(drv, combos, ARRAY_SIZE(combos));
169 return drv_add_kms_flags(drv);
172 static void i915_close(struct driver *drv)
174 struct i915_device *i915_dev = drv->priv;
175 drm_intel_bufmgr_destroy(i915_dev->mgr);
180 static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height,
181 uint32_t format, uint32_t flags)
186 uint32_t tiling_mode;
187 struct i915_bo *i915_bo;
189 int bpp = drv_stride_from_format(format, 1, 0);
190 struct i915_device *i915_dev = (struct i915_device *)bo->drv->priv;
192 if (flags & (BO_USE_CURSOR | BO_USE_LINEAR |
193 BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
194 tiling_mode = I915_TILING_NONE;
195 else if (flags & BO_USE_SCANOUT)
196 tiling_mode = I915_TILING_X;
198 tiling_mode = I915_TILING_Y;
200 i915_align_dimensions(bo->drv, tiling_mode, &width, &height, bpp);
201 drv_bo_from_format(bo, width, height, format);
203 if (!i915_verify_dimensions(bo->drv, bo->strides[0], height))
206 snprintf(name, sizeof(name), "i915-buffer-%u", i915_dev->count);
209 i915_bo = calloc(1, sizeof(*i915_bo));
215 i915_bo->ibos[0] = drm_intel_bo_alloc(i915_dev->mgr, name,
217 if (!i915_bo->ibos[0]) {
218 fprintf(stderr, "drv: drm_intel_bo_alloc failed");
224 for (plane = 0; plane < bo->num_planes; plane++) {
226 drm_intel_bo_reference(i915_bo->ibos[0]);
228 bo->handles[plane].u32 = i915_bo->ibos[0]->handle;
229 i915_bo->ibos[plane] = i915_bo->ibos[0];
232 bo->tiling = tiling_mode;
234 ret = drm_intel_bo_set_tiling(i915_bo->ibos[0], &bo->tiling,
237 if (ret || bo->tiling != tiling_mode) {
238 fprintf(stderr, "drv: drm_intel_gem_bo_set_tiling failed "
239 "errno=%x, stride=%x\n", errno, bo->strides[0]);
240 /* Calls i915 bo destroy. */
241 bo->drv->backend->bo_destroy(bo);
248 static int i915_bo_destroy(struct bo *bo)
251 struct i915_bo *i915_bo = bo->priv;
253 for (plane = 0; plane < bo->num_planes; plane++)
254 drm_intel_bo_unreference(i915_bo->ibos[plane]);
262 static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
266 struct i915_bo *i915_bo;
267 struct i915_device *i915_dev = bo->drv->priv;
269 i915_bo = calloc(1, sizeof(*i915_bo));
276 * When self-importing, libdrm_intel increments the reference count
277 * on the drm_intel_bo. It also returns the same drm_intel_bo per GEM
278 * handle. Thus, we don't need to increase the reference count
279 * (i.e, drv_increment_reference_count) when importing with this
282 for (plane = 0; plane < bo->num_planes; plane++) {
284 i915_bo->ibos[plane] = drm_intel_bo_gem_create_from_prime(i915_dev->mgr,
285 data->fds[plane], data->sizes[plane]);
287 if (!i915_bo->ibos[plane]) {
289 * Need to call GEM close on planes that were opened,
290 * if any. Adjust the num_planes variable to be the
291 * plane that failed, so GEM close will be called on
292 * planes before that plane.
294 bo->num_planes = plane;
296 fprintf(stderr, "drv: i915: failed to import failed");
300 bo->handles[plane].u32 = i915_bo->ibos[plane]->handle;
303 if (drm_intel_bo_get_tiling(i915_bo->ibos[0], &bo->tiling,
305 fprintf(stderr, "drv: drm_intel_bo_get_tiling failed");
313 static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane)
316 struct i915_bo *i915_bo = bo->priv;
318 if (bo->tiling == I915_TILING_NONE)
319 /* TODO(gsingh): use bo_map flags to determine if we should
322 ret = drm_intel_bo_map(i915_bo->ibos[0], 1);
324 ret = drm_intel_gem_bo_map_gtt(i915_bo->ibos[0]);
327 fprintf(stderr, "drv: i915_bo_map failed.");
331 return i915_bo->ibos[0]->virtual;
334 static int i915_bo_unmap(struct bo *bo, struct map_info *data)
337 struct i915_bo *i915_bo = bo->priv;
339 if (bo->tiling == I915_TILING_NONE)
340 ret = drm_intel_bo_unmap(i915_bo->ibos[0]);
342 ret = drm_intel_gem_bo_unmap_gtt(i915_bo->ibos[0]);
347 static uint32_t i915_resolve_format(uint32_t format)
350 case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
351 /*HACK: See b/28671744 */
352 return DRM_FORMAT_XBGR8888;
353 case DRM_FORMAT_FLEX_YCbCr_420_888:
354 return DRM_FORMAT_YVU420;
360 struct backend backend_i915 =
365 .bo_create = i915_bo_create,
366 .bo_destroy = i915_bo_destroy,
367 .bo_import = i915_bo_import,
368 .bo_map = i915_bo_map,
369 .bo_unmap = i915_bo_unmap,
370 .resolve_format = i915_resolve_format,