OSDN Git Service

nouveau: update against libdrm_nouveau-2.0
[android-x86/external-drm_gralloc.git] / gralloc_drm_freedreno.c
1 /*
2  * Copyright (C) 2011 Chia-I Wu <olvaffe@gmail.com>
3  * Copyright (C) 2011 LunarG Inc.
4  * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
5  *
6  * Based on xf86-video-nouveau, which has
7  *
8  * Copyright © 2007 Red Hat, Inc.
9  * Copyright © 2008 Maarten Maathuis
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  */
29
30 #define LOG_TAG "GRALLOC-FREEDRENO"
31
32 #include <cutils/log.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <drm.h>
36 #include <freedreno_drmif.h>
37
38 #include "gralloc_drm.h"
39 #include "gralloc_drm_priv.h"
40
41 struct fd_info {
42         struct gralloc_drm_drv_t base;
43
44         int fd;
45         struct fd_device *dev;
46 };
47
48 struct fd_buffer {
49         struct gralloc_drm_bo_t base;
50
51         struct fd_bo *bo;
52 };
53
54 static struct fd_bo *alloc_bo(struct fd_info *info,
55                 int width, int height, int cpp, int usage, int *pitch)
56 {
57         struct fd_bo *bo = NULL;
58         int flags, size;
59
60         /* TODO need a scanout flag if (usage & GRALLOC_USAGE_HW_FB).. */
61         flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE;
62
63         *pitch = ALIGN(width, 32) * cpp;
64         size = *pitch * height;
65
66         return fd_bo_new(info->dev, size, flags);
67 }
68
69 static struct gralloc_drm_bo_t *
70 fd_alloc(struct gralloc_drm_drv_t *drv, struct gralloc_drm_handle_t *handle)
71 {
72         struct fd_info *info = (struct fd_info *) drv;
73         struct fd_buffer *fd_buf;
74         int cpp;
75
76         cpp = gralloc_drm_get_bpp(handle->format);
77         if (!cpp) {
78                 ALOGE("unrecognized format 0x%x", handle->format);
79                 return NULL;
80         }
81
82         fd_buf = calloc(1, sizeof(*fd_buf));
83         if (!fd_buf)
84                 return NULL;
85
86         if (handle->name) {
87                 fd_buf->bo = fd_bo_from_name(info->dev, handle->name);
88                 if (!fd_buf->bo) {
89                         ALOGE("failed to create fd bo from name %u",
90                                         handle->name);
91                         free(fd_buf);
92                         return NULL;
93                 }
94         }
95         else {
96                 int width, height, pitch;
97
98                 width = handle->width;
99                 height = handle->height;
100                 gralloc_drm_align_geometry(handle->format, &width, &height);
101
102                 fd_buf->bo = alloc_bo(info, width, height,
103                                 cpp, handle->usage, &pitch);
104                 if (!fd_buf->bo) {
105                         ALOGE("failed to allocate fd bo %dx%dx%d",
106                                         handle->width, handle->height, cpp);
107                         free(fd_buf);
108                         return NULL;
109                 }
110
111                 if (fd_bo_get_name(fd_buf->bo, (uint32_t *) &handle->name)) {
112                         ALOGE("failed to flink fd bo");
113                         fd_bo_del(fd_buf->bo);
114                         free(fd_buf);
115                         return NULL;
116                 }
117
118                 handle->stride = pitch;
119         }
120
121         if (handle->usage & GRALLOC_USAGE_HW_FB)
122                 fd_buf->base.fb_handle = fd_bo_handle(fd_buf->bo);
123
124         fd_buf->base.handle = handle;
125
126         return &fd_buf->base;
127 }
128
129 static void fd_free(struct gralloc_drm_drv_t *drv,
130                 struct gralloc_drm_bo_t *bo)
131 {
132         struct fd_buffer *fd_buf = (struct fd_buffer *) bo;
133         fd_bo_del(fd_buf->bo);
134         free(fd_buf);
135 }
136
137 static int fd_map(struct gralloc_drm_drv_t *drv,
138                 struct gralloc_drm_bo_t *bo, int x, int y, int w, int h,
139                 int enable_write, void **addr)
140 {
141         struct fd_buffer *fd_buf = (struct fd_buffer *) bo;
142         if (fd_bo_map(fd_buf->bo))
143                 return 0;
144         return -errno;
145 }
146
147 static void fd_unmap(struct gralloc_drm_drv_t *drv,
148                 struct gralloc_drm_bo_t *bo)
149 {
150         // TODO should add fd_bo_unmap() to libdrm_freedreno someday..
151 }
152
153 static void fd_init_kms_features(struct gralloc_drm_drv_t *drv,
154                 struct gralloc_drm_t *drm)
155 {
156         struct fd_info *info = (struct fd_info *) drv;
157
158         switch (drm->primary.fb_format) {
159         case HAL_PIXEL_FORMAT_BGRA_8888:
160         case HAL_PIXEL_FORMAT_RGB_565:
161                 break;
162         default:
163                 drm->primary.fb_format = HAL_PIXEL_FORMAT_BGRA_8888;
164                 break;
165         }
166
167         drm->mode_quirk_vmwgfx = 0;
168         drm->swap_mode = DRM_SWAP_FLIP;
169         drm->mode_sync_flip = 1;
170         drm->swap_interval = 1;
171         drm->vblank_secondary = 0;
172 }
173
174 static void fd_destroy(struct gralloc_drm_drv_t *drv)
175 {
176         struct fd_info *info = (struct fd_info *) drv;
177         fd_device_del(info->dev);
178         free(info);
179 }
180
181 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_freedreno(int fd)
182 {
183         struct fd_info *info;
184         int err;
185
186         info = calloc(1, sizeof(*info));
187         if (!info)
188                 return NULL;
189
190         info->fd = fd;
191         info->dev = fd_device_new_dup(info->fd);
192         if (!info->dev) {
193                 ALOGE("failed to create fd device");
194                 free(info);
195                 return NULL;
196         }
197
198         info->base.destroy = fd_destroy;
199         info->base.init_kms_features = fd_init_kms_features;
200         info->base.alloc = fd_alloc;
201         info->base.free = fd_free;
202         info->base.map = fd_map;
203         info->base.unmap = fd_unmap;
204
205         return &info->base;
206 }