OSDN Git Service

add GBM_BO_USE_LINEAR flag for bo creation
[android-x86/external-minigbm.git] / i915.c
1 /*
2  * Copyright (c) 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.
5  */
6
7 #ifdef GBM_I915
8
9 #include <stdio.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <xf86drm.h>
14 #include <i915_drm.h>
15
16 #include "gbm_priv.h"
17 #include "helpers.h"
18 #include "util.h"
19
20 struct gbm_i915_device
21 {
22         int gen;
23 };
24
25
26 static int get_gen(int device_id)
27 {
28         const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
29                                      0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
30         unsigned i;
31         for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
32                 if (gen3_ids[i] == device_id)
33                         return 3;
34
35         return 4;
36 }
37
38 int gbm_i915_init(struct gbm_device *gbm)
39 {
40         struct gbm_i915_device *i915_gbm;
41         drm_i915_getparam_t get_param;
42         int device_id;
43         int ret;
44
45         i915_gbm = (struct gbm_i915_device*)malloc(sizeof(*i915_gbm));
46         if (!i915_gbm)
47                 return -1;
48
49         memset(&get_param, 0, sizeof(get_param));
50         get_param.param = I915_PARAM_CHIPSET_ID;
51         get_param.value = &device_id;
52         ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
53         if (ret) {
54                 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GETPARAM failed\n");
55                 free(i915_gbm);
56                 return -1;
57         }
58
59         i915_gbm->gen = get_gen(device_id);
60
61         gbm->priv = i915_gbm;
62
63         return 0;
64 }
65
66 void gbm_i915_close(struct gbm_device *gbm)
67 {
68         free(gbm->priv);
69         gbm->priv = NULL;
70 }
71
72 static void i915_align_dimensions(struct gbm_device *gbm, uint32_t tiling_mode,
73                                   uint32_t *width, uint32_t *height, int bpp)
74 {
75         struct gbm_i915_device *i915_gbm = (struct gbm_i915_device *)gbm->priv;
76         uint32_t width_alignment = 4, height_alignment = 4;
77
78         switch(tiling_mode) {
79                 default:
80                 case I915_TILING_NONE:
81                         width_alignment = 64 / bpp;
82                         break;
83
84                 case I915_TILING_X:
85                         width_alignment = 512 / bpp;
86                         height_alignment = 8;
87                         break;
88
89                 case I915_TILING_Y:
90                         if (i915_gbm->gen == 3) {
91                                 width_alignment = 512 / bpp;
92                                 height_alignment = 8;
93                         } else  {
94                                 width_alignment = 128 / bpp;
95                                 height_alignment = 32;
96                         }
97                         break;
98         }
99
100         if (i915_gbm->gen > 3) {
101                 *width = ALIGN(*width, width_alignment);
102                 *height = ALIGN(*height, height_alignment);
103         } else {
104                 uint32_t w;
105                 for (w = width_alignment; w < *width;  w <<= 1)
106                         ;
107                 *width = w;
108                 *height = ALIGN(*height, height_alignment);
109         }
110 }
111
112 static int i915_verify_dimensions(struct gbm_device *gbm, uint32_t stride,
113                                   uint32_t height)
114 {
115         struct gbm_i915_device *i915_gbm = (struct gbm_i915_device *)gbm->priv;
116         if (i915_gbm->gen <= 3 && stride > 8192)
117                 return 0;
118
119         return 1;
120 }
121
122 int gbm_i915_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height,
123                        uint32_t format, uint32_t flags)
124 {
125         struct gbm_device *gbm = bo->gbm;
126         int bpp = gbm_stride_from_format(format, 1);
127         struct drm_i915_gem_create gem_create;
128         struct drm_i915_gem_set_tiling gem_set_tiling;
129         uint32_t tiling_mode = I915_TILING_NONE;
130         size_t size;
131         int ret;
132
133         if (flags & (GBM_BO_USE_CURSOR | GBM_BO_USE_LINEAR))
134                 tiling_mode = I915_TILING_NONE;
135         else if (flags & GBM_BO_USE_SCANOUT)
136                 tiling_mode = I915_TILING_X;
137         else if (flags & GBM_BO_USE_RENDERING)
138                 tiling_mode = I915_TILING_Y;
139
140         i915_align_dimensions(gbm, tiling_mode, &width, &height, bpp);
141
142         bo->strides[0] = width * bpp;
143
144         if (!i915_verify_dimensions(gbm, bo->strides[0], height))
145                 return EINVAL;
146
147         memset(&gem_create, 0, sizeof(gem_create));
148         size = width * height * bpp;
149         gem_create.size = size;
150
151         ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
152         if (ret) {
153                 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GEM_CREATE failed "
154                                 "(size=%zu)\n", size);
155                 return ret;
156         }
157         bo->handles[0].u32 = gem_create.handle;
158         bo->sizes[0] = size;
159         bo->offsets[0] = 0;
160
161         memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
162         do {
163                 gem_set_tiling.handle = bo->handles[0].u32;
164                 gem_set_tiling.tiling_mode = tiling_mode;
165                 gem_set_tiling.stride = bo->strides[0];
166                 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING,
167                                &gem_set_tiling);
168         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
169
170         if (ret == -1) {
171                 struct drm_gem_close gem_close;
172                 gem_close.handle = bo->handles[0].u32;
173                 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GEM_SET_TILING failed "
174                                 "errno=%x (handle=%x, tiling=%x, stride=%x)\n",
175                                 errno,
176                                 gem_set_tiling.handle,
177                                 gem_set_tiling.tiling_mode,
178                                 gem_set_tiling.stride);
179                 drmIoctl(gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
180                 return -errno;
181         }
182
183         return 0;
184 }
185
186 const struct gbm_driver gbm_driver_i915 =
187 {
188         .name = "i915",
189         .init = gbm_i915_init,
190         .close = gbm_i915_close,
191         .bo_create = gbm_i915_bo_create,
192         .bo_destroy = gbm_gem_bo_destroy,
193         .format_list = {
194                 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
195                 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR},
196                 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
197                 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR},
198                 {GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
199                 {GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
200                 {GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
201                 {GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
202                 {GBM_FORMAT_RGB565,   GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
203                 {GBM_FORMAT_UYVY,     GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
204                 {GBM_FORMAT_UYVY,     GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR},
205                 {GBM_FORMAT_YUYV,     GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
206                 {GBM_FORMAT_YUYV,     GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR},
207         }
208 };
209
210 #endif