1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.12
4  *
5  * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@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 *
android_display(const struct native_display * ndpy)95 android_display(const struct native_display *ndpy)
96 {
97    return (struct android_display *) ndpy;
98 }
99 
100 static INLINE struct android_surface *
android_surface(const struct native_surface * nsurf)101 android_surface(const struct native_surface *nsurf)
102 {
103    return (struct android_surface *) nsurf;
104 }
105 
106 static INLINE struct android_config *
android_config(const struct native_config * nconf)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
get_pipe_format(int native)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
get_handle_name(buffer_handle_t handle)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
get_handle_name(buffer_handle_t handle)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 *
import_buffer(struct android_display * adpy,const struct pipe_resource * templ,ANativeWindowBuffer * abuf)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
android_surface_clear_cache(struct native_surface * nsurf)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 *
android_surface_add_cache(struct native_surface * nsurf,ANativeWindowBuffer * abuf)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
android_surface_dequeue_buffer(struct native_surface * nsurf)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
android_surface_enqueue_buffer(struct native_surface * nsurf)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
android_surface_swap_buffers(struct native_surface * nsurf)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
copy_resources(struct native_display * ndpy,struct pipe_resource * src,struct pipe_resource * dst)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
android_surface_present(struct native_surface * nsurf,const native_present_control * ctrl)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
android_surface_validate(struct native_surface * nsurf,uint attachment_mask,unsigned int * seq_num,struct pipe_resource ** textures,int * width,int * height)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
android_surface_wait(struct native_surface * nsurf)480 android_surface_wait(struct native_surface *nsurf)
481 {
482 }
483 
484 static void
android_surface_destroy(struct native_surface * nsurf)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 *
android_display_create_window_surface(struct native_display * ndpy,EGLNativeWindowType win,const struct native_config * nconf)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
android_display_init_configs(struct native_display * ndpy)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
android_display_init_drm(struct native_display * ndpy)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
android_display_init_sw(struct native_display * ndpy)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
android_display_init_screen(struct native_display * ndpy)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
android_display_destroy(struct native_display * ndpy)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 **
android_display_get_configs(struct native_display * ndpy,int * num_configs)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
android_display_get_param(struct native_display * ndpy,enum native_param_type param)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 *
android_display_import_buffer(struct native_display * ndpy,struct native_buffer * nbuf)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
android_display_export_buffer(struct native_display * ndpy,struct pipe_resource * res,struct native_buffer * nbuf)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 *
android_display_create(const struct native_event_handler * event_handler,boolean use_sw)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 *
native_create_display(void * dpy,boolean use_sw)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
android_log(EGLint level,const char * msg)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 *
native_get_android_platform(const struct native_event_handler * event_handler)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