st_api: Give get_egl_image arguments directly to the function
[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 void *egl_image,
210 struct st_egl_image *out)
211 {
212 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
213 EGLImageKHR handle = (EGLImageKHR) egl_image;
214 _EGLImage *img;
215 struct egl_g3d_image *gimg;
216
217 /* this is called from state trackers */
218 _eglLockMutex(&gsmapi->display->Mutex);
219
220 img = _eglLookupImage(handle, gsmapi->display);
221 if (!img) {
222 _eglUnlockMutex(&gsmapi->display->Mutex);
223 return FALSE;
224 }
225
226 gimg = egl_g3d_image(img);
227
228 out->texture = NULL;
229 pipe_resource_reference(&out->texture, gimg->texture);
230 out->face = gimg->face;
231 out->level = gimg->level;
232 out->zslice = gimg->zslice;
233
234 _eglUnlockMutex(&gsmapi->display->Mutex);
235
236 return TRUE;
237 }
238
239 static int
240 egl_g3d_st_manager_get_param(struct st_manager *smapi,
241 enum st_manager_param param)
242 {
243 return 0;
244 }
245
246 struct st_manager *
247 egl_g3d_create_st_manager(_EGLDisplay *dpy)
248 {
249 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
250 struct egl_g3d_st_manager *gsmapi;
251
252 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
253 if (gsmapi) {
254 gsmapi->display = dpy;
255
256 gsmapi->base.screen = gdpy->native->screen;
257 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
258 gsmapi->base.get_param = egl_g3d_st_manager_get_param;
259 }
260
261 return &gsmapi->base;;
262 }
263
264 void
265 egl_g3d_destroy_st_manager(struct st_manager *smapi)
266 {
267 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
268 FREE(gsmapi);
269 }
270
271 static boolean
272 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
273 enum st_attachment_type statt)
274 {
275 return TRUE;
276 }
277
278 static boolean
279 egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
280 const enum st_attachment_type *statts,
281 unsigned count,
282 struct pipe_resource **out)
283 {
284 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
285 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
286 struct pipe_resource templ;
287 unsigned i;
288
289 for (i = 0; i < count; i++) {
290 out[i] = NULL;
291
292 if (gsurf->stvis.render_buffer != statts[i])
293 continue;
294
295 if (!gsurf->render_texture) {
296 struct egl_g3d_display *gdpy =
297 egl_g3d_display(gsurf->base.Resource.Display);
298 struct pipe_screen *screen = gdpy->native->screen;
299
300 memset(&templ, 0, sizeof(templ));
301 templ.target = PIPE_TEXTURE_2D;
302 templ.last_level = 0;
303 templ.width0 = gsurf->base.Width;
304 templ.height0 = gsurf->base.Height;
305 templ.depth0 = 1;
306 templ.format = gsurf->stvis.color_format;
307 templ.bind = PIPE_BIND_RENDER_TARGET;
308
309 gsurf->render_texture = screen->resource_create(screen, &templ);
310 }
311
312 pipe_resource_reference(&out[i], gsurf->render_texture);
313 }
314
315 return TRUE;
316 }
317
318 static boolean
319 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
320 enum st_attachment_type statt)
321 {
322 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
323 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
324
325 return gsurf->native->flush_frontbuffer(gsurf->native);
326 }
327
328 static boolean
329 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
330 const enum st_attachment_type *statts,
331 unsigned count,
332 struct pipe_resource **out)
333 {
334 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
335 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
336 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
337 uint attachment_mask = 0;
338 unsigned i;
339
340 for (i = 0; i < count; i++) {
341 int natt;
342
343 switch (statts[i]) {
344 case ST_ATTACHMENT_FRONT_LEFT:
345 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
346 break;
347 case ST_ATTACHMENT_BACK_LEFT:
348 natt = NATIVE_ATTACHMENT_BACK_LEFT;
349 break;
350 case ST_ATTACHMENT_FRONT_RIGHT:
351 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
352 break;
353 case ST_ATTACHMENT_BACK_RIGHT:
354 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
355 break;
356 default:
357 natt = -1;
358 break;
359 }
360
361 if (natt >= 0)
362 attachment_mask |= 1 << natt;
363 }
364
365 if (!gsurf->native->validate(gsurf->native, attachment_mask,
366 &gsurf->sequence_number, textures, &gsurf->base.Width,
367 &gsurf->base.Height))
368 return FALSE;
369
370 for (i = 0; i < count; i++) {
371 struct pipe_resource *tex;
372 int natt;
373
374 switch (statts[i]) {
375 case ST_ATTACHMENT_FRONT_LEFT:
376 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
377 break;
378 case ST_ATTACHMENT_BACK_LEFT:
379 natt = NATIVE_ATTACHMENT_BACK_LEFT;
380 break;
381 case ST_ATTACHMENT_FRONT_RIGHT:
382 natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
383 break;
384 case ST_ATTACHMENT_BACK_RIGHT:
385 natt = NATIVE_ATTACHMENT_BACK_RIGHT;
386 break;
387 default:
388 natt = -1;
389 break;
390 }
391
392 if (natt >= 0) {
393 tex = textures[natt];
394
395 if (statts[i] == stfbi->visual->render_buffer)
396 pipe_resource_reference(&gsurf->render_texture, tex);
397
398 if (attachment_mask & (1 << natt)) {
399 /* transfer the ownership to the caller */
400 out[i] = tex;
401 attachment_mask &= ~(1 << natt);
402 }
403 else {
404 /* the attachment is listed more than once */
405 pipe_resource_reference(&out[i], tex);
406 }
407 }
408 }
409
410 return TRUE;
411 }
412
413 struct st_framebuffer_iface *
414 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
415 {
416 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
417 struct st_framebuffer_iface *stfbi;
418
419 stfbi = CALLOC_STRUCT(st_framebuffer_iface);
420 if (!stfbi)
421 return NULL;
422
423 stfbi->visual = &gsurf->stvis;
424 if (gsurf->base.Type != EGL_PBUFFER_BIT) {
425 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
426 stfbi->validate = egl_g3d_st_framebuffer_validate;
427 }
428 else {
429 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
430 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
431 }
432 stfbi->st_manager_private = (void *) &gsurf->base;
433
434 return stfbi;
435 }
436
437 void
438 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
439 {
440 FREE(stfbi);
441 }