util: Move gallium's PIPE_FORMAT utils to /util/format/
[mesa.git] / src / mesa / state_tracker / st_cb_eglimage.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2010 LunarG Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "main/errors.h"
29 #include "main/texobj.h"
30 #include "main/teximage.h"
31 #include "util/u_inlines.h"
32 #include "util/format/u_format.h"
33 #include "st_cb_eglimage.h"
34 #include "st_cb_fbo.h"
35 #include "st_context.h"
36 #include "st_texture.h"
37 #include "st_format.h"
38 #include "st_manager.h"
39 #include "st_sampler_view.h"
40 #include "util/u_surface.h"
41
42 static bool
43 is_format_supported(struct pipe_screen *screen, enum pipe_format format,
44 unsigned nr_samples, unsigned nr_storage_samples,
45 unsigned usage)
46 {
47 bool supported = screen->is_format_supported(screen, format, PIPE_TEXTURE_2D,
48 nr_samples, nr_storage_samples,
49 usage);
50
51 /* for sampling, some formats can be emulated.. it doesn't matter that
52 * the surface will have a format that the driver can't cope with because
53 * we'll give it sampler view formats that it can deal with and generate
54 * a shader variant that converts.
55 */
56 if ((usage == PIPE_BIND_SAMPLER_VIEW) && !supported) {
57 switch (format) {
58 case PIPE_FORMAT_IYUV:
59 supported = screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM,
60 PIPE_TEXTURE_2D, nr_samples,
61 nr_storage_samples, usage);
62 break;
63 case PIPE_FORMAT_NV12:
64 supported = screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM,
65 PIPE_TEXTURE_2D, nr_samples,
66 nr_storage_samples, usage) &&
67 screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM,
68 PIPE_TEXTURE_2D, nr_samples,
69 nr_storage_samples, usage);
70 break;
71 case PIPE_FORMAT_P016:
72 supported = screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM,
73 PIPE_TEXTURE_2D, nr_samples,
74 nr_storage_samples, usage) &&
75 screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM,
76 PIPE_TEXTURE_2D, nr_samples,
77 nr_storage_samples, usage);
78 break;
79 case PIPE_FORMAT_YUYV:
80 supported = screen->is_format_supported(screen, PIPE_FORMAT_RG88_UNORM,
81 PIPE_TEXTURE_2D, nr_samples,
82 nr_storage_samples, usage) &&
83 screen->is_format_supported(screen, PIPE_FORMAT_BGRA8888_UNORM,
84 PIPE_TEXTURE_2D, nr_samples,
85 nr_storage_samples, usage);
86 break;
87 case PIPE_FORMAT_UYVY:
88 supported = screen->is_format_supported(screen, PIPE_FORMAT_RG88_UNORM,
89 PIPE_TEXTURE_2D, nr_samples,
90 nr_storage_samples, usage) &&
91 screen->is_format_supported(screen, PIPE_FORMAT_RGBA8888_UNORM,
92 PIPE_TEXTURE_2D, nr_samples,
93 nr_storage_samples, usage);
94 break;
95 case PIPE_FORMAT_AYUV:
96 supported = screen->is_format_supported(screen, PIPE_FORMAT_RGBA8888_UNORM,
97 PIPE_TEXTURE_2D, nr_samples,
98 nr_storage_samples, usage);
99 break;
100 case PIPE_FORMAT_XYUV:
101 supported = screen->is_format_supported(screen, PIPE_FORMAT_RGBX8888_UNORM,
102 PIPE_TEXTURE_2D, nr_samples,
103 nr_storage_samples, usage);
104 break;
105 default:
106 break;
107 }
108 }
109
110 return supported;
111 }
112
113 /**
114 * Return the gallium texture of an EGLImage.
115 */
116 static bool
117 st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle,
118 unsigned usage, const char *error, struct st_egl_image *out)
119 {
120 struct st_context *st = st_context(ctx);
121 struct pipe_screen *screen = st->pipe->screen;
122 struct st_manager *smapi =
123 (struct st_manager *) st->iface.st_context_private;
124
125 if (!smapi || !smapi->get_egl_image)
126 return false;
127
128 memset(out, 0, sizeof(*out));
129 if (!smapi->get_egl_image(smapi, (void *) image_handle, out)) {
130 /* image_handle does not refer to a valid EGL image object */
131 _mesa_error(ctx, GL_INVALID_VALUE, "%s(image handle not found)", error);
132 return false;
133 }
134
135 if (!is_format_supported(screen, out->format, out->texture->nr_samples,
136 out->texture->nr_storage_samples, usage)) {
137 /* unable to specify a texture object using the specified EGL image */
138 pipe_resource_reference(&out->texture, NULL);
139 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format not supported)", error);
140 return false;
141 }
142
143 return true;
144 }
145
146 /**
147 * Return the base format just like _mesa_base_fbo_format does.
148 */
149 static GLenum
150 st_pipe_format_to_base_format(enum pipe_format format)
151 {
152 GLenum base_format;
153
154 if (util_format_is_depth_or_stencil(format)) {
155 if (util_format_is_depth_and_stencil(format)) {
156 base_format = GL_DEPTH_STENCIL;
157 }
158 else {
159 if (format == PIPE_FORMAT_S8_UINT)
160 base_format = GL_STENCIL_INDEX;
161 else
162 base_format = GL_DEPTH_COMPONENT;
163 }
164 }
165 else {
166 /* is this enough? */
167 if (util_format_has_alpha(format))
168 base_format = GL_RGBA;
169 else
170 base_format = GL_RGB;
171 }
172
173 return base_format;
174 }
175
176 static void
177 st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
178 struct gl_renderbuffer *rb,
179 GLeglImageOES image_handle)
180 {
181 struct st_renderbuffer *strb = st_renderbuffer(rb);
182 struct st_egl_image stimg;
183
184 if (st_get_egl_image(ctx, image_handle, PIPE_BIND_RENDER_TARGET,
185 "glEGLImageTargetRenderbufferStorage",
186 &stimg)) {
187 struct pipe_context *pipe = st_context(ctx)->pipe;
188 struct pipe_surface *ps, surf_tmpl;
189
190 u_surface_default_template(&surf_tmpl, stimg.texture);
191 surf_tmpl.format = stimg.format;
192 surf_tmpl.u.tex.level = stimg.level;
193 surf_tmpl.u.tex.first_layer = stimg.layer;
194 surf_tmpl.u.tex.last_layer = stimg.layer;
195 ps = pipe->create_surface(pipe, stimg.texture, &surf_tmpl);
196 pipe_resource_reference(&stimg.texture, NULL);
197
198 if (!ps)
199 return;
200
201 strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
202 strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
203 strb->Base.InternalFormat = strb->Base._BaseFormat;
204
205 st_set_ws_renderbuffer_surface(strb, ps);
206 pipe_surface_reference(&ps, NULL);
207 }
208 }
209
210 static void
211 st_bind_egl_image(struct gl_context *ctx,
212 struct gl_texture_object *texObj,
213 struct gl_texture_image *texImage,
214 struct st_egl_image *stimg)
215 {
216 struct st_context *st = st_context(ctx);
217 struct st_texture_object *stObj;
218 struct st_texture_image *stImage;
219 GLenum internalFormat;
220 mesa_format texFormat;
221
222 /* map pipe format to base format */
223 if (util_format_get_component_bits(stimg->format,
224 UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
225 internalFormat = GL_RGBA;
226 else
227 internalFormat = GL_RGB;
228
229 stObj = st_texture_object(texObj);
230 stImage = st_texture_image(texImage);
231
232 /* switch to surface based */
233 if (!stObj->surface_based) {
234 _mesa_clear_texture_object(ctx, texObj, NULL);
235 stObj->surface_based = GL_TRUE;
236 }
237
238 /* TODO RequiredTextureImageUnits should probably be reset back
239 * to 1 somewhere if different texture is bound??
240 */
241 switch (stimg->format) {
242 case PIPE_FORMAT_NV12:
243 texFormat = MESA_FORMAT_R_UNORM8;
244 texObj->RequiredTextureImageUnits = 2;
245 break;
246 case PIPE_FORMAT_P016:
247 texFormat = MESA_FORMAT_R_UNORM16;
248 texObj->RequiredTextureImageUnits = 2;
249 break;
250 case PIPE_FORMAT_IYUV:
251 texFormat = MESA_FORMAT_R_UNORM8;
252 texObj->RequiredTextureImageUnits = 3;
253 break;
254 case PIPE_FORMAT_YUYV:
255 case PIPE_FORMAT_UYVY:
256 texFormat = MESA_FORMAT_RG_UNORM8;
257 texObj->RequiredTextureImageUnits = 2;
258 break;
259 case PIPE_FORMAT_AYUV:
260 texFormat = MESA_FORMAT_R8G8B8A8_UNORM;
261 internalFormat = GL_RGBA;
262 texObj->RequiredTextureImageUnits = 1;
263 break;
264 case PIPE_FORMAT_XYUV:
265 texFormat = MESA_FORMAT_R8G8B8X8_UNORM;
266 texObj->RequiredTextureImageUnits = 1;
267 break;
268 default:
269 texFormat = st_pipe_format_to_mesa_format(stimg->format);
270 break;
271 }
272 assert(texFormat != MESA_FORMAT_NONE);
273
274 /* Minify texture size based on level set on the EGLImage. */
275 uint32_t width = u_minify(stimg->texture->width0, stimg->level);
276 uint32_t height = u_minify(stimg->texture->height0, stimg->level);
277
278 _mesa_init_teximage_fields(ctx, texImage, width, height,
279 1, 0, internalFormat, texFormat);
280
281 pipe_resource_reference(&stObj->pt, stimg->texture);
282 st_texture_release_all_sampler_views(st, stObj);
283 pipe_resource_reference(&stImage->pt, stObj->pt);
284 if (st->pipe->screen->resource_changed)
285 st->pipe->screen->resource_changed(st->pipe->screen, stImage->pt);
286
287 stObj->surface_format = stimg->format;
288 stObj->level_override = stimg->level;
289 stObj->layer_override = stimg->layer;
290
291 _mesa_dirty_texobj(ctx, texObj);
292 }
293
294 static void
295 st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target,
296 struct gl_texture_object *texObj,
297 struct gl_texture_image *texImage,
298 GLeglImageOES image_handle)
299 {
300 struct st_egl_image stimg;
301
302 if (!st_get_egl_image(ctx, image_handle, PIPE_BIND_SAMPLER_VIEW,
303 "glEGLImageTargetTexture2D", &stimg))
304 return;
305
306 st_bind_egl_image(ctx, texObj, texImage, &stimg);
307 pipe_resource_reference(&stimg.texture, NULL);
308 }
309
310 void
311 st_init_eglimage_functions(struct dd_function_table *functions)
312 {
313 functions->EGLImageTargetTexture2D = st_egl_image_target_texture_2d;
314 functions->EGLImageTargetRenderbufferStorage = st_egl_image_target_renderbuffer_storage;
315 }