Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / state_trackers / gbm / gbm_drm.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Benjamin Franzke <benjaminfranzke@googlemail.com>
26  */
27
28 #include "util/u_memory.h"
29 #include "util/u_inlines.h"
30
31 #include "state_tracker/drm_driver.h"
32
33 #include <unistd.h>
34 #include <sys/types.h>
35
36 #include "gbm_gallium_drmint.h"
37
38 static INLINE enum pipe_format
39 gbm_format_to_gallium(enum gbm_bo_format format)
40 {
41    switch (format) {
42    case GBM_BO_FORMAT_XRGB8888:
43       return PIPE_FORMAT_B8G8R8X8_UNORM;
44    case GBM_BO_FORMAT_ARGB8888:
45       return PIPE_FORMAT_B8G8R8A8_UNORM;
46    default:
47       return PIPE_FORMAT_NONE;
48    }
49
50    return PIPE_FORMAT_NONE;
51 }
52
53 static INLINE uint
54 gbm_usage_to_gallium(uint usage)
55 {
56    uint resource_usage = 0;
57
58    if (usage & GBM_BO_USE_SCANOUT)
59       resource_usage |= PIPE_BIND_SCANOUT;
60
61    if (usage & GBM_BO_USE_RENDERING)
62       resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
63
64    if (usage & GBM_BO_USE_CURSOR_64X64)
65       resource_usage |= PIPE_BIND_CURSOR;
66
67    return resource_usage;
68 }
69
70 static int
71 gbm_gallium_drm_is_format_supported(struct gbm_device *gbm,
72                                     enum gbm_bo_format format,
73                                     uint32_t usage)
74 {
75    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
76    enum pipe_format pf;
77
78    pf = gbm_format_to_gallium(format);
79    if (pf == PIPE_FORMAT_NONE)
80       return 0;
81
82    if (!gdrm->screen->is_format_supported(gdrm->screen, PIPE_TEXTURE_2D, pf, 0,
83                                           gbm_usage_to_gallium(usage)))
84       return 0;
85
86    if (usage & GBM_BO_USE_SCANOUT && format != GBM_BO_FORMAT_XRGB8888)
87       return 0;
88
89    return 1;
90 }
91
92 static void
93 gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo)
94 {
95    struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo);
96
97    pipe_resource_reference(&bo->resource, NULL);
98    free(bo);
99 }
100
101 static struct gbm_bo *
102 gbm_gallium_drm_bo_create_from_egl_image(struct gbm_device *gbm,
103                                          void *egl_dpy, void *egl_image,
104                                          uint32_t width, uint32_t height,
105                                          uint32_t usage)
106 {
107    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
108    struct gbm_gallium_drm_bo *bo;
109    struct winsys_handle whandle;
110
111    if (!gdrm->lookup_egl_image)
112       return NULL;
113
114    bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
115    if (bo == NULL)
116       return NULL;
117
118    bo->resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data,
119                                          egl_image);
120    if (bo->resource == NULL) {
121       FREE(bo);
122       return NULL;
123    }
124
125    bo->base.base.gbm = gbm;
126    bo->base.base.width = width;
127    bo->base.base.height = height;
128
129    memset(&whandle, 0, sizeof(whandle));
130    whandle.type = DRM_API_HANDLE_TYPE_KMS;
131    gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
132
133    bo->base.base.handle.u32 = whandle.handle;
134    bo->base.base.pitch      = whandle.stride;
135
136    return &bo->base.base;
137 }
138
139 static struct gbm_bo *
140 gbm_gallium_drm_bo_create(struct gbm_device *gbm,
141                           uint32_t width, uint32_t height,
142                           enum gbm_bo_format format, uint32_t usage)
143 {
144    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
145    struct gbm_gallium_drm_bo *bo;
146    struct pipe_resource templ;
147    struct winsys_handle whandle;
148    enum pipe_format pf;
149
150    bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
151    if (bo == NULL)
152       return NULL;
153
154    bo->base.base.gbm = gbm;
155    bo->base.base.width = width;
156    bo->base.base.height = height;
157
158    pf = gbm_format_to_gallium(format);
159    if (pf == PIPE_FORMAT_NONE)
160       return NULL;
161
162    memset(&templ, 0, sizeof(templ));
163    templ.bind = gbm_usage_to_gallium(usage);
164    templ.format = pf;
165    templ.target = PIPE_TEXTURE_2D;
166    templ.last_level = 0;
167    templ.width0 = width;
168    templ.height0 = height;
169    templ.depth0 = 1;
170    templ.array_size = 1;
171
172    bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ);
173    if (bo->resource == NULL) {
174       FREE(bo);
175       return NULL;
176    }
177
178    memset(&whandle, 0, sizeof(whandle));
179    whandle.type = DRM_API_HANDLE_TYPE_KMS;
180    gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
181
182    bo->base.base.handle.u32 = whandle.handle;
183    bo->base.base.pitch      = whandle.stride;
184
185    return &bo->base.base;
186 }
187
188 static void
189 gbm_gallium_drm_destroy(struct gbm_device *gbm)
190 {
191    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
192
193    gdrm->screen->destroy(gdrm->screen);
194
195    FREE(gdrm->base.driver_name);
196
197    FREE(gdrm);
198 }
199
200 struct gbm_device *
201 gbm_gallium_drm_device_create(int fd)
202 {
203    struct gbm_gallium_drm_device *gdrm;
204    int ret;
205
206    gdrm = calloc(1, sizeof *gdrm);
207
208    gdrm->base.base.fd = fd;
209    gdrm->base.base.bo_create = gbm_gallium_drm_bo_create;
210    gdrm->base.base.bo_create_from_egl_image =
211       gbm_gallium_drm_bo_create_from_egl_image;
212    gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy;
213    gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported;
214    gdrm->base.base.destroy = gbm_gallium_drm_destroy;
215
216    gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM;
217    gdrm->base.base.name = "drm";
218
219    ret = gallium_screen_create(gdrm);
220    if (ret) {
221       free(gdrm);
222       return NULL;
223    }
224
225    return &gdrm->base.base;
226 }