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 #include "glapi/glapi.h"
26 #include "eglconfig.h"
27 #include "eglcontext.h"
28 #include "egldisplay.h"
29 #include "egldriver.h"
30 #include "eglglobals.h"
32 #include "eglsurface.h"
37 #ifndef DROID_DEVICE_PATH
38 #define DROID_DEVICE_PATH "/dev/dri/card0"
41 struct droid_egl_driver
45 /* EGL_DEFAULT_DISPLAY */
46 struct droid_egl_display *default_display;
47 void (*flush_current)(void);
48 void (*finish_current)(void);
51 struct droid_egl_display
59 struct droid_backend *backend;
60 struct droid_screen *screen;
63 struct droid_egl_context {
65 struct droid_context *context;
68 struct droid_egl_surface {
70 struct droid_drawable *drawable;
71 struct droid_surface *surface;
74 struct droid_egl_image {
76 struct droid_drawable *drawable;
77 struct droid_surface *surface;
80 struct droid_egl_config {
82 const __DRIconfig *config;
85 static INLINE struct droid_egl_driver *
86 lookup_driver(_EGLDriver *drv)
88 return (struct droid_egl_driver *) drv;
91 static INLINE struct droid_egl_display *
92 lookup_display(_EGLDisplay *dpy)
94 return (struct droid_egl_display *) dpy->DriverData;
97 static INLINE struct droid_egl_context *
98 lookup_context(_EGLContext *context)
100 return (struct droid_egl_context *) context;
103 static INLINE struct droid_egl_surface *
104 lookup_surface(_EGLSurface *surface)
106 return (struct droid_egl_surface *) surface;
109 static INLINE struct droid_egl_image *
110 lookup_image(_EGLImage *image)
112 return (struct droid_egl_image *) image;
115 static INLINE struct droid_egl_config *
116 lookup_config(_EGLConfig *conf)
118 return (struct droid_egl_config *) conf;
122 droid_create_configs(_EGLDisplay *dpy, struct droid_egl_display *droid_dpy,
123 const __DRIconfig **configs, EGLint num_configs)
128 for (i = 0; i < num_configs; i++) {
129 struct droid_egl_config *droid_conf = calloc(1, sizeof(*droid_conf));
135 _eglInitConfig(&droid_conf->base, id);
136 droid_conf->config = configs[i];
137 droid_screen_convert_config(droid_dpy->screen, droid_conf->config,
140 val = GET_CONFIG_ATTRIB(&droid_conf->base, EGL_CONFIG_CAVEAT);
141 /* we do not want slow configs */
142 if (val == EGL_SLOW_CONFIG) {
145 _eglAddConfig(dpy, &droid_conf->base);
153 droid_initialize_display(struct droid_egl_display *droid_dpy)
155 const char *path = DROID_DEVICE_PATH;
157 droid_dpy->backend = droid_backend_create_intel(path);
158 if (!droid_dpy->backend)
161 droid_dpy->screen = droid_screen_create(droid_dpy->backend);
162 if (!droid_dpy->screen) {
163 free(droid_dpy->backend);
164 droid_dpy->backend = NULL;
168 droid_dpy->apis = EGL_OPENGL_ES_BIT;
169 droid_dpy->major = 1;
170 droid_dpy->major = 4;
176 droid_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
177 EGLint *major, EGLint *minor)
179 struct droid_egl_driver *droid_drv = lookup_driver(drv);
180 struct droid_egl_display *droid_dpy;
182 if (dpy->NativeDisplay != EGL_DEFAULT_DISPLAY)
183 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
185 /* the default display */
186 droid_dpy = droid_drv->default_display;
188 droid_dpy = calloc(1, sizeof(*droid_dpy));
190 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
191 if (!droid_initialize_display(droid_dpy))
192 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
194 droid_create_configs(dpy, droid_dpy, droid_dpy->screen->dri_configs,
195 droid_dpy->screen->num_dri_configs);
197 #if EGL_KHR_image_base
198 if (droid_dpy->backend->create_image_surface) {
199 dpy->Extensions.KHR_image = EGL_TRUE;
200 dpy->Extensions.KHR_image_base = EGL_TRUE;
201 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
205 droid_drv->default_display = droid_dpy;
208 dpy->DriverData = (void *) droid_dpy;
211 *major = droid_dpy->major;
212 *minor = droid_dpy->minor;
218 droid_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
220 struct droid_egl_driver *droid_drv = lookup_driver(drv);
221 struct droid_egl_display *droid_dpy = lookup_display(dpy);
223 dpy->DriverData = NULL;
225 if (!droid_dpy->refcnt) {
226 _eglReleaseDisplayResources(drv, dpy);
227 _eglCleanupDisplay(dpy);
230 droid_drv->default_display = NULL;
237 droid_eglGetProcAddress(const char *procname)
239 return (_EGLProc) _glapi_get_proc_address(procname);
243 droid_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
244 _EGLContext *share_list, const EGLint *attrib_list)
246 struct droid_egl_display *droid_dpy = lookup_display(dpy);
247 struct droid_egl_config *droid_conf = lookup_config(conf);
248 struct droid_egl_context *shared = lookup_context(share_list);
249 struct droid_egl_context *ctx;
251 ctx = calloc(1, sizeof(*ctx));
253 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
257 if (!_eglInitContext(drv, &ctx->base, &droid_conf->base, attrib_list)) {
263 droid_screen_create_context(droid_dpy->screen, droid_conf->config,
264 (shared) ? shared->context : NULL);
274 droid_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
276 struct droid_egl_display *droid_dpy = lookup_display(dpy);
277 struct droid_egl_context *droid_ctx = lookup_context(ctx);
279 if (!_eglIsContextBound(ctx))
280 droid_screen_destroy_context(droid_dpy->screen, droid_ctx->context);
286 droid_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
287 _EGLSurface *r, _EGLContext *ctx)
289 struct droid_egl_driver *droid_drv = lookup_driver(drv);
290 struct droid_egl_display *droid_dpy = lookup_display(dpy);
291 struct droid_egl_surface *draw = lookup_surface(d);
292 struct droid_egl_surface *read = lookup_surface(r);
293 struct droid_egl_context *droid_ctx = lookup_context(ctx);
295 struct droid_egl_context *droid_old;
297 old = _eglGetCurrentContext();
298 /* an unlinked context will be invalid after context switch */
299 if (!_eglIsContextLinked(old))
302 droid_old = lookup_context(old);
304 if (!_eglMakeCurrent(drv, dpy, d, r, ctx))
307 if (droid_old && droid_old != droid_ctx && droid_drv->flush_current)
308 droid_drv->flush_current();
310 _glapi_check_multithread();
312 /* bind new context or unbind old one */
314 droid_screen_bind_context(droid_dpy->screen,
315 draw->drawable, read->drawable,
318 droid_screen_bind_context(droid_dpy->screen,
326 droid_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
327 NativeWindowType window, const EGLint *attrib_list)
329 struct droid_egl_display *droid_dpy = lookup_display(dpy);
330 struct droid_egl_config *droid_conf = lookup_config(conf);
331 struct droid_egl_surface *surf;
333 surf = calloc(1, sizeof(*surf));
335 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
339 if (!_eglInitSurface(drv, &surf->base, EGL_WINDOW_BIT, &droid_conf->base, attrib_list)) {
345 droid_dpy->backend->create_window_surface(droid_dpy->backend,
346 &surf->base, window);
347 if (!surf->surface) {
352 surf->drawable = droid_screen_create_drawable(droid_dpy->screen,
355 if (!surf->drawable) {
356 droid_dpy->backend->destroy_surface(droid_dpy->backend, surf->surface);
365 droid_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
367 struct droid_egl_display *droid_dpy = lookup_display(dpy);
368 struct droid_egl_surface *droid_surf = lookup_surface(surf);
370 if (_eglIsSurfaceBound(&droid_surf->base))
373 droid_screen_destroy_drawable(droid_dpy->screen, droid_surf->drawable);
374 droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_surf->surface);
381 droid_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
383 struct droid_egl_driver *droid_drv = lookup_driver(drv);
384 struct droid_egl_display *droid_dpy = lookup_display(dpy);
385 struct droid_egl_surface *droid_surf = lookup_surface(surf);
386 _EGLContext *ctx = _eglGetCurrentContext();
387 struct droid_egl_context *droid_ctx = lookup_context(ctx);
390 if (droid_drv->flush_current)
391 droid_drv->flush_current();
393 droid_screen_swap_buffers(droid_dpy->screen,
395 droid_surf->drawable);
401 #if EGL_KHR_image_base
404 droid_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
405 EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
407 struct droid_egl_display *droid_dpy = lookup_display(dpy);
408 struct droid_egl_image *droid_img;
409 const __DRIconfig *dri_conf;
412 if (target != EGL_NATIVE_PIXMAP_KHR || ctx) {
413 _eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
417 droid_img = calloc(1, sizeof(*droid_img));
419 _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
423 if (!_eglInitImage(drv, &droid_img->base, attr_list)) {
429 droid_dpy->backend->create_image_surface(droid_dpy->backend,
430 (NativePixmapType) buffer,
432 if (!droid_img->surface) {
437 dri_conf = droid_dpy->screen->image_configs[depth];
439 droid_dpy->backend->destroy_surface(droid_dpy->backend,
445 droid_img->drawable =
446 droid_screen_create_drawable(droid_dpy->screen, dri_conf,
449 if (!droid_img->drawable) {
450 droid_dpy->backend->destroy_surface(droid_dpy->backend,
456 droid_img->base.ClientData =
457 droid_screen_get_drawable_data(droid_dpy->screen, droid_img->drawable);
459 return &droid_img->base;
464 droid_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
466 struct droid_egl_display *droid_dpy = lookup_display(dpy);
467 struct droid_egl_image *droid_img = lookup_image(img);
469 droid_screen_destroy_drawable(droid_dpy->screen, droid_img->drawable);
470 droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_img->surface);
476 #endif /* EGL_KHR_image_base */
479 droid_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy)
481 struct droid_egl_driver *droid_drv = lookup_driver(drv);
482 _EGLContext *ctx = _eglGetCurrentContext();
484 if (!ctx || !droid_drv->finish_current)
487 if (!_eglIsSurfaceLinked(ctx->DrawSurface))
488 return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitClient");
490 droid_drv->finish_current();
496 droid_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
498 struct droid_egl_display *droid_dpy = lookup_display(dpy);
499 _EGLContext *ctx = _eglGetCurrentContext();
500 struct droid_egl_surface *droid_surf;
502 if (engine != EGL_CORE_NATIVE_ENGINE)
503 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
508 if (!_eglIsSurfaceLinked(ctx->DrawSurface))
509 return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitNative");
511 droid_surf = lookup_surface(ctx->DrawSurface);
512 droid_dpy->backend->swap_native_buffers(droid_dpy->backend,
513 droid_surf->surface);
519 droid_Unload(_EGLDriver *drv)
521 struct droid_egl_driver *droid_drv = lookup_driver(drv);
526 _eglMain(const char *args)
528 struct droid_egl_driver *droid_drv = calloc(1, sizeof(*droid_drv));
532 _eglInitDriverFallbacks(&droid_drv->base);
533 droid_drv->base.API.Initialize = droid_eglInitialize;
534 droid_drv->base.API.Terminate = droid_eglTerminate;
536 droid_drv->base.API.GetProcAddress = droid_eglGetProcAddress;
538 droid_drv->base.API.CreateContext = droid_eglCreateContext;
539 droid_drv->base.API.DestroyContext = droid_eglDestroyContext;
540 droid_drv->base.API.MakeCurrent = droid_eglMakeCurrent;
541 droid_drv->base.API.CreateWindowSurface = droid_eglCreateWindowSurface;
542 droid_drv->base.API.DestroySurface = droid_eglDestroySurface;
543 droid_drv->base.API.SwapBuffers = droid_eglSwapBuffers;
544 #if EGL_KHR_image_base
545 droid_drv->base.API.CreateImageKHR = droid_eglCreateImageKHR;
546 droid_drv->base.API.DestroyImageKHR = droid_eglDestroyImageKHR;
547 #endif /* EGL_KHR_image_base */
548 droid_drv->base.API.WaitClient = droid_eglWaitClient;
549 droid_drv->base.API.WaitNative = droid_eglWaitNative;
551 droid_drv->base.Name = "Android/i915";
552 droid_drv->base.Unload = droid_Unload;
554 /* we need a way to flush commands */
555 droid_drv->flush_current =
556 (void (*)(void)) droid_eglGetProcAddress("glFlush");
557 droid_drv->finish_current =
558 (void (*)(void)) droid_eglGetProcAddress("glFinish");
560 return &droid_drv->base;