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
43 extern "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
56 struct android_config;
57
58 struct 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
67 struct 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
90 struct android_config {
91 struct native_config base;
92 };
93
94 static INLINE struct android_display *
android_display(const struct native_display * ndpy)95 android_display(const struct native_display *ndpy)
96 {
97 return (struct android_display *) ndpy;
98 }
99
100 static INLINE struct android_surface *
android_surface(const struct native_surface * nsurf)101 android_surface(const struct native_surface *nsurf)
102 {
103 return (struct android_surface *) nsurf;
104 }
105
106 static INLINE struct android_config *
android_config(const struct native_config * nconf)107 android_config(const struct native_config *nconf)
108 {
109 return (struct android_config *) nconf;
110 }
111
112 namespace android {
113
114 static enum pipe_format
get_pipe_format(int native)115 get_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>
151 static int
get_handle_name(buffer_handle_t handle)152 get_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
164 static int
get_handle_name(buffer_handle_t handle)165 get_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 */
175 static struct pipe_resource *
import_buffer(struct android_display * adpy,const struct pipe_resource * templ,ANativeWindowBuffer * abuf)176 import_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
228 static void
android_surface_clear_cache(struct native_surface * nsurf)229 android_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
242 static struct pipe_resource *
android_surface_add_cache(struct native_surface * nsurf,ANativeWindowBuffer * abuf)243 android_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 */
320 static boolean
android_surface_dequeue_buffer(struct native_surface * nsurf)321 android_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 */
346 static boolean
android_surface_enqueue_buffer(struct native_surface * nsurf)347 android_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
361 static boolean
android_surface_swap_buffers(struct native_surface * nsurf)362 android_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
376 static void
copy_resources(struct native_display * ndpy,struct pipe_resource * src,struct pipe_resource * dst)377 copy_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
393 static boolean
android_surface_present(struct native_surface * nsurf,const native_present_control * ctrl)394 android_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
438 static boolean
android_surface_validate(struct native_surface * nsurf,uint attachment_mask,unsigned int * seq_num,struct pipe_resource ** textures,int * width,int * height)439 android_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
479 static void
android_surface_wait(struct native_surface * nsurf)480 android_surface_wait(struct native_surface *nsurf)
481 {
482 }
483
484 static void
android_surface_destroy(struct native_surface * nsurf)485 android_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
502 static struct native_surface *
android_display_create_window_surface(struct native_display * ndpy,EGLNativeWindowType win,const struct native_config * nconf)503 android_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
554 static boolean
android_display_init_configs(struct native_display * ndpy)555 android_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
597 static boolean
android_display_init_drm(struct native_display * ndpy)598 android_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
631 static boolean
android_display_init_sw(struct native_display * ndpy)632 android_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
653 static boolean
android_display_init_screen(struct native_display * ndpy)654 android_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
675 static void
android_display_destroy(struct native_display * ndpy)676 android_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
686 static const struct native_config **
android_display_get_configs(struct native_display * ndpy,int * num_configs)687 android_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
705 static int
android_display_get_param(struct native_display * ndpy,enum native_param_type param)706 android_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
723 static struct pipe_resource *
android_display_import_buffer(struct native_display * ndpy,struct native_buffer * nbuf)724 android_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
760 static boolean
android_display_export_buffer(struct native_display * ndpy,struct pipe_resource * res,struct native_buffer * nbuf)761 android_display_export_buffer(struct native_display *ndpy,
762 struct pipe_resource *res,
763 struct native_buffer *nbuf)
764 {
765 return FALSE;
766 }
767
768 static struct native_display_buffer android_display_buffer = {
769 android_display_import_buffer,
770 android_display_export_buffer
771 };
772
773 static struct android_display *
android_display_create(const struct native_event_handler * event_handler,boolean use_sw)774 android_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
807 static const struct native_event_handler *android_event_handler;
808
809 static struct native_display *
native_create_display(void * dpy,boolean use_sw)810 native_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
819 static const struct native_platform android_platform = {
820 "Android", /* name */
821 native_create_display
822 };
823
824 }; /* namespace android */
825
826 using namespace android;
827
828 static void
android_log(EGLint level,const char * msg)829 android_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
849 const struct native_platform *
native_get_android_platform(const struct native_event_handler * event_handler)850 native_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