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
43extern "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
56struct android_config;
57
58struct 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
67struct 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
90struct android_config {
91   struct native_config base;
92};
93
94static INLINE struct android_display *
95android_display(const struct native_display *ndpy)
96{
97   return (struct android_display *) ndpy;
98}
99
100static INLINE struct android_surface *
101android_surface(const struct native_surface *nsurf)
102{
103   return (struct android_surface *) nsurf;
104}
105
106static INLINE struct android_config *
107android_config(const struct native_config *nconf)
108{
109   return (struct android_config *) nconf;
110}
111
112namespace android {
113
114static enum pipe_format
115get_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>
151static int
152get_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
164static int
165get_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 */
175static struct pipe_resource *
176import_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
228static void
229android_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
242static struct pipe_resource *
243android_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 */
320static boolean
321android_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 */
346static boolean
347android_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
361static boolean
362android_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
376static void
377copy_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
393static boolean
394android_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
438static boolean
439android_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
479static void
480android_surface_wait(struct native_surface *nsurf)
481{
482}
483
484static void
485android_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
502static struct native_surface *
503android_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
554static boolean
555android_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
597static boolean
598android_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
631static boolean
632android_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
653static boolean
654android_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
675static void
676android_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
686static const struct native_config **
687android_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
705static int
706android_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
723static struct pipe_resource *
724android_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
760static boolean
761android_display_export_buffer(struct native_display *ndpy,
762                              struct pipe_resource *res,
763                              struct native_buffer *nbuf)
764{
765   return FALSE;
766}
767
768static struct native_display_buffer android_display_buffer = {
769   android_display_import_buffer,
770   android_display_export_buffer
771};
772
773static struct android_display *
774android_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
807static const struct native_event_handler *android_event_handler;
808
809static struct native_display *
810native_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
819static const struct native_platform android_platform = {
820   "Android", /* name */
821   native_create_display
822};
823
824}; /* namespace android */
825
826using namespace android;
827
828static void
829android_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
849const struct native_platform *
850native_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