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