egl_g3d: add missing param to egl_g3d_st_manager_get_egl_image()
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d_st.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
4 *
5 * Copyright (C) 2010 LunarG Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Chia-I Wu <olv@lunarg.com>
27 */
28
29 #include "util/u_memory.h"
30 #include "util/u_string.h"
31 #include "util/u_inlines.h"
32 #include "util/u_dl.h"
33 #include "egldriver.h"
34 #include "eglimage.h"
35 #include "eglmutex.h"
36
37 #include "egl_g3d.h"
38 #include "egl_g3d_st.h"
39
40 struct egl_g3d_st_manager {
41 struct st_manager base;
42 _EGLDisplay *display;
43 };
44
45 static INLINE struct egl_g3d_st_manager *
46 egl_g3d_st_manager(struct st_manager *smapi)
47 {
48 return (struct egl_g3d_st_manager *) smapi;
49 }
50
51 static struct egl_g3d_st_module {
52 const char *filename;
53 struct util_dl_library *lib;
54 struct st_api *stapi;
55 } egl_g3d_st_modules[ST_API_COUNT];
56
57 static EGLBoolean
58 egl_g3d_search_path_callback(const char *dir, size_t len, void *callback_data)
59 {
60 struct egl_g3d_st_module *stmod =
61 (struct egl_g3d_st_module *) callback_data;
62 char path[1024];
63 int ret;
64
65 ret = util_snprintf(path, sizeof(path),
66 "%.*s/%s", len, dir, stmod->filename);
67 if (ret > 0 && ret < sizeof(path))
68 stmod->lib = util_dl_open(path);
69
70 return !(stmod->lib);
71 }
72
73 static boolean
74 egl_g3d_load_st_module(struct egl_g3d_st_module *stmod,
75 const char *filename, const char *procname)
76 {
77 struct st_api *(*create_api)(void);
78
79 stmod->filename = filename;
80 if (stmod->filename)
81 _eglSearchPathForEach(egl_g3d_search_path_callback, (void *) stmod);
82 else
83 stmod->lib = util_dl_open(NULL);
84
85 if (stmod->lib) {
86 create_api = (struct st_api *(*)(void))
87 util_dl_get_proc_address(stmod->lib, procname);
88 if (create_api)
89 stmod->stapi = create_api();
90
91 if (!stmod->stapi) {
92 util_dl_close(stmod->lib);
93 stmod->lib = NULL;
94 }
95 }
96
97 if (stmod->stapi) {
98 return TRUE;
99 }
100 else {
101 stmod->filename = NULL;
102 return FALSE;
103 }
104 }
105
106 void
107 egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT])
108 {
109 const char *skip_checks[ST_API_COUNT], *symbols[ST_API_COUNT];
110 const char *filenames[ST_API_COUNT][4];
111 struct util_dl_library *self;
112 int num_needed = 0, api;
113
114 self = util_dl_open(NULL);
115
116 /* collect the necessary data for loading modules */
117 for (api = 0; api < ST_API_COUNT; api++) {
118 int count = 0;
119
120 switch (api) {
121 case ST_API_OPENGL:
122 skip_checks[api] = "glColor4d";
123 symbols[api] = ST_CREATE_OPENGL_SYMBOL;
124 filenames[api][count++] = "api_GL.so";
125 break;
126 case ST_API_OPENGL_ES1:
127 skip_checks[api] = "glColor4x";
128 symbols[api] = ST_CREATE_OPENGL_ES1_SYMBOL;
129 filenames[api][count++] = "api_GLESv1_CM.so";
130 filenames[api][count++] = "api_GL.so";
131 break;
132 case ST_API_OPENGL_ES2:
133 skip_checks[api] = "glShaderBinary";
134 symbols[api] = ST_CREATE_OPENGL_ES2_SYMBOL;
135 filenames[api][count++] = "api_GLESv2.so";
136 filenames[api][count++] = "api_GL.so";
137 break;
138 case ST_API_OPENVG:
139 skip_checks[api] = "vgClear";
140 symbols[api] = ST_CREATE_OPENVG_SYMBOL;
141 filenames[api][count++]= "api_OpenVG.so";
142 break;
143 default:
144 assert(!"Unknown API Type\n");
145 skip_checks[api] = NULL;
146 symbols[api] = NULL;
147 break;
148 }
149 filenames[api][count++]= NULL;
150 assert(count < Elements(filenames[api]));
151
152 /* heuristicically decide if the module is needed */
153 if (!self || !skip_checks[api] ||
154 util_dl_get_proc_address(self, skip_checks[api])) {
155 /* unset so the module is not skipped */
156 skip_checks[api] = NULL;
157 num_needed++;
158 }
159 }
160 /* mark all moudles needed if we wrongly decided that none is needed */
161 if (!num_needed)
162 memset(skip_checks, 0, sizeof(skip_checks));
163
164 if (self)
165 util_dl_close(self);
166
167 for (api = 0; api < ST_API_COUNT; api++) {
168 struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api];
169 const char **p;
170
171 /* skip the module */
172 if (skip_checks[api])
173 continue;
174
175 /* try all filenames, including NULL */
176 for (p = filenames[api]; *p; p++) {
177 if (egl_g3d_load_st_module(stmod, *p, symbols[api]))
178 break;
179 }
180 if (!stmod->stapi)
181 egl_g3d_load_st_module(stmod, NULL, symbols[api]);
182
183 stapis[api] = stmod->stapi;
184 }
185 }
186
187 void
188 egl_g3d_destroy_st_apis(void)
189 {
190 int api;
191
192 for (api = 0; api < ST_API_COUNT; api++) {
193 struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api];
194
195 if (stmod->stapi) {
196 stmod->stapi->destroy(stmod->stapi);
197 stmod->stapi = NULL;
198 }
199 if (stmod->lib) {
200 util_dl_close(stmod->lib);
201 stmod->lib = NULL;
202 }
203 stmod->filename = NULL;
204 }
205 }
206
207 static boolean
208 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
209 struct st_context_iface *stctx,
210 void *egl_image,
211 struct st_egl_image *out)
212 {
213 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
214 EGLImageKHR handle = (EGLImageKHR) egl_image;
215 _EGLImage *img;
216 struct egl_g3d_image *gimg;
217
218 /* this is called from state trackers */
219 _eglLockMutex(&gsmapi->display->Mutex);
220
221 img = _eglLookupImage(handle, gsmapi->display);
222 if (!img) {
223 _eglUnlockMutex(&gsmapi->display->Mutex);
224 return FALSE;
225 }
226
227 gimg = egl_g3d_image(img);
228
229 out->texture = NULL;
230 pipe_resource_reference(&out->texture, gimg->texture);
231 out->face = gimg->face;
232 out->level = gimg->level;
233 out->zslice = gimg->zslice;
234
235 _eglUnlockMutex(&gsmapi->display->Mutex);
236
237 return TRUE;
238 }
239
240 static int
241 egl_g3d_st_manager_get_param(struct st_manager *smapi,
242 enum st_manager_param param)
243 {
244 return 0;
245 }
246
247 struct st_manager *
248 egl_g3d_create_st_manager(_EGLDisplay *dpy)
249 {
250 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
251 struct egl_g3d_st_manager *gsmapi;
252
253 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
254 if (gsmapi) {
255 gsmapi->display = dpy;
256
257 gsmapi->base.screen = gdpy->native->screen;
258 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
259 gsmapi->base.get_param = egl_g3d_st_manager_get_param;
260 }
261
262 return &gsmapi->base;;
263 }
264
265 void
266 egl_g3d_destroy_st_manager(struct st_manager *smapi)
267 {
268 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
269 FREE(gsmapi);
270 }
271
272 static boolean
273 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
274 enum st_attachment_type statt)
275 {
276 return TRUE;
277 }
278
279 static boolean
280 egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
281 const enum st_attachment_type *statts,
282 unsigned count,
283 struct pipe_resource **out)
284 {
285 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
286 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
287 struct pipe_resource templ;
288 unsigned i;
289
290 for (i = 0; i < count; i++) {
291 out[i] = NULL;
292
293 if (gsurf->stvis.render_buffer != statts[i])
294 continue;
295
296 if (!gsurf->render_texture) {
297 struct egl_g3d_display *gdpy =
298 egl_g3d_display(gsurf->base.Resource.Display);
299 struct pipe_screen *screen = gdpy->native->screen;
300
301 memset(&templ, 0, sizeof(templ));
302 templ.target = PIPE_TEXTURE_2D;
303 templ.last_level = 0;
304 templ.width0 = gsurf->base.Width;
305 templ.height0 = gsurf->base.Height;
306 templ.depth0 = 1;
307 templ.format = gsurf->stvis.color_format;
308 templ.bind = PIPE_BIND_RENDER_TARGET;
309
310 gsurf->render_texture = screen->resource_create(screen, &templ);
311 }
312
313 pipe_resource_reference(&out[i], gsurf->render_texture);
314 }
315
316 return TRUE;
317 }
318
319 static boolean
320 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
321 enum st_attachment_type statt)
322 {
323 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
324 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
325
326 return gsurf->native->flush_frontbuffer(gsurf->native);
327 }
328
329 static boolean
330 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
331 const enum st_attachment_type *statts,
332 unsigned count,
333 struct pipe_resource **out)
334 {
335 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
336 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
337 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
338 uint attachment_mask = 0;
339 unsigned i;
340
341 for (i = 0; i < count; i++) {
342 int natt;
343
344 switch (statts[i]) {
345 case ST_ATTACHMENT_FRONT_LEFT:
346 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
347 break;
348 case ST_ATTACHMENT_BACK_LEFT:
349 natt = NATIVE_ATTACHMENT_BACK_LEFT;
350 break;
351 case ST_ATTACHMENT_FRONT_RIGHT:
352 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
353 break;
354 case ST_ATTACHMENT_BACK_RIGHT:
355 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
356 break;
357 default:
358 natt = -1;
359 break;
360 }
361
362 if (natt >= 0)
363 attachment_mask |= 1 << natt;
364 }
365
366 if (!gsurf->native->validate(gsurf->native, attachment_mask,
367 &gsurf->sequence_number, textures, &gsurf->base.Width,
368 &gsurf->base.Height))
369 return FALSE;
370
371 for (i = 0; i < count; i++) {
372 struct pipe_resource *tex;
373 int natt;
374
375 switch (statts[i]) {
376 case ST_ATTACHMENT_FRONT_LEFT:
377 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
378 break;
379 case ST_ATTACHMENT_BACK_LEFT:
380 natt = NATIVE_ATTACHMENT_BACK_LEFT;
381 break;
382 case ST_ATTACHMENT_FRONT_RIGHT:
383 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
384 break;
385 case ST_ATTACHMENT_BACK_RIGHT:
386 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
387 break;
388 default:
389 natt = -1;
390 break;
391 }
392
393 if (natt >= 0) {
394 tex = textures[natt];
395
396 if (statts[i] == stfbi->visual->render_buffer)
397 pipe_resource_reference(&gsurf->render_texture, tex);
398
399 if (attachment_mask & (1 << natt)) {
400 /* transfer the ownership to the caller */
401 out[i] = tex;
402 attachment_mask &= ~(1 << natt);
403 }
404 else {
405 /* the attachment is listed more than once */
406 pipe_resource_reference(&out[i], tex);
407 }
408 }
409 }
410
411 return TRUE;
412 }
413
414 struct st_framebuffer_iface *
415 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
416 {
417 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
418 struct st_framebuffer_iface *stfbi;
419
420 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
421 if (!stfbi)
422 return NULL;
423
424 stfbi->visual = &gsurf->stvis;
425 if (gsurf->base.Type != EGL_PBUFFER_BIT) {
426 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
427 stfbi->validate = egl_g3d_st_framebuffer_validate;
428 }
429 else {
430 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
431 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
432 }
433 stfbi->st_manager_private = (void *) &gsurf->base;
434
435 return stfbi;
436 }
437
438 void
439 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
440 {
441 FREE(stfbi);
442 }