2 * Copyright (c) 2013 Renesas Solutions Corp.
3 * Copyright (c) 2012 Carsten Munk <carsten.munk@gmail.com>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 * Takanari Hayama <taki@igel.co.jp>
22 /* EGL function pointers */
23 #define EGL_EGLEXT_PROTOTYPES
25 #include <EGL/eglext.h>
27 #define IMG_LIBEGL_PATH "libEGL-pvr.so"
30 # define EGL_DEBUG(s, x...) { printf(s, ## x); }
32 # define EGL_DEBUG(s, x...) { }
35 #ifndef EGL_WAYLAND_BUFFER_WL
36 /* TI headers don't define this */
37 #define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */
47 #include <sys/types.h>
54 #include <wayland-kms.h>
56 #include <gbm/common.h>
59 static EGLint(*_eglGetError) (void);
61 static EGLDisplay(*_eglGetDisplay) (EGLNativeDisplayType display_id);
62 static EGLBoolean(*_eglInitialize) (EGLDisplay dpy, EGLint * major,
64 static EGLBoolean(*_eglTerminate) (EGLDisplay dpy);
66 static const char *(*_eglQueryString) (EGLDisplay dpy, EGLint name);
68 static EGLBoolean(*_eglGetConfigs) (EGLDisplay dpy, EGLConfig * configs,
69 EGLint config_size, EGLint * num_config);
70 static EGLBoolean(*_eglChooseConfig) (EGLDisplay dpy,
71 const EGLint * attrib_list,
73 EGLint config_size, EGLint * num_config);
74 static EGLBoolean(*_eglGetConfigAttrib) (EGLDisplay dpy,
76 EGLint attribute, EGLint * value);
78 static EGLSurface(*_eglCreateWindowSurface) (EGLDisplay dpy,
80 EGLNativeWindowType win,
81 const EGLint * attrib_list);
82 static EGLSurface(*_eglCreatePbufferSurface) (EGLDisplay dpy,
84 const EGLint * attrib_list);
85 static EGLSurface(*_eglCreatePixmapSurface) (EGLDisplay dpy,
87 EGLNativePixmapType pixmap,
88 const EGLint * attrib_list);
89 static EGLBoolean(*_eglDestroySurface) (EGLDisplay dpy, EGLSurface surface);
90 static EGLBoolean(*_eglQuerySurface) (EGLDisplay dpy, EGLSurface surface,
91 EGLint attribute, EGLint * value);
93 static EGLBoolean(*_eglBindAPI) (EGLenum api);
94 static EGLenum(*_eglQueryAPI) (void);
96 static EGLBoolean(*_eglWaitClient) (void);
98 static EGLBoolean(*_eglReleaseThread) (void);
100 static EGLSurface(*_eglCreatePbufferFromClientBuffer) (EGLDisplay dpy,
108 static EGLBoolean(*_eglSurfaceAttrib) (EGLDisplay dpy,
110 EGLint attribute, EGLint value);
111 static EGLBoolean(*_eglBindTexImage) (EGLDisplay dpy, EGLSurface surface,
113 static EGLBoolean(*_eglReleaseTexImage) (EGLDisplay dpy,
114 EGLSurface surface, EGLint buffer);
116 static EGLBoolean(*_eglSwapInterval) (EGLDisplay dpy, EGLint interval);
118 static EGLContext(*_eglCreateContext) (EGLDisplay dpy, EGLConfig config,
119 EGLContext share_context,
120 const EGLint * attrib_list);
121 static EGLBoolean(*_eglDestroyContext) (EGLDisplay dpy, EGLContext ctx);
122 static EGLBoolean(*_eglMakeCurrent) (EGLDisplay dpy, EGLSurface draw,
123 EGLSurface read, EGLContext ctx);
125 static EGLContext(*_eglGetCurrentContext) (void);
126 static EGLSurface(*_eglGetCurrentSurface) (EGLint readdraw);
127 static EGLDisplay(*_eglGetCurrentDisplay) (void);
128 static EGLBoolean(*_eglQueryContext) (EGLDisplay dpy, EGLContext ctx,
129 EGLint attribute, EGLint * value);
131 static EGLBoolean(*_eglWaitGL) (void);
132 static EGLBoolean(*_eglWaitNative) (EGLint engine);
133 static EGLBoolean(*_eglSwapBuffers) (EGLDisplay dpy, EGLSurface surface);
134 static EGLBoolean(*_eglCopyBuffers) (EGLDisplay dpy, EGLSurface surface,
135 EGLNativePixmapType target);
137 static EGLImageKHR(*_eglCreateImageKHR) (EGLDisplay dpy, EGLContext ctx,
139 EGLClientBuffer buffer,
140 const EGLint * attrib_list);
141 static EGLBoolean(*_eglDestroyImageKHR) (EGLDisplay dpy, EGLImageKHR image);
143 static __eglMustCastToProperFunctionPointerType(*_eglGetProcAddress) (const char *procname);
145 static void *_libegl = NULL;
147 static void _init_egl()
149 const char *filename = (getenv("LIBEGL")) ? getenv("LIBEGL") : IMG_LIBEGL_PATH;
150 _libegl = dlopen(filename, RTLD_LAZY);
153 #define EGL_DLSYM(f) \
154 if (!_libegl) _init_egl(); \
155 if (!_##f) _##f = dlsym(_libegl, #f); \
157 EGLint eglGetError(void)
159 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
160 EGL_DLSYM(eglGetError);
161 return _eglGetError();
165 static struct gbm_device *__gbm;
166 static struct wl_display *__wl_display = NULL;
169 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
171 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
172 EGL_DLSYM(eglGetDisplay);
176 void *head = *(void**)display_id;
177 if (head == gbm_create_device)
178 __gbm = (struct gbm_device*)display_id;
179 if (head == &wl_display_interface)
180 __wl_display = (struct wl_display*)display_id;
186 FILE *fp = fopen("/proc/self/maps", "r");
190 count = fread(buf, 1, BUFSIZ, fp);
191 fwrite(buf, count, 1, stdout);
195 EGL_DEBUG("\n\n%s: %p\n", __func__, _eglGetDisplay);
198 return _eglGetDisplay(display_id);
201 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint * major, EGLint * minor)
203 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
204 EGL_DLSYM(eglInitialize);
205 return _eglInitialize(dpy, major, minor);
208 EGLBoolean eglTerminate(EGLDisplay dpy)
210 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
211 EGL_DLSYM(eglTerminate);
212 return _eglTerminate(dpy);
215 #define EGL_WL_EXT_STRING "EGL_WL_bind_wayland_display "
217 const char *eglQueryString(EGLDisplay dpy, EGLint name)
219 static char *_eglextstr = NULL;
222 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
223 EGL_DLSYM(eglQueryString);
224 ret = _eglQueryString(dpy, name);
227 if (name == EGL_EXTENSIONS) {
231 _eglextstr = calloc(1, strlen(ret) + strlen(EGL_WL_EXT_STRING) + 1);
233 strcat(_eglextstr, ret);
234 strcat(_eglextstr, EGL_WL_EXT_STRING);
236 _eglextstr = (char*)ret;
246 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig * configs,
247 EGLint config_size, EGLint * num_config)
249 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
250 EGL_DLSYM(eglGetConfigs);
251 return _eglGetConfigs(dpy, configs, config_size, num_config);
254 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint * attrib_list,
255 EGLConfig * configs, EGLint config_size,
258 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
259 EGL_DLSYM(eglChooseConfig);
260 return _eglChooseConfig(dpy, attrib_list,
261 configs, config_size, num_config);
264 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
265 EGLint attribute, EGLint * value)
267 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
268 EGL_DLSYM(eglGetConfigAttrib);
269 return _eglGetConfigAttrib(dpy, config, attribute, value);
272 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
273 EGLNativeWindowType win,
274 const EGLint * attrib_list)
276 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
277 EGL_DLSYM(eglCreateWindowSurface);
278 return _eglCreateWindowSurface(dpy, config, win, attrib_list);
281 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
282 const EGLint * attrib_list)
284 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
285 EGL_DLSYM(eglCreatePbufferSurface);
286 return _eglCreatePbufferSurface(dpy, config, attrib_list);
289 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
290 EGLNativePixmapType pixmap,
291 const EGLint * attrib_list)
293 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
294 EGL_DLSYM(eglCreatePixmapSurface);
295 return _eglCreatePixmapSurface(dpy, config, pixmap, attrib_list);
298 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
300 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
301 EGL_DLSYM(eglDestroySurface);
302 return _eglDestroySurface(dpy, surface);
305 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
306 EGLint attribute, EGLint * value)
308 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
309 EGL_DLSYM(eglQuerySurface);
310 return _eglQuerySurface(dpy, surface, attribute, value);
313 EGLBoolean eglBindAPI(EGLenum api)
315 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
316 EGL_DLSYM(eglBindAPI);
317 return _eglBindAPI(api);
320 EGLenum eglQueryAPI(void)
322 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
323 EGL_DLSYM(eglQueryAPI);
324 return _eglQueryAPI();
327 EGLBoolean eglWaitClient(void)
329 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
330 EGL_DLSYM(eglWaitClient);
331 return _eglWaitClient();
334 EGLBoolean eglReleaseThread(void)
336 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
337 EGL_DLSYM(eglReleaseThread);
338 return _eglReleaseThread();
341 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
342 EGLClientBuffer buffer,
344 const EGLint * attrib_list)
346 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
347 EGL_DLSYM(eglCreatePbufferFromClientBuffer);
348 return _eglCreatePbufferFromClientBuffer(dpy, buftype, buffer,
349 config, attrib_list);
352 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
353 EGLint attribute, EGLint value)
355 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
356 EGL_DLSYM(eglSurfaceAttrib);
357 return _eglSurfaceAttrib(dpy, surface, attribute, value);
360 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
362 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
363 EGL_DLSYM(eglBindTexImage);
364 return _eglBindTexImage(dpy, surface, buffer);
367 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
369 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
370 EGL_DLSYM(eglReleaseTexImage);
371 return _eglReleaseTexImage(dpy, surface, buffer);
374 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
376 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
377 EGL_DLSYM(eglSwapInterval);
378 return _eglSwapInterval(dpy, interval);
381 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
382 EGLContext share_context,
383 const EGLint * attrib_list)
385 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
386 EGL_DLSYM(eglCreateContext);
387 return _eglCreateContext(dpy, config, share_context, attrib_list);
390 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
392 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
393 EGL_DLSYM(eglDestroyContext);
394 return _eglDestroyContext(dpy, ctx);
397 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
398 EGLSurface read, EGLContext ctx)
400 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
401 EGL_DLSYM(eglMakeCurrent);
402 return _eglMakeCurrent(dpy, draw, read, ctx);
405 EGLContext eglGetCurrentContext(void)
407 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
408 EGL_DLSYM(eglGetCurrentContext);
409 return _eglGetCurrentContext();
412 EGLSurface eglGetCurrentSurface(EGLint readdraw)
414 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
415 EGL_DLSYM(eglGetCurrentSurface);
416 return _eglGetCurrentSurface(readdraw);
419 EGLDisplay eglGetCurrentDisplay(void)
421 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
422 EGL_DLSYM(eglGetCurrentDisplay);
423 return _eglGetCurrentDisplay();
426 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx,
427 EGLint attribute, EGLint * value)
429 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
430 EGL_DLSYM(eglQueryContext);
431 return _eglQueryContext(dpy, ctx, attribute, value);
434 EGLBoolean eglWaitGL(void)
436 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
437 EGL_DLSYM(eglWaitGL);
441 EGLBoolean eglWaitNative(EGLint engine)
443 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
444 EGL_DLSYM(eglWaitNative);
445 return _eglWaitNative(engine);
448 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
450 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
451 EGL_DLSYM(eglSwapBuffers);
452 return _eglSwapBuffers(dpy, surface);
455 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
456 EGLNativePixmapType target)
458 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
459 EGL_DLSYM(eglCopyBuffers);
460 return _eglCopyBuffers(dpy, surface, target);
463 static EGLImageKHR __eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx,
464 EGLenum target, EGLClientBuffer buffer,
465 const EGLint * attrib_list)
467 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
468 if (!_eglCreateImageKHR) {
469 /* we can't EGL_DLSYM this, because it doesn't exist in libEGL.
470 * IMG's libEGL. we also can't ask ourselves for the location of
471 * eglGetProcAddress, otherwise we'll end up calling ourselves again, so
472 * we must look up eglGetProcAddress first and ask SGX
474 EGL_DLSYM(eglGetProcAddress);
475 _eglCreateImageKHR = (void*)_eglGetProcAddress("eglCreateImageKHR");
479 * We consider EGL_WAYLAND_BUFFER_WL to be EGL_ANTIVE_PIXMAP_KHR.
480 * This way IMG EGL will pass the request to underlying WSEGL.
482 if (target == EGL_WAYLAND_BUFFER_WL) {
483 EGL_DEBUG("%s: %s: mapping EGL_WAYLAND_BUFFER_WL to EGL_NATIVE_PIXMAP_KHR\n", __FILE__, __func__);
484 target = EGL_NATIVE_PIXMAP_KHR;
490 EGLint *_attr, *_attr2, *head;
493 while (*_attr != EGL_NONE) {
498 EGL_DEBUG("%s: %s: count=%d\n", __FILE__, __func__, count);
499 head = _attr2 = alloca(sizeof(EGLint) * count);
502 while (*_attr != EGL_NONE) {
503 if (*_attr != EGL_WAYLAND_PLANE_WL) {
504 EGL_DEBUG("%s: %s: copying %x\n", __FILE__, __func__, *_attr);
511 EGL_DEBUG("%s: %s: skipping %x\n", __FILE__, __func__, *_attr);
515 *_attr2 = - EGL_NONE;
520 EGL_DEBUG("%s: %s (target=%d, EGL_WAYLAND_BUFFER_WL=%d, EGL_NATIVE_PIXMAP_KHR=%d) : %p\n", __FILE__, __func__, target, EGL_WAYLAND_BUFFER_WL, EGL_NATIVE_PIXMAP_KHR, _eglCreateImageKHR);
521 // return _eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
522 return _eglCreateImageKHR(dpy, ctx, target, buffer, NULL);
526 static struct wl_kms *__wl_kms = NULL;
528 static EGLBoolean __eglBindWaylandDisplayWL(EGLDisplay dpy,
529 struct wl_display *display)
531 char *device_name = "/dev/dri/card0";
534 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
535 // TODO: create server side for wl_kms.
540 fd = gbm_device_get_fd(__gbm);
541 device_name = _gbm_fd_get_device_name(fd);
543 fd = open(device_name, O_RDWR);
546 __gbm = gbm_create_device(fd);
548 EGL_DEBUG("%s: decice_name=%s\n", __func__, device_name);
550 __wl_kms = wayland_kms_init(display, __wl_display, device_name, fd);
554 static EGLBoolean __eglUnbindWaylandDisplayWL(EGLDisplay dpy,
555 struct wl_display *display)
557 // TODO: destroy wl_kms?
558 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
560 wayland_kms_uninit(__wl_kms);
565 static EGLBoolean __eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
566 EGLint attribute, EGLint * value)
569 enum wl_kms_attribute attr;
570 EGLBoolean result = EGL_FALSE;
572 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
574 case EGL_TEXTURE_FORMAT:
575 attr = WL_KMS_TEXTURE_FORMAT;
581 attr = WL_KMS_HEIGHT;
587 ret = wayland_kms_query_buffer(__wl_kms, buffer, attr, &val);
589 *value = (EGLint)val;
597 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
599 EGL_DLSYM(eglGetProcAddress);
601 EGL_DEBUG("%s: %s(%s)\n", __FILE__, __func__, procname);
602 if (strcmp(procname, "eglCreateImageKHR") == 0) {
603 return (__eglMustCastToProperFunctionPointerType)__eglCreateImageKHR;
606 else if (strcmp(procname, "eglBindWaylandDisplayWL") == 0) {
607 return (__eglMustCastToProperFunctionPointerType)__eglBindWaylandDisplayWL;
608 } else if (strcmp(procname, "eglUnbindWaylandDisplayWL") == 0) {
609 return (__eglMustCastToProperFunctionPointerType)__eglUnbindWaylandDisplayWL;
610 } else if (strcmp(procname, "eglQueryWaylandBufferWL") == 0) {
611 return (__eglMustCastToProperFunctionPointerType)__eglQueryWaylandBufferWL;
614 return _eglGetProcAddress(procname);
617 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
619 EGL_DEBUG("%s: %s\n", __FILE__, __func__);
620 EGL_DLSYM(eglDestroyImageKHR);
621 return _eglDestroyImageKHR(dpy, image);