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[18] = {
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},
62 drm_intel_bufmgr *mgr;
68 drm_intel_bo *ibos[DRV_MAX_PLANES];
71 static int get_gen(int device_id)
73 const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
74 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
76 for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
77 if (gen3_ids[i] == device_id)
83 static void i915_align_dimensions(struct driver *drv, uint32_t tiling_mode,
84 uint32_t *width, uint32_t *height, int bpp)
86 struct i915_device *i915_dev = (struct i915_device *)drv->priv;
87 uint32_t width_alignment = 4, height_alignment = 4;
89 switch (tiling_mode) {
91 case I915_TILING_NONE:
92 width_alignment = 64 / bpp;
96 width_alignment = 512 / bpp;
101 if (i915_dev->gen == 3) {
102 width_alignment = 512 / bpp;
103 height_alignment = 8;
105 width_alignment = 128 / bpp;
106 height_alignment = 32;
111 if (i915_dev->gen > 3) {
112 *width = ALIGN(*width, width_alignment);
113 *height = ALIGN(*height, height_alignment);
116 for (w = width_alignment; w < *width; w <<= 1)
119 *height = ALIGN(*height, height_alignment);
123 static int i915_verify_dimensions(struct driver *drv, uint32_t stride,
126 struct i915_device *i915_dev = (struct i915_device *)drv->priv;
127 if (i915_dev->gen <= 3 && stride > 8192)
133 static int i915_init(struct driver *drv)
135 struct i915_device *i915_dev;
136 drm_i915_getparam_t get_param;
140 i915_dev = calloc(1, sizeof(*i915_dev));
144 memset(&get_param, 0, sizeof(get_param));
145 get_param.param = I915_PARAM_CHIPSET_ID;
146 get_param.value = &device_id;
147 ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
149 fprintf(stderr, "drv: DRM_IOCTL_I915_GETPARAM failed\n");
154 i915_dev->gen = get_gen(device_id);
157 i915_dev->mgr = drm_intel_bufmgr_gem_init(drv->fd, 16 * 1024);
158 if (!i915_dev->mgr) {
159 fprintf(stderr, "drv: drm_intel_bufmgr_gem_init failed\n");
164 drv->priv = i915_dev;
166 drv_insert_combinations(drv, combos, ARRAY_SIZE(combos));
167 return drv_add_kms_flags(drv);
170 static void i915_close(struct driver *drv)
172 struct i915_device *i915_dev = drv->priv;
173 drm_intel_bufmgr_destroy(i915_dev->mgr);
178 static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height,
179 uint32_t format, uint32_t flags)
184 uint32_t tiling_mode;
185 struct i915_bo *i915_bo;
187 int bpp = drv_stride_from_format(format, 1, 0);
188 struct i915_device *i915_dev = (struct i915_device *)bo->drv->priv;
190 if (flags & (BO_USE_CURSOR | BO_USE_LINEAR |
191 BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
192 tiling_mode = I915_TILING_NONE;
193 else if (flags & BO_USE_SCANOUT)
194 tiling_mode = I915_TILING_X;
196 tiling_mode = I915_TILING_Y;
198 i915_align_dimensions(bo->drv, tiling_mode, &width, &height, bpp);
199 drv_bo_from_format(bo, width, height, format);
201 if (!i915_verify_dimensions(bo->drv, bo->strides[0], height))
204 snprintf(name, sizeof(name), "i915-buffer-%u", i915_dev->count);
207 i915_bo = calloc(1, sizeof(*i915_bo));
213 i915_bo->ibos[0] = drm_intel_bo_alloc(i915_dev->mgr, name,
215 if (!i915_bo->ibos[0]) {
216 fprintf(stderr, "drv: drm_intel_bo_alloc failed");
222 for (plane = 0; plane < bo->num_planes; plane++) {
224 drm_intel_bo_reference(i915_bo->ibos[0]);
226 bo->handles[plane].u32 = i915_bo->ibos[0]->handle;
227 i915_bo->ibos[plane] = i915_bo->ibos[0];
230 bo->tiling = tiling_mode;
232 ret = drm_intel_bo_set_tiling(i915_bo->ibos[0], &bo->tiling,
235 if (ret || bo->tiling != tiling_mode) {
236 fprintf(stderr, "drv: drm_intel_gem_bo_set_tiling failed "
237 "errno=%x, stride=%x\n", errno, bo->strides[0]);
238 /* Calls i915 bo destroy. */
239 bo->drv->backend->bo_destroy(bo);
246 static int i915_bo_destroy(struct bo *bo)
249 struct i915_bo *i915_bo = bo->priv;
251 for (plane = 0; plane < bo->num_planes; plane++)
252 drm_intel_bo_unreference(i915_bo->ibos[plane]);
260 static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
264 struct i915_bo *i915_bo;
265 struct i915_device *i915_dev = bo->drv->priv;
267 i915_bo = calloc(1, sizeof(*i915_bo));
274 * When self-importing, libdrm_intel increments the reference count
275 * on the drm_intel_bo. It also returns the same drm_intel_bo per GEM
276 * handle. Thus, we don't need to increase the reference count
277 * (i.e, drv_increment_reference_count) when importing with this
280 for (plane = 0; plane < bo->num_planes; plane++) {
282 i915_bo->ibos[plane] = drm_intel_bo_gem_create_from_prime(i915_dev->mgr,
283 data->fds[plane], data->sizes[plane]);
285 if (!i915_bo->ibos[plane]) {
287 * Need to call GEM close on planes that were opened,
288 * if any. Adjust the num_planes variable to be the
289 * plane that failed, so GEM close will be called on
290 * planes before that plane.
292 bo->num_planes = plane;
294 fprintf(stderr, "drv: i915: failed to import failed");
298 bo->handles[plane].u32 = i915_bo->ibos[plane]->handle;
301 if (drm_intel_bo_get_tiling(i915_bo->ibos[0], &bo->tiling,
303 fprintf(stderr, "drv: drm_intel_bo_get_tiling failed");
311 static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane)
314 struct i915_bo *i915_bo = bo->priv;
316 if (bo->tiling == I915_TILING_NONE)
317 /* TODO(gsingh): use bo_map flags to determine if we should
320 ret = drm_intel_bo_map(i915_bo->ibos[0], 1);
322 ret = drm_intel_gem_bo_map_gtt(i915_bo->ibos[0]);
325 fprintf(stderr, "drv: i915_bo_map failed.");
329 return i915_bo->ibos[0]->virtual;
332 static int i915_bo_unmap(struct bo *bo, struct map_info *data)
335 struct i915_bo *i915_bo = bo->priv;
337 if (bo->tiling == I915_TILING_NONE)
338 ret = drm_intel_bo_unmap(i915_bo->ibos[0]);
340 ret = drm_intel_gem_bo_unmap_gtt(i915_bo->ibos[0]);
345 static uint32_t i915_resolve_format(uint32_t format)
348 case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
349 /*HACK: See b/28671744 */
350 return DRM_FORMAT_XBGR8888;
351 case DRM_FORMAT_FLEX_YCbCr_420_888:
352 return DRM_FORMAT_YVU420;
358 struct backend backend_i915 =
363 .bo_create = i915_bo_create,
364 .bo_destroy = i915_bo_destroy,
365 .bo_import = i915_bo_import,
366 .bo_map = i915_bo_map,
367 .bo_unmap = i915_bo_unmap,
368 .resolve_format = i915_resolve_format,