OSDN Git Service

minigbm: remove GBM_BO_USE_WRITE from the drivers.
[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 static 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 static 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 static int gbm_i915_bo_create(struct gbm_bo *bo,
123                               uint32_t width, uint32_t height,
124                               uint32_t format, uint32_t flags)
125 {
126         struct gbm_device *gbm = bo->gbm;
127         int bpp = gbm_stride_from_format(format, 1);
128         struct drm_i915_gem_create gem_create;
129         struct drm_i915_gem_set_tiling gem_set_tiling;
130         uint32_t tiling_mode = I915_TILING_NONE;
131         size_t size;
132         int ret;
133
134         if (flags & (GBM_BO_USE_CURSOR | GBM_BO_USE_LINEAR))
135                 tiling_mode = I915_TILING_NONE;
136         else if (flags & GBM_BO_USE_SCANOUT)
137                 tiling_mode = I915_TILING_X;
138         else if (flags & GBM_BO_USE_RENDERING)
139                 tiling_mode = I915_TILING_Y;
140
141         i915_align_dimensions(gbm, tiling_mode, &width, &height, bpp);
142
143         bo->strides[0] = width * bpp;
144
145         if (!i915_verify_dimensions(gbm, bo->strides[0], height))
146                 return EINVAL;
147
148         memset(&gem_create, 0, sizeof(gem_create));
149         size = width * height * bpp;
150         gem_create.size = size;
151
152         ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
153         if (ret) {
154                 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GEM_CREATE failed "
155                                 "(size=%zu)\n", size);
156                 return ret;
157         }
158         bo->handles[0].u32 = gem_create.handle;
159         bo->sizes[0] = size;
160         bo->offsets[0] = 0;
161
162         memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
163         do {
164                 gem_set_tiling.handle = bo->handles[0].u32;
165                 gem_set_tiling.tiling_mode = tiling_mode;
166                 gem_set_tiling.stride = bo->strides[0];
167                 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING,
168                                &gem_set_tiling);
169         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
170
171         if (ret == -1) {
172                 struct drm_gem_close gem_close;
173                 gem_close.handle = bo->handles[0].u32;
174                 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GEM_SET_TILING failed "
175                                 "errno=%x (handle=%x, tiling=%x, stride=%x)\n",
176                                 errno,
177                                 gem_set_tiling.handle,
178                                 gem_set_tiling.tiling_mode,
179                                 gem_set_tiling.stride);
180                 drmIoctl(gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
181                 return -errno;
182         }
183
184         return 0;
185 }
186
187 const struct gbm_driver gbm_driver_i915 =
188 {
189         .name = "i915",
190         .init = gbm_i915_init,
191         .close = gbm_i915_close,
192         .bo_create = gbm_i915_bo_create,
193         .bo_destroy = gbm_gem_bo_destroy,
194         .format_list = {
195                 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
196                 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_LINEAR},
197                 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
198                 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_LINEAR},
199                 {GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
200                 {GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
201                 {GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
202                 {GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
203                 {GBM_FORMAT_RGB565,   GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING},
204                 {GBM_FORMAT_UYVY,     GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING},
205                 {GBM_FORMAT_UYVY,     GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR},
206                 {GBM_FORMAT_YUYV,     GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING},
207                 {GBM_FORMAT_YUYV,     GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR},
208                 {GBM_FORMAT_R8,       GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR},
209                 {GBM_FORMAT_GR88,     GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR},
210         }
211 };
212
213 #endif