wayland/shm: rework format handling

Use a linked list for all supported formats and make the format table const.
This commit is contained in:
Alexander Preisinger 2013-08-26 18:36:16 +02:00
parent 56644b8abc
commit 65321f081d
1 changed files with 76 additions and 47 deletions

View File

@ -49,43 +49,42 @@ static const struct wl_shm_listener shm_listener;
struct fmtentry {
enum wl_shm_format wl_fmt;
enum mp_imgfmt mp_fmt;
bool hw_support;
};
// the first 2 Formats should be available on most platforms
// all other formats are optional
// the waylad byte order is reversed
static struct fmtentry fmttable[] = {
{WL_SHM_FORMAT_ARGB8888, IMGFMT_BGRA, false}, // 8b 8g 8r 8a
{WL_SHM_FORMAT_XRGB8888, IMGFMT_BGR0, false},
{WL_SHM_FORMAT_RGB332, IMGFMT_BGR8, false}, // 3b 3g 2r
{WL_SHM_FORMAT_BGR233, IMGFMT_RGB8, false}, // 3r 3g 3b,
{WL_SHM_FORMAT_XRGB4444, IMGFMT_BGR12_LE, false}, // 4b 4g 4r 4a
{WL_SHM_FORMAT_XBGR4444, IMGFMT_RGB12_LE, false}, // 4r 4g 4b 4a
{WL_SHM_FORMAT_RGBX4444, IMGFMT_RGB12_BE, false}, // 4a 4b 4g 4r
{WL_SHM_FORMAT_BGRX4444, IMGFMT_BGR12_BE, false}, // 4a 4r 4g 4b
{WL_SHM_FORMAT_ARGB4444, IMGFMT_BGR12_LE, false},
{WL_SHM_FORMAT_ABGR4444, IMGFMT_RGB12_LE, false},
{WL_SHM_FORMAT_RGBA4444, IMGFMT_RGB12_BE, false},
{WL_SHM_FORMAT_BGRA4444, IMGFMT_BGR12_BE, false},
{WL_SHM_FORMAT_XRGB1555, IMGFMT_BGR15_LE, false}, // 5b 5g 5r 1a
{WL_SHM_FORMAT_XBGR1555, IMGFMT_RGB15_LE, false}, // 5r 5g 5b 1a
{WL_SHM_FORMAT_RGBX5551, IMGFMT_RGB15_BE, false}, // 1a 5g 5b 5r
{WL_SHM_FORMAT_BGRX5551, IMGFMT_BGR15_BE, false}, // 1a 5r 5g 5b
{WL_SHM_FORMAT_ARGB1555, IMGFMT_BGR15_LE, false},
{WL_SHM_FORMAT_ABGR1555, IMGFMT_RGB15_LE, false},
{WL_SHM_FORMAT_RGBA5551, IMGFMT_RGB15_BE, false},
{WL_SHM_FORMAT_BGRA5551, IMGFMT_BGR15_BE, false},
{WL_SHM_FORMAT_RGB565, IMGFMT_BGR16_LE, false}, // 5b 6g 5r
{WL_SHM_FORMAT_BGR565, IMGFMT_RGB16_LE, false}, // 5r 6g 5b
{WL_SHM_FORMAT_RGB888, IMGFMT_BGR24, false}, // 8b 8g 8r
{WL_SHM_FORMAT_BGR888, IMGFMT_RGB24, false}, // 8r 8g 8b
{WL_SHM_FORMAT_XBGR8888, IMGFMT_RGB0, false},
{WL_SHM_FORMAT_RGBX8888, IMGFMT_0BGR, false},
{WL_SHM_FORMAT_BGRX8888, IMGFMT_0RGB, false},
{WL_SHM_FORMAT_ABGR8888, IMGFMT_RGBA, false},
{WL_SHM_FORMAT_RGBA8888, IMGFMT_ABGR, false},
{WL_SHM_FORMAT_BGRA8888, IMGFMT_ARGB, false},
static const struct fmtentry fmttable[] = {
{WL_SHM_FORMAT_ARGB8888, IMGFMT_BGRA}, // 8b 8g 8r 8a
{WL_SHM_FORMAT_XRGB8888, IMGFMT_BGR0},
{WL_SHM_FORMAT_RGB332, IMGFMT_BGR8}, // 3b 3g 2r
{WL_SHM_FORMAT_BGR233, IMGFMT_RGB8}, // 3r 3g 3b,
{WL_SHM_FORMAT_XRGB4444, IMGFMT_BGR12_LE}, // 4b 4g 4r 4a
{WL_SHM_FORMAT_XBGR4444, IMGFMT_RGB12_LE}, // 4r 4g 4b 4a
{WL_SHM_FORMAT_RGBX4444, IMGFMT_RGB12_BE}, // 4a 4b 4g 4r
{WL_SHM_FORMAT_BGRX4444, IMGFMT_BGR12_BE}, // 4a 4r 4g 4b
{WL_SHM_FORMAT_ARGB4444, IMGFMT_BGR12_LE},
{WL_SHM_FORMAT_ABGR4444, IMGFMT_RGB12_LE},
{WL_SHM_FORMAT_RGBA4444, IMGFMT_RGB12_BE},
{WL_SHM_FORMAT_BGRA4444, IMGFMT_BGR12_BE},
{WL_SHM_FORMAT_XRGB1555, IMGFMT_BGR15_LE}, // 5b 5g 5r 1a
{WL_SHM_FORMAT_XBGR1555, IMGFMT_RGB15_LE}, // 5r 5g 5b 1a
{WL_SHM_FORMAT_RGBX5551, IMGFMT_RGB15_BE}, // 1a 5g 5b 5r
{WL_SHM_FORMAT_BGRX5551, IMGFMT_BGR15_BE}, // 1a 5r 5g 5b
{WL_SHM_FORMAT_ARGB1555, IMGFMT_BGR15_LE},
{WL_SHM_FORMAT_ABGR1555, IMGFMT_RGB15_LE},
{WL_SHM_FORMAT_RGBA5551, IMGFMT_RGB15_BE},
{WL_SHM_FORMAT_BGRA5551, IMGFMT_BGR15_BE},
{WL_SHM_FORMAT_RGB565, IMGFMT_BGR16_LE}, // 5b 6g 5r
{WL_SHM_FORMAT_BGR565, IMGFMT_RGB16_LE}, // 5r 6g 5b
{WL_SHM_FORMAT_RGB888, IMGFMT_BGR24}, // 8b 8g 8r
{WL_SHM_FORMAT_BGR888, IMGFMT_RGB24}, // 8r 8g 8b
{WL_SHM_FORMAT_XBGR8888, IMGFMT_RGB0},
{WL_SHM_FORMAT_RGBX8888, IMGFMT_0BGR},
{WL_SHM_FORMAT_BGRX8888, IMGFMT_0RGB},
{WL_SHM_FORMAT_ABGR8888, IMGFMT_RGBA},
{WL_SHM_FORMAT_RGBA8888, IMGFMT_ABGR},
{WL_SHM_FORMAT_BGRA8888, IMGFMT_ARGB},
};
#define MAX_FORMAT_ENTRIES (sizeof(fmttable) / sizeof(fmttable[0]))
@ -100,11 +99,18 @@ struct buffer {
size_t shm_size;
};
struct supported_format {
const struct fmtentry *fmt;
bool is_alpha;
struct wl_list link;
};
struct priv {
struct vo *vo;
struct vo_wayland_state *wl;
struct fmtentry *pref_format;
struct wl_list format_list;
const struct fmtentry *pref_format;
int bytes_per_pixel;
int stride;
@ -207,6 +213,11 @@ static int os_create_anonymous_file(off_t size)
return fd;
}
static bool is_alpha_format(const struct fmtentry *fmt)
{
return !!(mp_imgfmt_get_desc(fmt->mp_fmt).flags & MP_IMGFLAG_ALPHA);
}
static void buffer_swap(struct priv *p)
{
if (!p->back_buffer->is_new)
@ -459,7 +470,10 @@ static void shm_handle_format(void *data,
if (fmttable[i].wl_fmt == format) {
MP_INFO(p->vo, "format %s supported by hw\n",
mp_imgfmt_to_name(fmttable[i].mp_fmt));
fmttable[i].hw_support = true;
struct supported_format *sf = talloc(p, struct supported_format);
sf->fmt = &fmttable[i];
sf->is_alpha = is_alpha_format(sf->fmt);
wl_list_insert(&p->format_list, &sf->link);
}
}
}
@ -511,8 +525,10 @@ static void flip_page(struct vo *vo)
static int query_format(struct vo *vo, uint32_t format)
{
for (int i = 0; i < MAX_FORMAT_ENTRIES; ++i) {
if (fmttable[i].mp_fmt == format && fmttable[i].hw_support)
struct priv *p = vo->priv;
struct supported_format *sf;
wl_list_for_each_reverse(sf, &p->format_list, link) {
if (sf->fmt->mp_fmt == format)
return VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_CSP_SUPPORTED;
}
@ -531,24 +547,35 @@ static int reconfig(struct vo *vo, struct mp_image_params *fmt, int flags)
p->height = vo->dheight;
p->in_format = *fmt;
struct supported_format *sf;
// find the same format first
for (int i = 0; !p->pref_format && i < MAX_FORMAT_ENTRIES; ++i) {
if (fmttable[i].mp_fmt == fmt->imgfmt && fmttable[i].hw_support)
p->pref_format = &fmttable[i];
wl_list_for_each(sf, &p->format_list, link) {
if (sf->fmt->mp_fmt == fmt->imgfmt && (p->enable_alpha == sf->is_alpha)) {
p->pref_format = sf->fmt;
break;
}
}
// if the format is not supported choose one of the fancy formats next
// the default formats are always first so begin with the last
for (int i = MAX_FORMAT_ENTRIES-1; !p->pref_format && i >= 0; --i) {
if (fmttable[i].hw_support)
p->pref_format = &fmttable[i];
// the default formats are always last
if (!p->pref_format) {
wl_list_for_each(sf, &p->format_list, link) {
if (p->enable_alpha == sf->is_alpha) {
p->pref_format = sf->fmt;
break;
}
}
}
if (p->use_default)
p->pref_format = &fmttable[DEFAULT_FORMAT_ENTRY];
// if use default is enable overwrite the auto selected one
if (p->use_default) {
if (p->enable_alpha)
p->pref_format = &fmttable[DEFAULT_ALPHA_FORMAT_ENTRY];
else
p->pref_format = &fmttable[DEFAULT_FORMAT_ENTRY];
}
if (p->enable_alpha)
p->pref_format = &fmttable[DEFAULT_ALPHA_FORMAT_ENTRY];
p->bytes_per_pixel = mp_imgfmt_get_desc(p->pref_format->mp_fmt).bytes[0];
MP_VERBOSE(vo, "bytes per pixel: %d\n", p->bytes_per_pixel);
@ -590,6 +617,8 @@ static int preinit(struct vo *vo)
p->front_buffer = &p->buffers[1];
p->back_buffer = &p->buffers[0];
wl_list_init(&p->format_list);
wl_shm_add_listener(p->wl->display.shm, &shm_listener, p);
wl_display_dispatch(p->wl->display.display);
return 0;