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