OSDN Git Service

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