2 * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
4 * This is based on the work of eagle, by
5 * Copyright © 2008, 2009 Kristian Høgsberg
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:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
27 #define LOG_TAG "DROID-LOADER"
28 #include <utils/Log.h>
36 #include "EGL/internal/eglimage_dri.h"
38 #ifndef DROID_DRIVER_PATH
39 #define DROID_DRIVER_PATH "/system/lib"
43 struct droid_backend *backend;
48 __DRIcoreExtension *core;
49 __DRIdri2Extension *dri2;
52 struct droid_context {
53 __DRIcontext *dri_context;
56 struct droid_drawable {
57 struct droid_loader *loader;
58 struct droid_surface *surface;
60 __DRIdrawable *dri_drawable;
61 const __DRIconfig *dri_config;
62 __DRIEGLImage *dri_image;
66 loader_ext_get_buffers_with_format(__DRIdrawable *driDrawable,
67 int *width, int *height,
68 unsigned int *attachments, int count,
69 int *out_count, void *loaderPrivate)
71 struct droid_drawable *drawable = (struct droid_drawable *) loaderPrivate;
72 struct droid_loader *loader = drawable->loader;
75 buffers = loader->backend->get_surface_buffers(loader->backend,
84 static const __DRIdri2LoaderExtension loader_ext_dri2_loader = {
85 { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
88 loader_ext_get_buffers_with_format,
92 loader_ext_get_ust(int64_t *ust)
99 if (gettimeofday(&tv, NULL) == 0) {
100 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
107 static const __DRIsystemTimeExtension loader_ext_system_time = {
108 { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
113 static const __DRIextension *loader_extensions[] = {
114 &loader_ext_dri2_loader.base,
115 &loader_ext_system_time.base,
119 static struct droid_loader *
120 loader_create(struct droid_backend *backend)
122 struct droid_loader *loader;
124 loader = calloc(1, sizeof(*loader));
128 loader->backend = backend;
134 loader_destroy(struct droid_loader *loader)
136 if (loader->filename)
137 free(loader->filename);
139 dlclose(loader->handle);
144 loader_load(struct droid_loader *loader, const char *filename)
146 const __DRIextension **extensions;
147 const char *path = NULL;
150 LOGD("Loading DRI driver %s", filename);
152 loader->handle = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
153 if (loader->handle == NULL) {
154 LOGE("dlopen: %s", dlerror());
158 extensions = dlsym(loader->handle, __DRI_DRIVER_EXTENSIONS);
159 if (extensions == NULL) {
160 LOGE("dlsym: %s", dlerror());
161 dlclose(loader->handle);
162 loader->handle = NULL;
166 for (i = 0; extensions[i]; i++) {
167 if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
168 extensions[i]->version >= __DRI_CORE_VERSION) {
169 loader->core = (__DRIcoreExtension *) extensions[i];
172 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
173 extensions[i]->version >= __DRI_DRI2_VERSION) {
174 loader->dri2 = (__DRIdri2Extension *) extensions[i];
178 if (loader->core == NULL || loader->dri2 == NULL) {
179 LOGE("missing required DRI extensions");
180 dlclose(loader->handle);
181 loader->handle = NULL;
189 loader_init(struct droid_loader *loader)
194 path = DROID_DRIVER_PATH;
195 snprintf(filename, sizeof(filename), "%s/%s_dri.so",
196 path, loader->backend->driver_name);
198 if (!loader_load(loader, filename))
201 loader->filename = strdup(filename);
207 droid_backend_destroy(struct droid_backend *backend)
209 backend->destroy(backend);
213 screen_find_image_configs(struct droid_screen *screen)
215 struct droid_loader *loader = screen->loader;
218 for (depth = 0; depth < DROID_MAX_IMAGE_DEPTH + 1; depth++) {
219 for (i = 0; i < screen->num_dri_configs; i++) {
220 const __DRIconfig *conf = screen->dri_configs[i];
224 droid_screen_convert_config(screen, conf, &egl_conf);
226 val = GET_CONFIG_ATTRIB(&egl_conf, EGL_CONFIG_CAVEAT);
227 if (val == EGL_SLOW_CONFIG)
230 rgba = GET_CONFIG_ATTRIB(&egl_conf, EGL_RED_SIZE);
231 rgba += GET_CONFIG_ATTRIB(&egl_conf, EGL_GREEN_SIZE);
232 rgba += GET_CONFIG_ATTRIB(&egl_conf, EGL_BLUE_SIZE);
233 rgba += GET_CONFIG_ATTRIB(&egl_conf, EGL_ALPHA_SIZE);
238 val = GET_CONFIG_ATTRIB(&egl_conf, EGL_BIND_TO_TEXTURE_RGBA);
240 screen->image_configs[depth] = conf;
245 val = GET_CONFIG_ATTRIB(&egl_conf, EGL_BIND_TO_TEXTURE_RGB);
247 screen->image_configs[depth] = conf;
254 struct droid_screen *
255 droid_screen_create(struct droid_backend *backend)
257 struct droid_screen *screen = NULL;
258 struct droid_loader *loader;
259 const __DRIextension **extensions;
260 int fd, screen_number;
263 loader = loader_create(backend);
264 if (!loader || !loader_init(loader)) {
265 LOGE("failed to initialize loader");
269 screen = calloc(1, sizeof(*screen));
271 LOGE("failed to allocate new screen");
275 if (!loader->backend->initialize(loader->backend, &fd, &screen_number)) {
276 LOGE("failed to initialize backend");
280 screen->loader = loader;
282 loader->dri2->createNewScreen(screen_number, fd,
284 &screen->dri_configs, NULL);
285 if (!screen->dri_screen) {
286 LOGE("failed to create DRI screen");
290 extensions = loader->core->getExtensions(screen->dri_screen);
292 for (i = 0; extensions && extensions[i]; i++) {
293 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0 &&
294 extensions[i]->version >= __DRI_TEX_BUFFER_VERSION)
295 screen->tex_buffer = (__DRItexBufferExtension *) extensions[i];
297 if (strcmp(extensions[i]->name, __DRI_COPY_BUFFER) == 0 &&
298 extensions[i]->version >= __DRI_COPY_BUFFER_VERSION)
299 screen->copy_buffer = (__DRIcopyBufferExtension *) extensions[i];
302 if (!screen->tex_buffer) {
303 LOGE("DRI driver has no TexBuffer extension");
307 if (!screen->tex_buffer) {
308 LOGE("DRI driver has no CopyBuffer extension");
312 for (i = 0; screen->dri_configs[i]; i++)
314 screen->num_dri_configs = i;
316 screen_find_image_configs(screen);
322 droid_screen_destroy(screen);
324 loader_destroy(loader);
330 droid_screen_destroy(struct droid_screen *screen)
332 struct droid_loader *loader = screen->loader;
333 if (screen->dri_screen)
334 loader->core->destroyScreen(screen->dri_screen);
338 static const struct {
340 unsigned int dri_attrib;
341 } droid_attrib_map[] = {
342 { EGL_BUFFER_SIZE, __DRI_ATTRIB_BUFFER_SIZE },
343 { EGL_RED_SIZE, __DRI_ATTRIB_RED_SIZE },
344 { EGL_GREEN_SIZE, __DRI_ATTRIB_GREEN_SIZE },
345 { EGL_BLUE_SIZE, __DRI_ATTRIB_BLUE_SIZE },
346 { EGL_ALPHA_SIZE, __DRI_ATTRIB_ALPHA_SIZE },
347 { EGL_BIND_TO_TEXTURE_RGB, __DRI_ATTRIB_BIND_TO_TEXTURE_RGB },
348 { EGL_BIND_TO_TEXTURE_RGBA, __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA },
349 { EGL_CONFIG_CAVEAT, __DRI_ATTRIB_CONFIG_CAVEAT },
350 { EGL_DEPTH_SIZE, __DRI_ATTRIB_DEPTH_SIZE },
351 { EGL_LEVEL, __DRI_ATTRIB_LEVEL },
352 { EGL_MAX_PBUFFER_WIDTH, __DRI_ATTRIB_MAX_PBUFFER_WIDTH },
353 { EGL_MAX_PBUFFER_HEIGHT, __DRI_ATTRIB_MAX_PBUFFER_HEIGHT },
354 { EGL_MAX_PBUFFER_PIXELS, __DRI_ATTRIB_MAX_PBUFFER_PIXELS },
355 { EGL_SAMPLE_BUFFERS, __DRI_ATTRIB_SAMPLE_BUFFERS },
356 { EGL_SAMPLES, __DRI_ATTRIB_SAMPLES },
357 { EGL_STENCIL_SIZE, __DRI_ATTRIB_STENCIL_SIZE },
361 droid_screen_convert_config(struct droid_screen *screen,
362 const __DRIconfig *conf, _EGLConfig *egl_conf)
364 struct droid_loader *loader = screen->loader;
365 const int num_attrs =
366 sizeof(droid_attrib_map) / sizeof(droid_attrib_map[0]);
369 for (i = 0; i < num_attrs; i++) {
370 unsigned int dri_attrib = droid_attrib_map[i].dri_attrib;
371 unsigned int dri_value;
372 EGLenum egl_attrib = droid_attrib_map[i].egl_attrib;
375 if (!loader->core->getConfigAttrib(conf, dri_attrib, &dri_value)) {
376 LOGE("failed to get attribute %02d for %p", dri_attrib, conf);
380 switch (egl_attrib) {
381 case EGL_CONFIG_CAVEAT:
382 if (dri_value & __DRI_ATTRIB_SLOW_BIT)
383 egl_value = EGL_SLOW_CONFIG;
384 else if (dri_value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
385 egl_value = EGL_NON_CONFORMANT_CONFIG;
387 egl_value = EGL_NONE;
390 egl_value = (EGLint) dri_value;
393 SET_CONFIG_ATTRIB(egl_conf, egl_attrib, egl_value);
397 struct droid_context *
398 droid_screen_create_context(struct droid_screen *screen,
399 const __DRIconfig *conf,
400 struct droid_context *shared)
402 struct droid_loader *loader = screen->loader;
403 struct droid_context *ctx;
405 ctx = calloc(1, sizeof(*ctx));
407 LOGE("failed to allocate context");
412 loader->dri2->createNewContext(screen->dri_screen, conf,
413 (shared) ? shared->dri_context : NULL,
415 if (!ctx->dri_context) {
416 LOGE("failed to create DRI context");
425 droid_screen_destroy_context(struct droid_screen *screen,
426 struct droid_context *ctx)
428 struct droid_loader *loader = screen->loader;
429 loader->core->destroyContext(ctx->dri_context);
433 struct droid_drawable *
434 droid_screen_create_drawable(struct droid_screen *screen,
435 const __DRIconfig *conf,
436 struct droid_surface *surf)
438 struct droid_loader *loader = screen->loader;
439 struct droid_drawable *drawable;
441 drawable = calloc(1, sizeof(*drawable));
443 LOGE("failed to allocate drawable");
447 /* needed in GetBuffers */
448 drawable->loader = loader;
449 drawable->surface = surf;
450 drawable->dri_config = conf;
452 drawable->dri_drawable =
453 loader->dri2->createNewDrawable(screen->dri_screen,
454 conf, (void *) drawable);
455 if (!drawable->dri_drawable) {
456 LOGE("failed to create DRI drawable");
465 droid_screen_get_drawable_data(struct droid_screen *screen,
466 struct droid_drawable *drawable)
468 struct droid_loader *loader = screen->loader;
469 __DRIEGLImage *img = drawable->dri_image;
474 img = calloc(1, sizeof(__DRIEGLImage));
478 img->magic = __DRI_EGL_IMAGE_MAGIC;
479 img->drawable = drawable->dri_drawable;
481 if (loader->core->getConfigAttrib(drawable->dri_config,
482 EGL_BIND_TO_TEXTURE_RGBA, &val))
483 img->texture_format_rgba = val;
485 drawable->dri_image = img;
492 droid_screen_destroy_drawable(struct droid_screen *screen,
493 struct droid_drawable *drawable)
495 struct droid_loader *loader = screen->loader;
496 if (drawable->dri_image)
497 free(drawable->dri_image);
498 loader->core->destroyDrawable(drawable->dri_drawable);
503 droid_screen_bind_context(struct droid_screen *screen,
504 struct droid_drawable *draw,
505 struct droid_drawable *read,
506 struct droid_context *ctx)
508 struct droid_loader *loader = screen->loader;
513 ret = loader->core->bindContext(ctx->dri_context,
516 else if (!draw && !read)
517 ret = loader->core->unbindContext(ctx->dri_context);
521 LOGE("failed to bind context %p", ctx);
527 droid_screen_swap_buffers(struct droid_screen *screen,
528 struct droid_context *ctx,
529 struct droid_drawable *drawable)
531 struct droid_loader *loader = screen->loader;
536 native = loader->backend->get_native_buffer(loader->backend,
540 /* copy from front buffer to native buffer */
542 err = screen->copy_buffer->copyBuffer(ctx->dri_context, native, 0, 0,
543 drawable->dri_drawable,
544 __DRI_BUFFER_FRONT_LEFT, 0, 0,
548 loader->backend->swap_native_buffers(loader->backend, drawable->surface);