st/egl: add buffer preserving support to Android
[mesa.git] / src / gallium / state_trackers / egl / android / native_android.cpp
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
33 extern "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
46 struct android_config;
47
48 struct 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
57 struct 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
80 struct android_config {
81 struct native_config base;
82 };
83
84 static INLINE struct android_display *
85 android_display(const struct native_display *ndpy)
86 {
87 return (struct android_display *) ndpy;
88 }
89
90 static INLINE struct android_surface *
91 android_surface(const struct native_surface *nsurf)
92 {
93 return (struct android_surface *) nsurf;
94 }
95
96 static INLINE struct android_config *
97 android_config(const struct native_config *nconf)
98 {
99 return (struct android_config *) nconf;
100 }
101
102 namespace android {
103
104 static enum pipe_format
105 get_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>
139 static int
140 get_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 */
153 static struct pipe_resource *
154 import_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
206 static void
207 android_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
220 static struct pipe_resource *
221 android_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 */
298 static boolean
299 android_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 */
324 static boolean
325 android_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
339 static boolean
340 android_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
357 static void
358 copy_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
374 static boolean
375 android_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
417 static boolean
418 android_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
458 static void
459 android_surface_wait(struct native_surface *nsurf)
460 {
461 }
462
463 static void
464 android_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
481 static struct native_surface *
482 android_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
533 static boolean
534 android_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
576 static boolean
577 android_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
607 static boolean
608 android_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
629 static boolean
630 android_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
651 static void
652 android_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
662 static const struct native_config **
663 android_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
681 static int
682 android_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
699 static struct pipe_resource *
700 android_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
736 static boolean
737 android_display_export_buffer(struct native_display *ndpy,
738 struct pipe_resource *res,
739 struct native_buffer *nbuf)
740 {
741 return FALSE;
742 }
743
744 static struct native_display_buffer android_display_buffer = {
745 android_display_import_buffer,
746 android_display_export_buffer
747 };
748
749 static struct android_display *
750 android_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
783 static const struct native_event_handler *android_event_handler;
784
785 static struct native_display *
786 native_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
795 static const struct native_platform android_platform = {
796 "Android", /* name */
797 native_create_display
798 };
799
800 }; /* namespace android */
801
802 using namespace android;
803
804 static void
805 android_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
825 const struct native_platform *
826 native_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 }