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