2 * Mesa 3-D graphics library
5 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
6 * Copyright (C) 2010-2011 LunarG Inc.
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
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>
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"
46 struct android_config
;
48 struct android_display
{
49 struct native_display base
;
52 const struct native_event_handler
*event_handler
;
53 struct android_config
*configs
;
57 struct android_surface
{
58 struct native_surface base
;
60 struct android_display
*adpy
;
61 android_native_window_t
*win
;
63 /* staging color buffer for when buffer preserving is enabled */
64 struct pipe_resource
*color_res
;
67 android_native_buffer_t
*buf
;
68 struct pipe_resource
*buf_res
;
70 /* cache the current back buffers */
76 void *cache_handles
[2];
77 struct pipe_resource
*cache_resources
[2];
80 struct android_config
{
81 struct native_config base
;
84 static INLINE
struct android_display
*
85 android_display(const struct native_display
*ndpy
)
87 return (struct android_display
*) ndpy
;
90 static INLINE
struct android_surface
*
91 android_surface(const struct native_surface
*nsurf
)
93 return (struct android_surface
*) nsurf
;
96 static INLINE
struct android_config
*
97 android_config(const struct native_config
*nconf
)
99 return (struct android_config
*) nconf
;
104 static enum pipe_format
105 get_pipe_format(int native
)
107 enum pipe_format fmt
;
110 case HAL_PIXEL_FORMAT_RGBA_8888
:
111 fmt
= PIPE_FORMAT_R8G8B8A8_UNORM
;
113 case HAL_PIXEL_FORMAT_RGBX_8888
:
114 fmt
= PIPE_FORMAT_R8G8B8X8_UNORM
;
116 case HAL_PIXEL_FORMAT_RGB_888
:
117 fmt
= PIPE_FORMAT_R8G8B8_UNORM
;
119 case HAL_PIXEL_FORMAT_RGB_565
:
120 fmt
= PIPE_FORMAT_B5G6R5_UNORM
;
122 case HAL_PIXEL_FORMAT_BGRA_8888
:
123 fmt
= PIPE_FORMAT_B8G8R8A8_UNORM
;
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; */
130 LOGE("unsupported native format 0x%x", native
);
131 fmt
= PIPE_FORMAT_NONE
;
138 #include <gralloc_drm_handle.h>
140 get_handle_name(buffer_handle_t handle
)
142 struct gralloc_drm_handle_t
*dh
;
144 /* check that the buffer is allocated by drm_gralloc and cast */
145 dh
= gralloc_drm_handle(handle
);
147 return (dh
) ? dh
->name
: 0;
151 * Import an android_native_buffer_t allocated by the server.
153 static struct pipe_resource
*
154 import_buffer(struct android_display
*adpy
, const struct pipe_resource
*templ
,
155 struct android_native_buffer_t
*abuf
)
157 struct pipe_screen
*screen
= adpy
->base
.screen
;
158 struct pipe_resource
*res
;
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");
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");
172 struct winsys_handle handle
;
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
);
184 abuf
->stride
* util_format_get_blocksize(templ
->format
);
186 res
= screen
->resource_from_handle(screen
, templ
, &handle
);
189 struct android_winsys_handle handle
;
191 memset(&handle
, 0, sizeof(handle
));
192 handle
.handle
= abuf
->handle
;
194 abuf
->stride
* util_format_get_blocksize(templ
->format
);
196 res
= screen
->resource_from_handle(screen
,
197 templ
, (struct winsys_handle
*) &handle
);
201 LOGE("failed to import buffer %p", abuf
);
207 android_surface_clear_cache(struct native_surface
*nsurf
)
209 struct android_surface
*asurf
= android_surface(nsurf
);
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
);
217 memset(&asurf
->cache_key
, 0, sizeof(asurf
->cache_key
));
220 static struct pipe_resource
*
221 android_surface_add_cache(struct native_surface
*nsurf
,
222 struct android_native_buffer_t
*abuf
)
224 struct android_surface
*asurf
= android_surface(nsurf
);
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
);
234 if (asurf
->adpy
->use_drm
)
235 handle
= (void *) get_handle_name(abuf
->handle
);
237 handle
= (void *) abuf
->handle
;
238 /* NULL is invalid */
240 LOGE("invalid buffer native buffer %p", abuf
);
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
])
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
);
257 asurf
->cache_key
.width
= abuf
->width
;
258 asurf
->cache_key
.height
= abuf
->height
;
259 asurf
->cache_key
.format
= abuf
->format
;
262 if (!asurf
->cache_handles
[idx
]) {
263 struct pipe_resource templ
;
265 assert(!asurf
->cache_resources
[idx
]);
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
;
276 templ
.width0
= asurf
->buf
->width
;
277 templ
.height0
= asurf
->buf
->height
;
279 templ
.array_size
= 1;
281 if (templ
.format
!= PIPE_FORMAT_NONE
) {
282 asurf
->cache_resources
[idx
] =
283 import_buffer(asurf
->adpy
, &templ
, asurf
->buf
);
286 asurf
->cache_resources
[idx
] = NULL
;
289 asurf
->cache_handles
[idx
] = handle
;
292 return asurf
->cache_resources
[idx
];
296 * Dequeue the next back buffer for rendering.
299 android_surface_dequeue_buffer(struct native_surface
*nsurf
)
301 struct android_surface
*asurf
= android_surface(nsurf
);
302 struct pipe_resource
*res
;
304 if (asurf
->win
->dequeueBuffer(asurf
->win
, &asurf
->buf
) != NO_ERROR
) {
305 LOGE("failed to dequeue window %p", asurf
->win
);
309 asurf
->buf
->common
.incRef(&asurf
->buf
->common
);
310 asurf
->win
->lockBuffer(asurf
->win
, asurf
->buf
);
312 res
= android_surface_add_cache(&asurf
->base
, asurf
->buf
);
316 pipe_resource_reference(&asurf
->buf_res
, res
);
322 * Enqueue the back buffer. This will make it the next front buffer.
325 android_surface_enqueue_buffer(struct native_surface
*nsurf
)
327 struct android_surface
*asurf
= android_surface(nsurf
);
329 pipe_resource_reference(&asurf
->buf_res
, NULL
);
331 asurf
->win
->queueBuffer(asurf
->win
, asurf
->buf
);
333 asurf
->buf
->common
.decRef(&asurf
->buf
->common
);
340 android_surface_swap_buffers(struct native_surface
*nsurf
)
342 struct android_surface
*asurf
= android_surface(nsurf
);
343 struct android_display
*adpy
= asurf
->adpy
;
348 android_surface_enqueue_buffer(&asurf
->base
);
351 adpy
->event_handler
->invalid_surface(&adpy
->base
,
352 &asurf
->base
, asurf
->stamp
);
358 copy_resources(struct native_display
*ndpy
,
359 struct pipe_resource
*src
,
360 struct pipe_resource
*dst
)
362 struct pipe_context
*pipe
;
365 pipe
= ndpy_get_copy_context(ndpy
);
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
);
375 android_surface_present(struct native_surface
*nsurf
,
376 enum native_attachment natt
,
380 struct android_surface
*asurf
= android_surface(nsurf
);
381 struct android_display
*adpy
= asurf
->adpy
;
384 if (swap_interval
|| natt
!= NATIVE_ATTACHMENT_BACK_LEFT
)
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
);
391 pipe_resource_reference(&asurf
->color_res
, NULL
);
394 struct pipe_resource templ
;
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
;
406 adpy
->base
.screen
->resource_create(adpy
->base
.screen
, &templ
);
407 if (!asurf
->color_res
)
410 /* preserve the contents */
411 copy_resources(&adpy
->base
, asurf
->buf_res
, asurf
->color_res
);
414 return android_surface_swap_buffers(nsurf
);
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
)
422 struct android_surface
*asurf
= android_surface(nsurf
);
423 struct winsys_handle handle
;
426 if (!android_surface_dequeue_buffer(&asurf
->base
))
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
);
438 /* we have access to only the back buffer */
439 const enum native_attachment att
= NATIVE_ATTACHMENT_BACK_LEFT
;
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
);
449 *seq_num
= asurf
->stamp
;
451 *width
= asurf
->buf
->width
;
453 *height
= asurf
->buf
->height
;
459 android_surface_wait(struct native_surface
*nsurf
)
464 android_surface_destroy(struct native_surface
*nsurf
)
466 struct android_surface
*asurf
= android_surface(nsurf
);
469 pipe_resource_reference(&asurf
->color_res
, NULL
);
472 android_surface_enqueue_buffer(&asurf
->base
);
474 android_surface_clear_cache(&asurf
->base
);
476 asurf
->win
->common
.decRef(&asurf
->win
->common
);
481 static struct native_surface
*
482 android_display_create_window_surface(struct native_display
*ndpy
,
483 EGLNativeWindowType win
,
484 const struct native_config
*nconf
)
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
;
492 if (win
->common
.magic
!= ANDROID_NATIVE_WINDOW_MAGIC
) {
493 LOGE("invalid native window with magic 0x%x", win
->common
.magic
);
496 if (win
->query(win
, NATIVE_WINDOW_FORMAT
, &val
)) {
497 LOGE("failed to query native window format");
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");
511 asurf
= CALLOC_STRUCT(android_surface
);
517 asurf
->win
->common
.incRef(&asurf
->win
->common
);
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
);
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
;
534 android_display_init_configs(struct native_display
*ndpy
)
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
,
546 adpy
->configs
= (struct android_config
*)
547 CALLOC(Elements(native_formats
), sizeof(*adpy
->configs
));
551 for (i
= 0; i
< Elements(native_formats
); i
++) {
552 enum pipe_format color_format
;
553 struct android_config
*aconf
;
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
]);
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
;
569 aconf
->base
.native_visual_id
= native_formats
[i
];
570 aconf
->base
.native_visual_type
= native_formats
[i
];
577 android_display_init_drm(struct native_display
*ndpy
)
579 struct android_display
*adpy
= android_display(ndpy
);
580 const hw_module_t
*mod
;
583 /* get the authorized fd from gralloc */
584 err
= hw_get_module(GRALLOC_HARDWARE_MODULE_ID
, &mod
);
586 const gralloc_module_t
*gr
= (gralloc_module_t
*) mod
;
590 err
= gr
->perform(gr
, GRALLOC_MODULE_PERFORM_GET_DRM_FD
, &fd
);
592 if (!err
&& fd
>= 0) {
594 adpy
->event_handler
->new_drm_screen(&adpy
->base
, NULL
, fd
);
597 if (adpy
->base
.screen
) {
598 LOGI("using DRM screen");
602 LOGE("failed to create DRM screen");
608 android_display_init_sw(struct native_display
*ndpy
)
610 struct android_display
*adpy
= android_display(ndpy
);
611 struct sw_winsys
*ws
;
613 ws
= android_create_sw_winsys();
616 adpy
->event_handler
->new_sw_screen(&adpy
->base
, ws
);
619 if (adpy
->base
.screen
) {
620 LOGI("using SW screen");
624 LOGE("failed to create SW screen");
630 android_display_init_screen(struct native_display
*ndpy
)
632 struct android_display
*adpy
= android_display(ndpy
);
635 android_display_init_drm(&adpy
->base
);
637 android_display_init_sw(&adpy
->base
);
639 if (!adpy
->base
.screen
)
642 if (!android_display_init_configs(&adpy
->base
)) {
643 adpy
->base
.screen
->destroy(adpy
->base
.screen
);
644 adpy
->base
.screen
= NULL
;
652 android_display_destroy(struct native_display
*ndpy
)
654 struct android_display
*adpy
= android_display(ndpy
);
657 if (adpy
->base
.screen
)
658 adpy
->base
.screen
->destroy(adpy
->base
.screen
);
662 static const struct native_config
**
663 android_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
665 struct android_display
*adpy
= android_display(ndpy
);
666 const struct native_config
**configs
;
669 configs
= (const struct native_config
**)
670 MALLOC(adpy
->num_configs
* sizeof(*configs
));
672 for (i
= 0; i
< adpy
->num_configs
; i
++)
673 configs
[i
] = (const struct native_config
*) &adpy
->configs
[i
];
675 *num_configs
= adpy
->num_configs
;
682 android_display_get_param(struct native_display
*ndpy
,
683 enum native_param_type param
)
688 case NATIVE_PARAM_PRESERVE_BUFFER
:
699 static struct pipe_resource
*
700 android_display_import_buffer(struct native_display
*ndpy
,
701 struct native_buffer
*nbuf
)
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
;
708 if (nbuf
->type
!= NATIVE_BUFFER_ANDROID
)
711 abuf
= nbuf
->u
.android
;
713 if (!abuf
|| abuf
->common
.magic
!= ANDROID_NATIVE_BUFFER_MAGIC
||
714 abuf
->common
.version
!= sizeof(*abuf
)) {
715 LOGE("invalid android native buffer");
719 format
= get_pipe_format(abuf
->format
);
720 if (format
== PIPE_FORMAT_NONE
)
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
;
731 templ
.array_size
= 1;
733 return import_buffer(adpy
, &templ
, abuf
);
737 android_display_export_buffer(struct native_display
*ndpy
,
738 struct pipe_resource
*res
,
739 struct native_buffer
*nbuf
)
744 static struct native_display_buffer android_display_buffer
= {
745 android_display_import_buffer
,
746 android_display_export_buffer
749 static struct android_display
*
750 android_display_create(const struct native_event_handler
*event_handler
,
753 struct android_display
*adpy
;
754 char value
[PROPERTY_VALUE_MAX
];
757 /* check if SW renderer is forced */
758 if (property_get("debug.mesa.software", value
, NULL
))
759 force_sw
= (atoi(value
) != 0);
761 force_sw
= debug_get_bool_option("EGL_SOFTWARE", FALSE
);
765 adpy
= CALLOC_STRUCT(android_display
);
769 adpy
->event_handler
= event_handler
;
770 adpy
->use_drm
= !use_sw
;
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
;
778 adpy
->base
.buffer
= &android_display_buffer
;
783 static const struct native_event_handler
*android_event_handler
;
785 static struct native_display
*
786 native_create_display(void *dpy
, boolean use_sw
)
788 struct android_display
*adpy
;
790 adpy
= android_display_create(android_event_handler
, use_sw
);
792 return (adpy
) ? &adpy
->base
: NULL
;
795 static const struct native_platform android_platform
= {
796 "Android", /* name */
797 native_create_display
800 }; /* namespace android */
802 using namespace android
;
805 android_log(EGLint level
, const char *msg
)
818 LOG_FATAL("%s", msg
);
825 const struct native_platform
*
826 native_get_android_platform(const struct native_event_handler
*event_handler
)
828 android_event_handler
= event_handler
;
829 /* use Android logger */
830 _eglSetLogProc(android_log
);
832 return &android_platform
;