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