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