Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
  5.  * Copyright (C) 2010-2011 LunarG Inc.
  6.  *
  7.  * Based on platform_x11, which has
  8.  *
  9.  * Copyright © 2011 Intel Corporation
  10.  *
  11.  * Permission is hereby granted, free of charge, to any person obtaining a
  12.  * copy of this software and associated documentation files (the "Software"),
  13.  * to deal in the Software without restriction, including without limitation
  14.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15.  * and/or sell copies of the Software, and to permit persons to whom the
  16.  * Software is furnished to do so, subject to the following conditions:
  17.  *
  18.  * The above copyright notice and this permission notice shall be included
  19.  * in all copies or substantial portions of the Software.
  20.  *
  21.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  24.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27.  * DEALINGS IN THE SOFTWARE.
  28.  */
  29.  
  30. #include <errno.h>
  31. #include <dlfcn.h>
  32.  
  33. #if ANDROID_VERSION >= 0x402
  34. #include <sync/sync.h>
  35. #endif
  36.  
  37. /* for droid_get_pci_id */
  38. #include <xf86drm.h>
  39. #include <i915_drm.h>
  40. #include <radeon_drm.h>
  41.  
  42. #include "egl_dri2.h"
  43. #include "gralloc_drm.h"
  44.  
  45. static int
  46. get_format_bpp(int native)
  47. {
  48.    int bpp;
  49.  
  50.    switch (native) {
  51.    case HAL_PIXEL_FORMAT_RGBA_8888:
  52.    case HAL_PIXEL_FORMAT_RGBX_8888:
  53.    case HAL_PIXEL_FORMAT_BGRA_8888:
  54.       bpp = 4;
  55.       break;
  56.    case HAL_PIXEL_FORMAT_RGB_888:
  57.       bpp = 3;
  58.       break;
  59.    case HAL_PIXEL_FORMAT_RGB_565:
  60.    case HAL_PIXEL_FORMAT_RGBA_5551:
  61.    case HAL_PIXEL_FORMAT_RGBA_4444:
  62.       bpp = 2;
  63.       break;
  64.    default:
  65.       bpp = 0;
  66.       break;
  67.    }
  68.  
  69.    return bpp;
  70. }
  71.  
  72. static int
  73. get_native_buffer_name(struct ANativeWindowBuffer *buf)
  74. {
  75.    return gralloc_drm_get_gem_handle(buf->handle);
  76. }
  77.  
  78. static EGLBoolean
  79. droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
  80. {
  81. #if ANDROID_VERSION >= 0x0402
  82.    int fence_fd;
  83.  
  84.    if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
  85.                                         &fence_fd))
  86.       return EGL_FALSE;
  87.  
  88.    /* If access to the buffer is controlled by a sync fence, then block on the
  89.     * fence.
  90.     *
  91.     * It may be more performant to postpone blocking until there is an
  92.     * immediate need to write to the buffer. But doing so would require adding
  93.     * hooks to the DRI2 loader.
  94.     *
  95.     * From the ANativeWindow::dequeueBuffer documentation:
  96.     *
  97.     *    The libsync fence file descriptor returned in the int pointed to by
  98.     *    the fenceFd argument will refer to the fence that must signal
  99.     *    before the dequeued buffer may be written to.  A value of -1
  100.     *    indicates that the caller may access the buffer immediately without
  101.     *    waiting on a fence.  If a valid file descriptor is returned (i.e.
  102.     *    any value except -1) then the caller is responsible for closing the
  103.     *    file descriptor.
  104.     */
  105.     if (fence_fd >= 0) {
  106.        /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:
  107.         *
  108.         *    Waits indefinitely if timeout < 0.
  109.         */
  110.         int timeout = -1;
  111.         sync_wait(fence_fd, timeout);
  112.         close(fence_fd);
  113.    }
  114.  
  115.    dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
  116. #else
  117.    if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer))
  118.       return EGL_FALSE;
  119.  
  120.    dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
  121.    dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer);
  122. #endif
  123.  
  124.    return EGL_TRUE;
  125. }
  126.  
  127. static EGLBoolean
  128. droid_window_enqueue_buffer(struct dri2_egl_surface *dri2_surf)
  129. {
  130. #if ANDROID_VERSION >= 0x0402
  131.    /* Queue the buffer without a sync fence. This informs the ANativeWindow
  132.     * that it may access the buffer immediately.
  133.     *
  134.     * From ANativeWindow::dequeueBuffer:
  135.     *
  136.     *    The fenceFd argument specifies a libsync fence file descriptor for
  137.     *    a fence that must signal before the buffer can be accessed.  If
  138.     *    the buffer can be accessed immediately then a value of -1 should
  139.     *    be used.  The caller must not use the file descriptor after it
  140.     *    is passed to queueBuffer, and the ANativeWindow implementation
  141.     *    is responsible for closing it.
  142.     */
  143.    int fence_fd = -1;
  144.    dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
  145.                                   fence_fd);
  146. #else
  147.    dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer);
  148. #endif
  149.  
  150.    dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common);
  151.    dri2_surf->buffer = NULL;
  152.  
  153.    return EGL_TRUE;
  154. }
  155.  
  156. static void
  157. droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
  158. {
  159.    /* no cancel buffer? */
  160.    droid_window_enqueue_buffer(dri2_surf);
  161. }
  162.  
  163. static __DRIbuffer *
  164. droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
  165.                          unsigned int att, unsigned int format)
  166. {
  167.    struct dri2_egl_display *dri2_dpy =
  168.       dri2_egl_display(dri2_surf->base.Resource.Display);
  169.  
  170.    if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
  171.       return NULL;
  172.  
  173.    if (!dri2_surf->local_buffers[att]) {
  174.       dri2_surf->local_buffers[att] =
  175.          dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
  176.                dri2_surf->base.Width, dri2_surf->base.Height);
  177.    }
  178.  
  179.    return dri2_surf->local_buffers[att];
  180. }
  181.  
  182. static void
  183. droid_free_local_buffers(struct dri2_egl_surface *dri2_surf)
  184. {
  185.    struct dri2_egl_display *dri2_dpy =
  186.       dri2_egl_display(dri2_surf->base.Resource.Display);
  187.    int i;
  188.  
  189.    for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
  190.       if (dri2_surf->local_buffers[i]) {
  191.          dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
  192.                dri2_surf->local_buffers[i]);
  193.          dri2_surf->local_buffers[i] = NULL;
  194.       }
  195.    }
  196. }
  197.  
  198. static _EGLSurface *
  199. droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
  200.                     _EGLConfig *conf, EGLNativeWindowType window,
  201.                     const EGLint *attrib_list)
  202. {
  203.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  204.    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  205.    struct dri2_egl_surface *dri2_surf;
  206.    dri2_surf = calloc(1, sizeof *dri2_surf);
  207.    if (!dri2_surf) {
  208.       _eglError(EGL_BAD_ALLOC, "droid_create_surface");
  209.       return NULL;
  210.    }
  211.  
  212.    if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
  213.       goto cleanup_surface;
  214.  
  215.    if (type == EGL_WINDOW_BIT) {
  216.       int format;
  217.  
  218.       if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
  219.          _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
  220.          goto cleanup_surface;
  221.       }
  222.       if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
  223.          _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
  224.          goto cleanup_surface;
  225.       }
  226.  
  227.       if (format != dri2_conf->base.NativeVisualID) {
  228.          _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
  229.                format, dri2_conf->base.NativeVisualID);
  230.       }
  231.  
  232.       window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width);
  233.       window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
  234.    }
  235.  
  236.    dri2_surf->dri_drawable =
  237.       (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen,
  238.                                            dri2_conf->dri_double_config,
  239.                                            dri2_surf);
  240.    if (dri2_surf->dri_drawable == NULL) {
  241.       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
  242.       goto cleanup_surface;
  243.    }
  244.  
  245.    if (window) {
  246.       window->common.incRef(&window->common);
  247.       dri2_surf->window = window;
  248.    }
  249.  
  250.    return &dri2_surf->base;
  251.  
  252. cleanup_surface:
  253.    free(dri2_surf);
  254.  
  255.    return NULL;
  256. }
  257.  
  258. static _EGLSurface *
  259. droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
  260.                            _EGLConfig *conf, EGLNativeWindowType window,
  261.                            const EGLint *attrib_list)
  262. {
  263.    return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
  264.                               window, attrib_list);
  265. }
  266.  
  267. static _EGLSurface *
  268. droid_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
  269.                            _EGLConfig *conf, EGLNativePixmapType pixmap,
  270.                            const EGLint *attrib_list)
  271. {
  272.    return NULL;
  273. }
  274.  
  275. static _EGLSurface *
  276. droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
  277.                             _EGLConfig *conf, const EGLint *attrib_list)
  278. {
  279.    return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
  280.                               NULL, attrib_list);
  281. }
  282.  
  283. static EGLBoolean
  284. droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  285. {
  286.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  287.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  288.  
  289.    if (!_eglPutSurface(surf))
  290.       return EGL_TRUE;
  291.  
  292.    droid_free_local_buffers(dri2_surf);
  293.  
  294.    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  295.       if (dri2_surf->buffer)
  296.          droid_window_cancel_buffer(dri2_surf);
  297.  
  298.       dri2_surf->window->common.decRef(&dri2_surf->window->common);
  299.    }
  300.  
  301.    (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
  302.  
  303.    free(dri2_surf);
  304.  
  305.    return EGL_TRUE;
  306. }
  307.  
  308. static EGLBoolean
  309. droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  310. {
  311.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  312.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  313.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  314.    _EGLContext *ctx;
  315.  
  316.    if (dri2_surf->base.Type != EGL_WINDOW_BIT)
  317.       return EGL_TRUE;
  318.  
  319.    if (dri2_drv->glFlush) {
  320.       ctx = _eglGetCurrentContext();
  321.       if (ctx && ctx->DrawSurface == &dri2_surf->base)
  322.          dri2_drv->glFlush();
  323.    }
  324.  
  325.    (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
  326.  
  327.    if (dri2_surf->buffer)
  328.       droid_window_enqueue_buffer(dri2_surf);
  329.  
  330.    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  331.  
  332.    return EGL_TRUE;
  333. }
  334.  
  335. static _EGLImage *
  336. dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
  337.                                         struct ANativeWindowBuffer *buf)
  338. {
  339.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  340.    struct dri2_egl_image *dri2_img;
  341.    int name;
  342.    EGLint format;
  343.  
  344.    if (ctx != NULL) {
  345.       /* From the EGL_ANDROID_image_native_buffer spec:
  346.        *
  347.        *     * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
  348.        *       EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
  349.        */
  350.       _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
  351.                 "EGL_NATIVE_BUFFER_ANDROID, the context must be "
  352.                 "EGL_NO_CONTEXT");
  353.       return NULL;
  354.    }
  355.  
  356.    if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
  357.        buf->common.version != sizeof(*buf)) {
  358.       _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
  359.       return NULL;
  360.    }
  361.  
  362.    name = get_native_buffer_name(buf);
  363.    if (!name) {
  364.       _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
  365.       return NULL;
  366.    }
  367.  
  368.    /* see the table in droid_add_configs_for_visuals */
  369.    switch (buf->format) {
  370.    case HAL_PIXEL_FORMAT_BGRA_8888:
  371.       format = __DRI_IMAGE_FORMAT_ARGB8888;
  372.       break;
  373.    case HAL_PIXEL_FORMAT_RGB_565:
  374.       format = __DRI_IMAGE_FORMAT_RGB565;
  375.       break;
  376.    case HAL_PIXEL_FORMAT_RGBA_8888:
  377.       format = __DRI_IMAGE_FORMAT_ABGR8888;
  378.       break;
  379.    case HAL_PIXEL_FORMAT_RGBX_8888:
  380.       format = __DRI_IMAGE_FORMAT_XBGR8888;
  381.       break;
  382.    case HAL_PIXEL_FORMAT_RGB_888:
  383.    case HAL_PIXEL_FORMAT_RGBA_5551:
  384.    case HAL_PIXEL_FORMAT_RGBA_4444:
  385.       /* unsupported */
  386.    default:
  387.       _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", buf->format);
  388.       return NULL;
  389.       break;
  390.    }
  391.  
  392.    dri2_img = calloc(1, sizeof(*dri2_img));
  393.    if (!dri2_img) {
  394.       _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
  395.       return NULL;
  396.    }
  397.  
  398.    if (!_eglInitImage(&dri2_img->base, disp)) {
  399.       free(dri2_img);
  400.       return NULL;
  401.    }
  402.  
  403.    dri2_img->dri_image =
  404.       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
  405.                                            buf->width,
  406.                                            buf->height,
  407.                                            format,
  408.                                            name,
  409.                                            buf->stride,
  410.                                            dri2_img);
  411.    if (!dri2_img->dri_image) {
  412.       free(dri2_img);
  413.       _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
  414.       return NULL;
  415.    }
  416.  
  417.    return &dri2_img->base;
  418. }
  419.  
  420. static _EGLImage *
  421. droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  422.                        _EGLContext *ctx, EGLenum target,
  423.                        EGLClientBuffer buffer, const EGLint *attr_list)
  424. {
  425.    switch (target) {
  426.    case EGL_NATIVE_BUFFER_ANDROID:
  427.       return dri2_create_image_android_native_buffer(disp, ctx,
  428.             (struct ANativeWindowBuffer *) buffer);
  429.    default:
  430.       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
  431.    }
  432. }
  433.  
  434. static void
  435. droid_init_driver_functions(_EGLDriver *drv)
  436. {
  437.    drv->API.CreateWindowSurface = droid_create_window_surface;
  438.    drv->API.CreatePixmapSurface = droid_create_pixmap_surface;
  439.    drv->API.CreatePbufferSurface = droid_create_pbuffer_surface;
  440.    drv->API.DestroySurface = droid_destroy_surface;
  441.    drv->API.SwapBuffers = droid_swap_buffers;
  442.  
  443.    drv->API.CreateImageKHR = droid_create_image_khr;
  444. }
  445.  
  446. static void
  447. droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  448. {
  449. }
  450.  
  451. static int
  452. droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
  453.                                     unsigned int *attachments, int count)
  454. {
  455.    int num_buffers = 0, i;
  456.  
  457.    /* fill dri2_surf->buffers */
  458.    for (i = 0; i < count * 2; i += 2) {
  459.       __DRIbuffer *buf, *local;
  460.  
  461.       assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
  462.       buf = &dri2_surf->buffers[num_buffers];
  463.  
  464.       switch (attachments[i]) {
  465.       case __DRI_BUFFER_BACK_LEFT:
  466.          if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  467.             buf->attachment = attachments[i];
  468.             buf->name = get_native_buffer_name(dri2_surf->buffer);
  469.             buf->cpp = get_format_bpp(dri2_surf->buffer->format);
  470.             buf->pitch = dri2_surf->buffer->stride * buf->cpp;
  471.             buf->flags = 0;
  472.  
  473.             if (buf->name)
  474.                num_buffers++;
  475.  
  476.             break;
  477.          }
  478.          /* fall through for pbuffers */
  479.       case __DRI_BUFFER_DEPTH:
  480.       case __DRI_BUFFER_STENCIL:
  481.       case __DRI_BUFFER_ACCUM:
  482.       case __DRI_BUFFER_DEPTH_STENCIL:
  483.       case __DRI_BUFFER_HIZ:
  484.          local = droid_alloc_local_buffer(dri2_surf,
  485.                attachments[i], attachments[i + 1]);
  486.  
  487.          if (local) {
  488.             *buf = *local;
  489.             num_buffers++;
  490.          }
  491.          break;
  492.       case __DRI_BUFFER_FRONT_LEFT:
  493.       case __DRI_BUFFER_FRONT_RIGHT:
  494.       case __DRI_BUFFER_FAKE_FRONT_LEFT:
  495.       case __DRI_BUFFER_FAKE_FRONT_RIGHT:
  496.       case __DRI_BUFFER_BACK_RIGHT:
  497.       default:
  498.          /* no front or right buffers */
  499.          break;
  500.       }
  501.    }
  502.  
  503.    return num_buffers;
  504. }
  505.  
  506. static __DRIbuffer *
  507. droid_get_buffers_with_format(__DRIdrawable * driDrawable,
  508.                              int *width, int *height,
  509.                              unsigned int *attachments, int count,
  510.                              int *out_count, void *loaderPrivate)
  511. {
  512.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  513.    struct dri2_egl_display *dri2_dpy =
  514.       dri2_egl_display(dri2_surf->base.Resource.Display);
  515.    int i;
  516.  
  517.    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  518.       /* try to dequeue the next back buffer */
  519.       if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf))
  520.          return NULL;
  521.  
  522.       /* free outdated buffers and update the surface size */
  523.       if (dri2_surf->base.Width != dri2_surf->buffer->width ||
  524.           dri2_surf->base.Height != dri2_surf->buffer->height) {
  525.          droid_free_local_buffers(dri2_surf);
  526.          dri2_surf->base.Width = dri2_surf->buffer->width;
  527.          dri2_surf->base.Height = dri2_surf->buffer->height;
  528.       }
  529.    }
  530.  
  531.    dri2_surf->buffer_count =
  532.       droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
  533.  
  534.    if (width)
  535.       *width = dri2_surf->base.Width;
  536.    if (height)
  537.       *height = dri2_surf->base.Height;
  538.  
  539.    *out_count = dri2_surf->buffer_count;;
  540.  
  541.    return dri2_surf->buffers;
  542. }
  543.  
  544. static EGLBoolean
  545. droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
  546. {
  547.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  548.    const struct {
  549.       int format;
  550.       int size;
  551.       unsigned int rgba_masks[4];
  552.    } visuals[] = {
  553.       { HAL_PIXEL_FORMAT_RGBA_8888, 32, { 0xff, 0xff00, 0xff0000, 0xff000000 } },
  554.       { HAL_PIXEL_FORMAT_RGBX_8888, 32, { 0xff, 0xff00, 0xff0000, 0x0 } },
  555.       { HAL_PIXEL_FORMAT_RGB_888,   24, { 0xff, 0xff00, 0xff0000, 0x0 } },
  556.       { HAL_PIXEL_FORMAT_RGB_565,   16, { 0xf800, 0x7e0, 0x1f, 0x0 } },
  557.       { HAL_PIXEL_FORMAT_BGRA_8888, 32, { 0xff0000, 0xff00, 0xff, 0xff000000 } },
  558.       { 0, 0, { 0, 0, 0, 0 } }
  559.    };
  560.    int count, i, j;
  561.  
  562.    count = 0;
  563.    for (i = 0; visuals[i].format; i++) {
  564.       int format_count = 0;
  565.  
  566.       for (j = 0; dri2_dpy->driver_configs[j]; j++) {
  567.          const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
  568.          struct dri2_egl_config *dri2_conf;
  569.          unsigned int double_buffered = 0;
  570.  
  571.          dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[j],
  572.             __DRI_ATTRIB_DOUBLE_BUFFER, &double_buffered);
  573.  
  574.          /* support only double buffered configs */
  575.          if (!double_buffered)
  576.             continue;
  577.  
  578.          dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[j],
  579.                count + 1, visuals[i].size, surface_type, NULL,
  580.                visuals[i].rgba_masks);
  581.          if (dri2_conf) {
  582.             dri2_conf->base.NativeVisualID = visuals[i].format;
  583.             dri2_conf->base.NativeVisualType = visuals[i].format;
  584.             count++;
  585.             format_count++;
  586.          }
  587.       }
  588.  
  589.       if (!format_count) {
  590.          _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
  591.                visuals[i].format);
  592.       }
  593.    }
  594.  
  595.    /* post-process configs */
  596.    for (i = 0; i < dpy->Configs->Size; i++) {
  597.       struct dri2_egl_config *dri2_conf = dri2_egl_config(dpy->Configs->Elements[i]);
  598.  
  599.       /* there is no front buffer so no OpenGL */
  600.       dri2_conf->base.RenderableType &= ~EGL_OPENGL_BIT;
  601.       dri2_conf->base.Conformant &= ~EGL_OPENGL_BIT;
  602.    }
  603.  
  604.    return (count != 0);
  605. }
  606.  
  607. static EGLBoolean
  608. droid_get_pci_id(int fd, int *vendor_id, int *chip_id)
  609. {
  610.    drmVersionPtr version;
  611.  
  612.    *chip_id = -1;
  613.  
  614.    version = drmGetVersion(fd);
  615.    if (!version) {
  616.       _eglLog(_EGL_WARNING, "invalid drm fd");
  617.       return EGL_FALSE;
  618.    }
  619.    if (!version->name) {
  620.       _eglLog(_EGL_WARNING, "unable to determine the driver name");
  621.       drmFreeVersion(version);
  622.       return EGL_FALSE;
  623.    }
  624.  
  625.    if (strcmp(version->name, "i915") == 0) {
  626.       struct drm_i915_getparam gp;
  627.       int ret;
  628.  
  629.       *vendor_id = 0x8086;
  630.  
  631.       memset(&gp, 0, sizeof(gp));
  632.       gp.param = I915_PARAM_CHIPSET_ID;
  633.       gp.value = chip_id;
  634.       ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
  635.       if (ret) {
  636.          _eglLog(_EGL_WARNING, "failed to get param for i915");
  637.          *chip_id = -1;
  638.       }
  639.    }
  640.    else if (strcmp(version->name, "radeon") == 0) {
  641.       struct drm_radeon_info info;
  642.       int ret;
  643.  
  644.       *vendor_id = 0x1002;
  645.  
  646.       memset(&info, 0, sizeof(info));
  647.       info.request = RADEON_INFO_DEVICE_ID;
  648.       info.value = (unsigned long) chip_id;
  649.       ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
  650.       if (ret) {
  651.          _eglLog(_EGL_WARNING, "failed to get info for radeon");
  652.          *chip_id = -1;
  653.       }
  654.    }
  655.    else if (strcmp(version->name, "nouveau") == 0) {
  656.       *vendor_id = 0x10de;
  657.       /* not used */
  658.       *chip_id = 0;
  659.    }
  660.    else if (strcmp(version->name, "vmwgfx") == 0) {
  661.       *vendor_id = 0x15ad;
  662.       /* assume SVGA II */
  663.       *chip_id = 0x0405;
  664.    }
  665.  
  666.    drmFreeVersion(version);
  667.  
  668.    return (*chip_id >= 0);
  669. }
  670.  
  671. #define DRIVER_MAP_DRI2_ONLY
  672. #include "pci_ids/pci_id_driver_map.h"
  673. static const char *
  674. droid_get_driver_name(int fd)
  675. {
  676.    int vendor_id = -1, chip_id = -1;
  677.    int idx, i;
  678.    char *name;
  679.  
  680.    if (!droid_get_pci_id(fd, &vendor_id, &chip_id))
  681.       return NULL;
  682.  
  683.    for (idx = 0; driver_map[idx].driver; idx++) {
  684.       if (vendor_id != driver_map[idx].vendor_id)
  685.          continue;
  686.  
  687.       if (driver_map[idx].num_chips_ids == -1)
  688.          break;
  689.  
  690.       for (i = 0; i < driver_map[idx].num_chips_ids; i++) {
  691.          if (driver_map[idx].chip_ids[i] == chip_id)
  692.             break;
  693.       }
  694.       if (i < driver_map[idx].num_chips_ids)
  695.               break;
  696.    }
  697.  
  698.    _eglLog(_EGL_INFO, "pci id for fd %d: %04x:%04x, driver %s",
  699.          fd, vendor_id, chip_id, driver_map[idx].driver);
  700.  
  701.    return driver_map[idx].driver;
  702. }
  703.  
  704. static int
  705. droid_open_device(void)
  706. {
  707.    const hw_module_t *mod;
  708.    int fd = -1, err;
  709.  
  710.    err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
  711.    if (!err) {
  712.       const gralloc_module_t *gr = (gralloc_module_t *) mod;
  713.  
  714.       err = -EINVAL;
  715.       if (gr->perform)
  716.          err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
  717.    }
  718.    if (err || fd < 0) {
  719.       _eglLog(_EGL_WARNING, "fail to get drm fd");
  720.       fd = -1;
  721.    }
  722.  
  723.    return (fd >= 0) ? dup(fd) : -1;
  724. }
  725.  
  726. /* support versions < JellyBean */
  727. #ifndef ALOGW
  728. #define ALOGW LOGW
  729. #endif
  730. #ifndef ALOGD
  731. #define ALOGD LOGD
  732. #endif
  733. #ifndef ALOGI
  734. #define ALOGI LOGI
  735. #endif
  736.  
  737. static void
  738. droid_log(EGLint level, const char *msg)
  739. {
  740.    switch (level) {
  741.    case _EGL_DEBUG:
  742.       ALOGD("%s", msg);
  743.       break;
  744.    case _EGL_INFO:
  745.       ALOGI("%s", msg);
  746.       break;
  747.    case _EGL_WARNING:
  748.       ALOGW("%s", msg);
  749.       break;
  750.    case _EGL_FATAL:
  751.       LOG_FATAL("%s", msg);
  752.       break;
  753.    default:
  754.       break;
  755.    }
  756. }
  757.  
  758. EGLBoolean
  759. dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
  760. {
  761.    struct dri2_egl_display *dri2_dpy;
  762.    const char *err;
  763.  
  764.    _eglSetLogProc(droid_log);
  765.  
  766.    dri2_dpy = calloc(1, sizeof(*dri2_dpy));
  767.    if (!dri2_dpy)
  768.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  769.  
  770.    dpy->DriverData = (void *) dri2_dpy;
  771.  
  772.    dri2_dpy->fd = droid_open_device();
  773.    if (dri2_dpy->fd < 0) {
  774.       err = "DRI2: failed to open device";
  775.       goto cleanup_display;
  776.    }
  777.  
  778.    dri2_dpy->driver_name = (char *) droid_get_driver_name(dri2_dpy->fd);
  779.    if (dri2_dpy->driver_name == NULL) {
  780.       err = "DRI2: failed to get driver name";
  781.       goto cleanup_device;
  782.    }
  783.  
  784.    if (!dri2_load_driver(dpy)) {
  785.       err = "DRI2: failed to load driver";
  786.       goto cleanup_device;
  787.    }
  788.  
  789.    dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
  790.    dri2_dpy->dri2_loader_extension.base.version = 3;
  791.    dri2_dpy->dri2_loader_extension.getBuffers = NULL;
  792.    dri2_dpy->dri2_loader_extension.flushFrontBuffer = droid_flush_front_buffer;
  793.    dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
  794.       droid_get_buffers_with_format;
  795.  
  796.    dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
  797.    dri2_dpy->extensions[1] = &image_lookup_extension.base;
  798.    dri2_dpy->extensions[2] = &use_invalidate.base;
  799.    dri2_dpy->extensions[3] = NULL;
  800.  
  801.    if (!dri2_create_screen(dpy)) {
  802.       err = "DRI2: failed to create screen";
  803.       goto cleanup_driver;
  804.    }
  805.  
  806.    if (!droid_add_configs_for_visuals(drv, dpy)) {
  807.       err = "DRI2: failed to add configs";
  808.       goto cleanup_screen;
  809.    }
  810.  
  811.    dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
  812.    dpy->Extensions.KHR_image_base = EGL_TRUE;
  813.  
  814.    /* we're supporting EGL 1.4 */
  815.    dpy->VersionMajor = 1;
  816.    dpy->VersionMinor = 4;
  817.  
  818.    droid_init_driver_functions(drv);
  819.  
  820.    return EGL_TRUE;
  821.  
  822. cleanup_screen:
  823.    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
  824. cleanup_driver:
  825.    dlclose(dri2_dpy->driver);
  826. cleanup_device:
  827.    close(dri2_dpy->fd);
  828. cleanup_display:
  829.    free(dri2_dpy);
  830.  
  831.    return _eglError(EGL_NOT_INITIALIZED, err);
  832. }
  833.