2 * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
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:
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
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #define LOG_TAG "DROID-EGL"
25 #include <utils/Log.h>
27 #include "glapi/glapi.h"
29 #include "eglconfig.h"
30 #include "eglcontext.h"
31 #include "egldisplay.h"
32 #include "egldriver.h"
33 #include "eglglobals.h"
35 #include "eglsurface.h"
40 #ifndef DROID_DEVICE_PATH
41 #define DROID_DEVICE_PATH "/dev/dri/card0"
44 struct droid_egl_driver
48 /* EGL_DEFAULT_DISPLAY */
49 struct droid_egl_display *default_display;
50 void (*flush_current)(void);
51 void (*finish_current)(void);
54 struct droid_egl_display
62 struct droid_backend *backend;
63 struct droid_screen *screen;
66 struct droid_egl_context {
68 struct droid_context *context;
71 struct droid_egl_surface {
73 struct droid_drawable *drawable;
74 struct droid_surface *surface;
77 struct droid_egl_image {
79 struct droid_drawable *drawable;
80 struct droid_surface *surface;
83 struct droid_egl_config {
85 const __DRIconfig *config;
88 static INLINE struct droid_egl_driver *
89 lookup_driver(_EGLDriver *drv)
91 return (struct droid_egl_driver *) drv;
94 static INLINE struct droid_egl_display *
95 lookup_display(_EGLDisplay *dpy)
97 return (struct droid_egl_display *) dpy->DriverData;
100 static INLINE struct droid_egl_context *
101 lookup_context(_EGLContext *context)
103 return (struct droid_egl_context *) context;
106 static INLINE struct droid_egl_surface *
107 lookup_surface(_EGLSurface *surface)
109 return (struct droid_egl_surface *) surface;
112 static INLINE struct droid_egl_image *
113 lookup_image(_EGLImage *image)
115 return (struct droid_egl_image *) image;
118 static INLINE struct droid_egl_config *
119 lookup_config(_EGLConfig *conf)
121 return (struct droid_egl_config *) conf;
125 droid_create_configs(_EGLDisplay *dpy, struct droid_egl_display *droid_dpy,
126 const __DRIconfig **configs, EGLint num_configs)
131 for (i = 0; i < num_configs; i++) {
132 struct droid_egl_config *droid_conf = calloc(1, sizeof(*droid_conf));
138 _eglInitConfig(&droid_conf->base, id);
139 droid_conf->config = configs[i];
140 if (!droid_screen_convert_config(droid_dpy->screen, droid_conf->config,
141 &droid_conf->base)) {
146 val = GET_CONFIG_ATTRIB(&droid_conf->base, EGL_CONFIG_CAVEAT);
147 /* we do not want slow configs */
148 if (val == EGL_SLOW_CONFIG) {
151 _eglAddConfig(dpy, &droid_conf->base);
159 droid_initialize_display(struct droid_egl_display *droid_dpy)
161 const char *path = DROID_DEVICE_PATH;
163 droid_dpy->backend = droid_backend_create_intel(path);
164 if (!droid_dpy->backend)
167 droid_dpy->screen = droid_screen_create(droid_dpy->backend);
168 if (!droid_dpy->screen) {
169 free(droid_dpy->backend);
170 droid_dpy->backend = NULL;
174 droid_dpy->apis = EGL_OPENGL_ES_BIT;
175 droid_dpy->major = 1;
176 droid_dpy->major = 4;
182 droid_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
183 EGLint *major, EGLint *minor)
185 struct droid_egl_driver *droid_drv = lookup_driver(drv);
186 struct droid_egl_display *droid_dpy;
188 if (dpy->NativeDisplay != EGL_DEFAULT_DISPLAY)
189 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
191 /* the default display */
192 droid_dpy = droid_drv->default_display;
194 droid_dpy = calloc(1, sizeof(*droid_dpy));
196 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
197 if (!droid_initialize_display(droid_dpy))
198 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
200 droid_create_configs(dpy, droid_dpy, droid_dpy->screen->dri_configs,
201 droid_dpy->screen->num_dri_configs);
203 #if EGL_KHR_image_base
204 if (droid_dpy->backend->create_image_surface) {
205 dpy->Extensions.KHR_image = EGL_TRUE;
206 dpy->Extensions.KHR_image_base = EGL_TRUE;
207 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
211 droid_drv->default_display = droid_dpy;
214 dpy->DriverData = (void *) droid_dpy;
217 *major = droid_dpy->major;
218 *minor = droid_dpy->minor;
224 droid_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
226 struct droid_egl_driver *droid_drv = lookup_driver(drv);
227 struct droid_egl_display *droid_dpy = lookup_display(dpy);
229 dpy->DriverData = NULL;
231 if (!droid_dpy->refcnt) {
232 _eglReleaseDisplayResources(drv, dpy);
233 _eglCleanupDisplay(dpy);
236 droid_drv->default_display = NULL;
243 droid_eglGetProcAddress(const char *procname)
245 return (_EGLProc) _glapi_get_proc_address(procname);
249 droid_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
250 _EGLContext *share_list, const EGLint *attrib_list)
252 struct droid_egl_display *droid_dpy = lookup_display(dpy);
253 struct droid_egl_config *droid_conf = lookup_config(conf);
254 struct droid_egl_context *shared = lookup_context(share_list);
255 struct droid_egl_context *ctx;
257 ctx = calloc(1, sizeof(*ctx));
259 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
263 if (!_eglInitContext(drv, &ctx->base, &droid_conf->base, attrib_list)) {
269 droid_screen_create_context(droid_dpy->screen, droid_conf->config,
270 (shared) ? shared->context : NULL);
280 droid_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
282 struct droid_egl_display *droid_dpy = lookup_display(dpy);
283 struct droid_egl_context *droid_ctx = lookup_context(ctx);
285 if (!_eglIsContextBound(ctx))
286 droid_screen_destroy_context(droid_dpy->screen, droid_ctx->context);
292 droid_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
293 _EGLSurface *r, _EGLContext *ctx)
295 struct droid_egl_driver *droid_drv = lookup_driver(drv);
296 struct droid_egl_display *droid_dpy = lookup_display(dpy);
297 struct droid_egl_surface *draw = lookup_surface(d);
298 struct droid_egl_surface *read = lookup_surface(r);
299 struct droid_egl_context *droid_ctx = lookup_context(ctx);
301 struct droid_egl_context *droid_old;
303 old = _eglGetCurrentContext();
304 /* an unlinked context will be invalid after context switch */
305 if (!_eglIsContextLinked(old))
308 droid_old = lookup_context(old);
310 if (!_eglMakeCurrent(drv, dpy, d, r, ctx))
313 if (droid_old && droid_old != droid_ctx && droid_drv->flush_current)
314 droid_drv->flush_current();
316 _glapi_check_multithread();
318 /* bind new context or unbind old one */
320 droid_screen_bind_context(droid_dpy->screen,
321 draw->drawable, read->drawable,
324 droid_screen_bind_context(droid_dpy->screen,
332 droid_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
333 NativeWindowType window, const EGLint *attrib_list)
335 struct droid_egl_display *droid_dpy = lookup_display(dpy);
336 struct droid_egl_config *droid_conf = lookup_config(conf);
337 struct droid_egl_surface *surf;
339 surf = calloc(1, sizeof(*surf));
341 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
345 if (!_eglInitSurface(drv, &surf->base, EGL_WINDOW_BIT, &droid_conf->base, attrib_list)) {
351 droid_dpy->backend->create_window_surface(droid_dpy->backend,
352 &surf->base, window);
353 if (!surf->surface) {
358 surf->drawable = droid_screen_create_drawable(droid_dpy->screen,
361 if (!surf->drawable) {
362 droid_dpy->backend->destroy_surface(droid_dpy->backend, surf->surface);
371 droid_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
373 struct droid_egl_display *droid_dpy = lookup_display(dpy);
374 struct droid_egl_surface *droid_surf = lookup_surface(surf);
376 if (_eglIsSurfaceBound(&droid_surf->base))
379 droid_screen_destroy_drawable(droid_dpy->screen, droid_surf->drawable);
380 droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_surf->surface);
387 droid_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
389 struct droid_egl_driver *droid_drv = lookup_driver(drv);
390 struct droid_egl_display *droid_dpy = lookup_display(dpy);
391 struct droid_egl_surface *droid_surf = lookup_surface(surf);
392 _EGLContext *ctx = _eglGetCurrentContext();
393 struct droid_egl_context *droid_ctx = lookup_context(ctx);
396 if (droid_drv->flush_current)
397 droid_drv->flush_current();
399 droid_screen_swap_buffers(droid_dpy->screen,
401 droid_surf->drawable);
407 #if EGL_KHR_image_base
410 droid_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
411 EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
413 struct droid_egl_display *droid_dpy = lookup_display(dpy);
414 struct droid_egl_image *droid_img;
415 struct droid_egl_config *droid_conf;
419 /* only EGL_KHR_image_pixmap is supported */
420 if (target != EGL_NATIVE_PIXMAP_KHR || ctx) {
421 _eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
425 for (i = 0; i < dpy->NumConfigs; i++) {
426 conf = dpy->Configs[i];
427 if (droid_dpy->backend->match_pixmap(droid_dpy->backend, conf,
428 (NativePixmapType) buffer)) {
430 val = GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB);
431 val |= GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA);
436 if (i >= dpy->NumConfigs)
439 droid_img = calloc(1, sizeof(*droid_img));
441 _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
445 if (!_eglInitImage(drv, &droid_img->base, attr_list)) {
451 droid_dpy->backend->create_image_surface(droid_dpy->backend,
452 (NativePixmapType) buffer);
453 if (!droid_img->surface) {
458 droid_conf = lookup_config(conf);
459 droid_img->drawable =
460 droid_screen_create_drawable(droid_dpy->screen, droid_conf->config,
463 if (!droid_img->drawable) {
464 droid_dpy->backend->destroy_surface(droid_dpy->backend,
470 droid_img->base.ClientData =
471 droid_screen_get_drawable_data(droid_dpy->screen, droid_img->drawable);
473 return &droid_img->base;
478 droid_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
480 struct droid_egl_display *droid_dpy = lookup_display(dpy);
481 struct droid_egl_image *droid_img = lookup_image(img);
483 droid_screen_destroy_drawable(droid_dpy->screen, droid_img->drawable);
484 droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_img->surface);
490 #endif /* EGL_KHR_image_base */
493 droid_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy)
495 struct droid_egl_driver *droid_drv = lookup_driver(drv);
496 _EGLContext *ctx = _eglGetCurrentContext();
498 if (!ctx || !droid_drv->finish_current)
501 if (!_eglIsSurfaceLinked(ctx->DrawSurface))
502 return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitClient");
504 droid_drv->finish_current();
510 droid_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
512 struct droid_egl_display *droid_dpy = lookup_display(dpy);
513 _EGLContext *ctx = _eglGetCurrentContext();
514 struct droid_egl_surface *droid_surf;
516 if (engine != EGL_CORE_NATIVE_ENGINE)
517 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
522 if (!_eglIsSurfaceLinked(ctx->DrawSurface))
523 return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitNative");
525 droid_surf = lookup_surface(ctx->DrawSurface);
526 droid_dpy->backend->swap_native_buffers(droid_dpy->backend,
527 droid_surf->surface);
533 droid_Unload(_EGLDriver *drv)
535 struct droid_egl_driver *droid_drv = lookup_driver(drv);
540 droid_Log(EGLint level, const char *msg)
559 _eglMain(const char *args)
561 struct droid_egl_driver *droid_drv = calloc(1, sizeof(*droid_drv));
565 _eglInitDriverFallbacks(&droid_drv->base);
566 droid_drv->base.API.Initialize = droid_eglInitialize;
567 droid_drv->base.API.Terminate = droid_eglTerminate;
569 droid_drv->base.API.GetProcAddress = droid_eglGetProcAddress;
571 droid_drv->base.API.CreateContext = droid_eglCreateContext;
572 droid_drv->base.API.DestroyContext = droid_eglDestroyContext;
573 droid_drv->base.API.MakeCurrent = droid_eglMakeCurrent;
574 droid_drv->base.API.CreateWindowSurface = droid_eglCreateWindowSurface;
575 droid_drv->base.API.DestroySurface = droid_eglDestroySurface;
576 droid_drv->base.API.SwapBuffers = droid_eglSwapBuffers;
577 #if EGL_KHR_image_base
578 droid_drv->base.API.CreateImageKHR = droid_eglCreateImageKHR;
579 droid_drv->base.API.DestroyImageKHR = droid_eglDestroyImageKHR;
580 #endif /* EGL_KHR_image_base */
581 droid_drv->base.API.WaitClient = droid_eglWaitClient;
582 droid_drv->base.API.WaitNative = droid_eglWaitNative;
584 droid_drv->base.Name = "Android/i915";
585 droid_drv->base.Unload = droid_Unload;
587 /* we need a way to flush commands */
588 droid_drv->flush_current =
589 (void (*)(void)) droid_eglGetProcAddress("glFlush");
590 droid_drv->finish_current =
591 (void (*)(void)) droid_eglGetProcAddress("glFinish");
593 _eglSetLogProc(droid_Log);
595 return &droid_drv->base;