Home | History | Annotate | Download | only in android
      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  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included
     16  * in all copies or substantial portions of the Software.
     17  *
     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.
     25  */
     26 
     27 #define LOG_TAG "EGL-GALLIUM"
     28 
     29 #if ANDROID_VERSION >= 0x0400
     30 #include <stdlib.h>
     31 #include <system/window.h>
     32 #else
     33 #define android_native_buffer_t ANativeWindowBuffer
     34 #include <ui/egl/android_natives.h>
     35 #include <ui/android_native_buffer.h>
     36 #endif
     37 
     38 #include <hardware/gralloc.h>
     39 #include <cutils/properties.h>
     40 #include <cutils/log.h>
     41 #include <utils/Errors.h>
     42 
     43 extern "C" {
     44 #include "egllog.h"
     45 }
     46 
     47 #include "util/u_memory.h"
     48 #include "util/u_inlines.h"
     49 #include "util/u_format.h"
     50 #include "util/u_box.h"
     51 #include "common/native.h"
     52 #include "common/native_helper.h"
     53 #include "android/android_sw_winsys.h"
     54 #include "state_tracker/drm_driver.h"
     55 
     56 struct android_config;
     57 
     58 struct android_display {
     59    struct native_display base;
     60 
     61    boolean use_drm;
     62    const struct native_event_handler *event_handler;
     63    struct android_config *configs;
     64    int num_configs;
     65 };
     66 
     67 struct android_surface {
     68    struct native_surface base;
     69 
     70    struct android_display *adpy;
     71    ANativeWindow *win;
     72 
     73    /* staging color buffer for when buffer preserving is enabled */
     74    struct pipe_resource *color_res;
     75 
     76    uint stamp;
     77    ANativeWindowBuffer *buf;
     78    struct pipe_resource *buf_res;
     79 
     80    /* cache the current back buffers */
     81    struct {
     82       int width;
     83       int height;
     84       int format;
     85    } cache_key;
     86    void *cache_handles[2];
     87    struct pipe_resource *cache_resources[2];
     88 };
     89 
     90 struct android_config {
     91    struct native_config base;
     92 };
     93 
     94 static INLINE struct android_display *
     95 android_display(const struct native_display *ndpy)
     96 {
     97    return (struct android_display *) ndpy;
     98 }
     99 
    100 static INLINE struct android_surface *
    101 android_surface(const struct native_surface *nsurf)
    102 {
    103    return (struct android_surface *) nsurf;
    104 }
    105 
    106 static INLINE struct android_config *
    107 android_config(const struct native_config *nconf)
    108 {
    109    return (struct android_config *) nconf;
    110 }
    111 
    112 namespace android {
    113 
    114 static enum pipe_format
    115 get_pipe_format(int native)
    116 {
    117    enum pipe_format fmt;
    118 
    119    switch (native) {
    120    case HAL_PIXEL_FORMAT_RGBA_8888:
    121       fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
    122       break;
    123    case HAL_PIXEL_FORMAT_RGBX_8888:
    124       fmt = PIPE_FORMAT_R8G8B8X8_UNORM;
    125       break;
    126    case HAL_PIXEL_FORMAT_RGB_888:
    127       fmt = PIPE_FORMAT_R8G8B8_UNORM;
    128       break;
    129    case HAL_PIXEL_FORMAT_RGB_565:
    130       fmt = PIPE_FORMAT_B5G6R5_UNORM;
    131       break;
    132    case HAL_PIXEL_FORMAT_BGRA_8888:
    133       fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
    134       break;
    135    case HAL_PIXEL_FORMAT_RGBA_5551:
    136       /* fmt = PIPE_FORMAT_A1B5G5R5_UNORM; */
    137    case HAL_PIXEL_FORMAT_RGBA_4444:
    138       /* fmt = PIPE_FORMAT_A4B4G4R4_UNORM; */
    139    default:
    140       LOGE("unsupported native format 0x%x", native);
    141       fmt = PIPE_FORMAT_NONE;
    142       break;
    143    }
    144 
    145    return fmt;
    146 }
    147 
    148 #ifndef ANDROID_BACKEND_NO_DRM
    149 
    150 #include <gralloc_drm_handle.h>
    151 static int
    152 get_handle_name(buffer_handle_t handle)
    153 {
    154    struct gralloc_drm_handle_t *dh;
    155 
    156    /* check that the buffer is allocated by drm_gralloc and cast */
    157    dh = gralloc_drm_handle(handle);
    158 
    159    return (dh) ? dh->name : 0;
    160 }
    161 
    162 #else
    163 
    164 static int
    165 get_handle_name(buffer_handle_t handle)
    166 {
    167    return 0;
    168 }
    169 
    170 #endif /* ANDROID_BACKEND_NO_DRM */
    171 
    172 /**
    173  * Import an ANativeWindowBuffer allocated by the server.
    174  */
    175 static struct pipe_resource *
    176 import_buffer(struct android_display *adpy, const struct pipe_resource *templ,
    177               ANativeWindowBuffer *abuf)
    178 {
    179    struct pipe_screen *screen = adpy->base.screen;
    180    struct pipe_resource *res;
    181 
    182    if (templ->bind & PIPE_BIND_RENDER_TARGET) {
    183       if (!screen->is_format_supported(screen, templ->format,
    184                templ->target, 0, PIPE_BIND_RENDER_TARGET))
    185          LOGW("importing unsupported buffer as render target");
    186    }
    187    if (templ->bind & PIPE_BIND_SAMPLER_VIEW) {
    188       if (!screen->is_format_supported(screen, templ->format,
    189                templ->target, 0, PIPE_BIND_SAMPLER_VIEW))
    190          LOGW("importing unsupported buffer as sampler view");
    191    }
    192 
    193    if (adpy->use_drm) {
    194       struct winsys_handle handle;
    195 
    196       memset(&handle, 0, sizeof(handle));
    197       handle.type = DRM_API_HANDLE_TYPE_SHARED;
    198       /* for DRM, we need the GEM name */
    199       handle.handle = get_handle_name(abuf->handle);
    200       if (!handle.handle) {
    201          LOGE("unable to import invalid buffer %p", abuf);
    202          return NULL;
    203       }
    204 
    205       handle.stride =
    206          abuf->stride * util_format_get_blocksize(templ->format);
    207 
    208       res = screen->resource_from_handle(screen, templ, &handle);
    209    }
    210    else {
    211       struct android_winsys_handle handle;
    212 
    213       memset(&handle, 0, sizeof(handle));
    214       handle.handle = abuf->handle;
    215       handle.stride =
    216          abuf->stride * util_format_get_blocksize(templ->format);
    217 
    218       res = screen->resource_from_handle(screen,
    219             templ, (struct winsys_handle *) &handle);
    220    }
    221 
    222    if (!res)
    223       LOGE("failed to import buffer %p", abuf);
    224 
    225    return res;
    226 }
    227 
    228 static void
    229 android_surface_clear_cache(struct native_surface *nsurf)
    230 {
    231    struct android_surface *asurf = android_surface(nsurf);
    232    int i;
    233 
    234    for (i = 0; i < Elements(asurf->cache_handles); i++) {
    235       asurf->cache_handles[i] = NULL;
    236       pipe_resource_reference(&asurf->cache_resources[i], NULL);
    237    }
    238 
    239    memset(&asurf->cache_key, 0, sizeof(asurf->cache_key));
    240 }
    241 
    242 static struct pipe_resource *
    243 android_surface_add_cache(struct native_surface *nsurf,
    244                           ANativeWindowBuffer *abuf)
    245 {
    246    struct android_surface *asurf = android_surface(nsurf);
    247    void *handle;
    248    int idx;
    249 
    250    /* how about abuf->usage? */
    251    if (asurf->cache_key.width != abuf->width ||
    252        asurf->cache_key.height != abuf->height ||
    253        asurf->cache_key.format != abuf->format)
    254       android_surface_clear_cache(&asurf->base);
    255 
    256    if (asurf->adpy->use_drm)
    257       handle = (void *) get_handle_name(abuf->handle);
    258    else
    259       handle = (void *) abuf->handle;
    260    /* NULL is invalid */
    261    if (!handle) {
    262       LOGE("invalid buffer native buffer %p", abuf);
    263       return NULL;
    264    }
    265 
    266    /* find the slot to use */
    267    for (idx = 0; idx < Elements(asurf->cache_handles); idx++) {
    268       if (asurf->cache_handles[idx] == handle || !asurf->cache_handles[idx])
    269          break;
    270    }
    271    if (idx == Elements(asurf->cache_handles)) {
    272       LOGW("cache full: buf %p, width %d, height %d, format %d, usage 0x%x",
    273             abuf, abuf->width, abuf->height, abuf->format, abuf->usage);
    274       android_surface_clear_cache(&asurf->base);
    275       idx = 0;
    276    }
    277 
    278    if (idx == 0) {
    279       asurf->cache_key.width = abuf->width;
    280       asurf->cache_key.height = abuf->height;
    281       asurf->cache_key.format = abuf->format;
    282    }
    283 
    284    if (!asurf->cache_handles[idx]) {
    285       struct pipe_resource templ;
    286 
    287       assert(!asurf->cache_resources[idx]);
    288 
    289       memset(&templ, 0, sizeof(templ));
    290       templ.target = PIPE_TEXTURE_2D;
    291       templ.format = get_pipe_format(asurf->buf->format);
    292       templ.bind = PIPE_BIND_RENDER_TARGET;
    293       if (!asurf->adpy->use_drm) {
    294          templ.bind |= PIPE_BIND_TRANSFER_WRITE |
    295                        PIPE_BIND_TRANSFER_READ;
    296       }
    297 
    298       templ.width0 = asurf->buf->width;
    299       templ.height0 = asurf->buf->height;
    300       templ.depth0 = 1;
    301       templ.array_size = 1;
    302 
    303       if (templ.format != PIPE_FORMAT_NONE) {
    304          asurf->cache_resources[idx] =
    305             import_buffer(asurf->adpy, &templ, asurf->buf);
    306       }
    307       else {
    308          asurf->cache_resources[idx] = NULL;
    309       }
    310 
    311       asurf->cache_handles[idx] = handle;
    312    }
    313 
    314    return asurf->cache_resources[idx];
    315 }
    316 
    317 /**
    318  * Dequeue the next back buffer for rendering.
    319  */
    320 static boolean
    321 android_surface_dequeue_buffer(struct native_surface *nsurf)
    322 {
    323    struct android_surface *asurf = android_surface(nsurf);
    324    struct pipe_resource *res;
    325 
    326    if (asurf->win->dequeueBuffer(asurf->win, &asurf->buf) != NO_ERROR) {
    327       LOGE("failed to dequeue window %p", asurf->win);
    328       return FALSE;
    329    }
    330 
    331    asurf->buf->common.incRef(&asurf->buf->common);
    332    asurf->win->lockBuffer(asurf->win, asurf->buf);
    333 
    334    res = android_surface_add_cache(&asurf->base, asurf->buf);
    335    if (!res)
    336       return FALSE;
    337 
    338    pipe_resource_reference(&asurf->buf_res, res);
    339 
    340    return TRUE;
    341 }
    342 
    343 /**
    344  * Enqueue the back buffer.  This will make it the next front buffer.
    345  */
    346 static boolean
    347 android_surface_enqueue_buffer(struct native_surface *nsurf)
    348 {
    349    struct android_surface *asurf = android_surface(nsurf);
    350 
    351    pipe_resource_reference(&asurf->buf_res, NULL);
    352 
    353    asurf->win->queueBuffer(asurf->win, asurf->buf);
    354 
    355    asurf->buf->common.decRef(&asurf->buf->common);
    356    asurf->buf = NULL;
    357 
    358    return TRUE;
    359 }
    360 
    361 static boolean
    362 android_surface_swap_buffers(struct native_surface *nsurf)
    363 {
    364    struct android_surface *asurf = android_surface(nsurf);
    365    struct android_display *adpy = asurf->adpy;
    366 
    367    android_surface_enqueue_buffer(&asurf->base);
    368 
    369    asurf->stamp++;
    370    adpy->event_handler->invalid_surface(&adpy->base,
    371          &asurf->base, asurf->stamp);
    372 
    373    return TRUE;
    374 }
    375 
    376 static void
    377 copy_resources(struct native_display *ndpy,
    378                struct pipe_resource *src,
    379                struct pipe_resource *dst)
    380 {
    381    struct pipe_context *pipe;
    382    struct pipe_box box;
    383 
    384    pipe = ndpy_get_copy_context(ndpy);
    385    if (!pipe)
    386       return;
    387 
    388    u_box_origin_2d(src->width0, src->height0, &box);
    389    pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &box);
    390    pipe->flush(pipe, NULL);
    391 }
    392 
    393 static boolean
    394 android_surface_present(struct native_surface *nsurf,
    395                         const native_present_control *ctrl)
    396 {
    397    struct android_surface *asurf = android_surface(nsurf);
    398    struct android_display *adpy = asurf->adpy;
    399    boolean ret;
    400 
    401    if (ctrl->swap_interval || ctrl->natt != NATIVE_ATTACHMENT_BACK_LEFT)
    402       return FALSE;
    403 
    404    /* this happens when eglSwapBuffers is called more than once in a row */
    405    if (!asurf->buf)
    406       return TRUE;
    407 
    408    /* we always render to color_res first when it exists */
    409    if (asurf->color_res) {
    410       copy_resources(&adpy->base, asurf->color_res, asurf->buf_res);
    411       if (!ctrl->preserve)
    412          pipe_resource_reference(&asurf->color_res, NULL);
    413    }
    414    else if (ctrl->preserve) {
    415       struct pipe_resource templ;
    416 
    417       memset(&templ, 0, sizeof(templ));
    418       templ.target = asurf->buf_res->target;
    419       templ.format = asurf->buf_res->format;
    420       templ.bind = PIPE_BIND_RENDER_TARGET;
    421       templ.width0 = asurf->buf_res->width0;
    422       templ.height0 = asurf->buf_res->height0;
    423       templ.depth0 = asurf->buf_res->depth0;
    424       templ.array_size = asurf->buf_res->array_size;
    425 
    426       asurf->color_res =
    427          adpy->base.screen->resource_create(adpy->base.screen, &templ);
    428       if (!asurf->color_res)
    429          return FALSE;
    430 
    431       /* preserve the contents */
    432       copy_resources(&adpy->base, asurf->buf_res, asurf->color_res);
    433    }
    434 
    435    return android_surface_swap_buffers(nsurf);
    436 }
    437 
    438 static boolean
    439 android_surface_validate(struct native_surface *nsurf, uint attachment_mask,
    440                          unsigned int *seq_num, struct pipe_resource **textures,
    441                          int *width, int *height)
    442 {
    443    struct android_surface *asurf = android_surface(nsurf);
    444    struct winsys_handle handle;
    445 
    446    if (!asurf->buf) {
    447       if (!android_surface_dequeue_buffer(&asurf->base))
    448          return FALSE;
    449 
    450       /* color_res must be compatible with buf_res */
    451       if (asurf->color_res &&
    452           (asurf->color_res->format != asurf->buf_res->format ||
    453            asurf->color_res->width0 != asurf->buf_res->width0 ||
    454            asurf->color_res->height0 != asurf->buf_res->height0))
    455          pipe_resource_reference(&asurf->color_res, NULL);
    456    }
    457 
    458    if (textures) {
    459       /* we have access to only the back buffer */
    460       const enum native_attachment att = NATIVE_ATTACHMENT_BACK_LEFT;
    461 
    462       if (native_attachment_mask_test(attachment_mask, att)) {
    463          textures[att] = NULL;
    464          pipe_resource_reference(&textures[att],
    465                (asurf->color_res) ? asurf->color_res : asurf->buf_res);
    466       }
    467    }
    468 
    469    if (seq_num)
    470       *seq_num = asurf->stamp;
    471    if (width)
    472       *width = asurf->buf->width;
    473    if (height)
    474       *height = asurf->buf->height;
    475 
    476    return TRUE;
    477 }
    478 
    479 static void
    480 android_surface_wait(struct native_surface *nsurf)
    481 {
    482 }
    483 
    484 static void
    485 android_surface_destroy(struct native_surface *nsurf)
    486 {
    487    struct android_surface *asurf = android_surface(nsurf);
    488    int i;
    489 
    490    pipe_resource_reference(&asurf->color_res, NULL);
    491 
    492    if (asurf->buf)
    493       android_surface_enqueue_buffer(&asurf->base);
    494 
    495    android_surface_clear_cache(&asurf->base);
    496 
    497    asurf->win->common.decRef(&asurf->win->common);
    498 
    499    FREE(asurf);
    500 }
    501 
    502 static struct native_surface *
    503 android_display_create_window_surface(struct native_display *ndpy,
    504                                       EGLNativeWindowType win,
    505                                       const struct native_config *nconf)
    506 {
    507    struct android_display *adpy = android_display(ndpy);
    508    struct android_config *aconf = android_config(nconf);
    509    struct android_surface *asurf;
    510    enum pipe_format format;
    511    int val;
    512 
    513    if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
    514       LOGE("invalid native window with magic 0x%x", win->common.magic);
    515       return NULL;
    516    }
    517    if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) {
    518       LOGE("failed to query native window format");
    519       return NULL;
    520    }
    521    format = get_pipe_format(val);
    522    if (format != nconf->color_format) {
    523       LOGW("native window format 0x%x != config format 0x%x",
    524             format, nconf->color_format);
    525       if (!adpy->base.screen->is_format_supported(adpy->base.screen,
    526                format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) {
    527          LOGE("and the native window cannot be used as a render target");
    528          return NULL;
    529       }
    530    }
    531 
    532    asurf = CALLOC_STRUCT(android_surface);
    533    if (!asurf)
    534       return NULL;
    535 
    536    asurf->adpy = adpy;
    537    asurf->win = win;
    538    asurf->win->common.incRef(&asurf->win->common);
    539 
    540    /* request buffers that are for CPU access */
    541    if (!adpy->use_drm) {
    542       native_window_set_usage(asurf->win,
    543             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
    544    }
    545 
    546    asurf->base.destroy = android_surface_destroy;
    547    asurf->base.present = android_surface_present;
    548    asurf->base.validate = android_surface_validate;
    549    asurf->base.wait = android_surface_wait;
    550 
    551    return &asurf->base;
    552 }
    553 
    554 static boolean
    555 android_display_init_configs(struct native_display *ndpy)
    556 {
    557    struct android_display *adpy = android_display(ndpy);
    558    const int native_formats[] = {
    559       HAL_PIXEL_FORMAT_RGBA_8888,
    560       HAL_PIXEL_FORMAT_RGBX_8888,
    561       HAL_PIXEL_FORMAT_RGB_888,
    562       HAL_PIXEL_FORMAT_RGB_565,
    563       HAL_PIXEL_FORMAT_BGRA_8888,
    564    };
    565    int i;
    566 
    567    adpy->configs = (struct android_config *)
    568       CALLOC(Elements(native_formats), sizeof(*adpy->configs));
    569    if (!adpy->configs)
    570       return FALSE;
    571 
    572    for (i = 0; i < Elements(native_formats); i++) {
    573       enum pipe_format color_format;
    574       struct android_config *aconf;
    575 
    576       color_format = get_pipe_format(native_formats[i]);
    577       if (color_format == PIPE_FORMAT_NONE ||
    578           !adpy->base.screen->is_format_supported(adpy->base.screen,
    579                color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) {
    580          LOGI("skip unsupported native format 0x%x", native_formats[i]);
    581          continue;
    582       }
    583 
    584       aconf = &adpy->configs[adpy->num_configs++];
    585       /* only the back buffer */
    586       aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT;
    587       aconf->base.color_format = color_format;
    588       aconf->base.window_bit = TRUE;
    589 
    590       aconf->base.native_visual_id = native_formats[i];
    591       aconf->base.native_visual_type = native_formats[i];
    592    }
    593 
    594    return TRUE;
    595 }
    596 
    597 static boolean
    598 android_display_init_drm(struct native_display *ndpy)
    599 {
    600    struct android_display *adpy = android_display(ndpy);
    601    const hw_module_t *mod;
    602    int fd, err;
    603 
    604 #ifndef ANDROID_BACKEND_NO_DRM
    605    /* get the authorized fd from gralloc */
    606    err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
    607    if (!err) {
    608       const gralloc_module_t *gr = (gralloc_module_t *) mod;
    609 
    610       err = -EINVAL;
    611       if (gr->perform)
    612          err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
    613    }
    614    if (!err && fd >= 0) {
    615       adpy->base.screen =
    616          adpy->event_handler->new_drm_screen(&adpy->base, NULL, fd);
    617    }
    618 #endif
    619 
    620    if (adpy->base.screen) {
    621       LOGI("using DRM screen");
    622       return TRUE;
    623    }
    624    else {
    625       LOGW("failed to create DRM screen");
    626       LOGW("will fall back to other EGL drivers if any");
    627       return FALSE;
    628    }
    629 }
    630 
    631 static boolean
    632 android_display_init_sw(struct native_display *ndpy)
    633 {
    634    struct android_display *adpy = android_display(ndpy);
    635    struct sw_winsys *ws;
    636 
    637    ws = android_create_sw_winsys();
    638    if (ws) {
    639       adpy->base.screen =
    640          adpy->event_handler->new_sw_screen(&adpy->base, ws);
    641    }
    642 
    643    if (adpy->base.screen) {
    644       LOGI("using SW screen");
    645       return TRUE;
    646    }
    647    else {
    648       LOGE("failed to create SW screen");
    649       return FALSE;
    650    }
    651 }
    652 
    653 static boolean
    654 android_display_init_screen(struct native_display *ndpy)
    655 {
    656    struct android_display *adpy = android_display(ndpy);
    657 
    658    if (adpy->use_drm)
    659       android_display_init_drm(&adpy->base);
    660    else
    661       android_display_init_sw(&adpy->base);
    662 
    663    if (!adpy->base.screen)
    664       return FALSE;
    665 
    666    if (!android_display_init_configs(&adpy->base)) {
    667       adpy->base.screen->destroy(adpy->base.screen);
    668       adpy->base.screen = NULL;
    669       return FALSE;
    670    }
    671 
    672    return TRUE;
    673 }
    674 
    675 static void
    676 android_display_destroy(struct native_display *ndpy)
    677 {
    678    struct android_display *adpy = android_display(ndpy);
    679 
    680    FREE(adpy->configs);
    681    if (adpy->base.screen)
    682       adpy->base.screen->destroy(adpy->base.screen);
    683    FREE(adpy);
    684 }
    685 
    686 static const struct native_config **
    687 android_display_get_configs(struct native_display *ndpy, int *num_configs)
    688 {
    689    struct android_display *adpy = android_display(ndpy);
    690    const struct native_config **configs;
    691    int i;
    692 
    693    configs = (const struct native_config **)
    694       MALLOC(adpy->num_configs * sizeof(*configs));
    695    if (configs) {
    696       for (i = 0; i < adpy->num_configs; i++)
    697          configs[i] = (const struct native_config *) &adpy->configs[i];
    698       if (num_configs)
    699          *num_configs = adpy->num_configs;
    700    }
    701 
    702    return configs;
    703 }
    704 
    705 static int
    706 android_display_get_param(struct native_display *ndpy,
    707                           enum native_param_type param)
    708 {
    709    int val;
    710 
    711    switch (param) {
    712    case NATIVE_PARAM_PRESERVE_BUFFER:
    713       val = 1;
    714       break;
    715    default:
    716       val = 0;
    717       break;
    718    }
    719 
    720    return val;
    721 }
    722 
    723 static struct pipe_resource *
    724 android_display_import_buffer(struct native_display *ndpy,
    725                               struct native_buffer *nbuf)
    726 {
    727    struct android_display *adpy = android_display(ndpy);
    728    ANativeWindowBuffer *abuf;
    729    enum pipe_format format;
    730    struct pipe_resource templ;
    731 
    732    if (nbuf->type != NATIVE_BUFFER_ANDROID)
    733       return NULL;
    734 
    735    abuf = nbuf->u.android;
    736 
    737    if (!abuf || abuf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
    738        abuf->common.version != sizeof(*abuf)) {
    739       LOGE("invalid android native buffer");
    740       return NULL;
    741    }
    742 
    743    format = get_pipe_format(abuf->format);
    744    if (format == PIPE_FORMAT_NONE)
    745       return NULL;
    746 
    747    memset(&templ, 0, sizeof(templ));
    748    templ.target = PIPE_TEXTURE_2D;
    749    templ.format = format;
    750    /* assume for texturing only */
    751    templ.bind = PIPE_BIND_SAMPLER_VIEW;
    752    templ.width0 = abuf->width;
    753    templ.height0 = abuf->height;
    754    templ.depth0 = 1;
    755    templ.array_size = 1;
    756 
    757    return import_buffer(adpy, &templ, abuf);
    758 }
    759 
    760 static boolean
    761 android_display_export_buffer(struct native_display *ndpy,
    762                               struct pipe_resource *res,
    763                               struct native_buffer *nbuf)
    764 {
    765    return FALSE;
    766 }
    767 
    768 static struct native_display_buffer android_display_buffer = {
    769    android_display_import_buffer,
    770    android_display_export_buffer
    771 };
    772 
    773 static struct android_display *
    774 android_display_create(const struct native_event_handler *event_handler,
    775                        boolean use_sw)
    776 {
    777    struct android_display *adpy;
    778    char value[PROPERTY_VALUE_MAX];
    779    boolean force_sw;
    780 
    781    /* check if SW renderer is forced */
    782    if (property_get("debug.mesa.software", value, NULL))
    783       force_sw = (atoi(value) != 0);
    784    else
    785       force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
    786    if (force_sw)
    787       use_sw = TRUE;
    788 
    789    adpy = CALLOC_STRUCT(android_display);
    790    if (!adpy)
    791       return NULL;
    792 
    793    adpy->event_handler = event_handler;
    794    adpy->use_drm = !use_sw;
    795 
    796    adpy->base.init_screen = android_display_init_screen;
    797    adpy->base.destroy = android_display_destroy;
    798    adpy->base.get_param = android_display_get_param;
    799    adpy->base.get_configs = android_display_get_configs;
    800    adpy->base.create_window_surface = android_display_create_window_surface;
    801 
    802    adpy->base.buffer = &android_display_buffer;
    803 
    804    return adpy;
    805 }
    806 
    807 static const struct native_event_handler *android_event_handler;
    808 
    809 static struct native_display *
    810 native_create_display(void *dpy, boolean use_sw)
    811 {
    812    struct android_display *adpy;
    813 
    814    adpy = android_display_create(android_event_handler, use_sw);
    815 
    816    return (adpy) ? &adpy->base : NULL;
    817 }
    818 
    819 static const struct native_platform android_platform = {
    820    "Android", /* name */
    821    native_create_display
    822 };
    823 
    824 }; /* namespace android */
    825 
    826 using namespace android;
    827 
    828 static void
    829 android_log(EGLint level, const char *msg)
    830 {
    831    switch (level) {
    832    case _EGL_DEBUG:
    833       LOGD("%s", msg);
    834       break;
    835    case _EGL_INFO:
    836       LOGI("%s", msg);
    837       break;
    838    case _EGL_WARNING:
    839       LOGW("%s", msg);
    840       break;
    841    case _EGL_FATAL:
    842       LOG_FATAL("%s", msg);
    843       break;
    844    default:
    845       break;
    846    }
    847 }
    848 
    849 const struct native_platform *
    850 native_get_android_platform(const struct native_event_handler *event_handler)
    851 {
    852    android_event_handler = event_handler;
    853    /* use Android logger */
    854    _eglSetLogProc(android_log);
    855 
    856    return &android_platform;
    857 }
    858