X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnouveau%2Fnouveau_vp3_video.c;h=e7a63181de825f6b3c64d66235e0bef23aa8397a;hb=afb8f2d4a346041adf54d45729963a55a625ac1f;hp=ff00b373d63f5b8cc087afa38170154c7baf3729;hpb=e01ba9d6b049d5eee8c125e3ec43b4539c26e4d7;p=mesa.git diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.c b/src/gallium/drivers/nouveau/nouveau_vp3_video.c index ff00b373d63..e7a63181de8 100644 --- a/src/gallium/drivers/nouveau/nouveau_vp3_video.c +++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.c @@ -21,9 +21,12 @@ */ #include +#include #include #include +#include + #include "nouveau_screen.h" #include "nouveau_context.h" #include "nouveau_vp3_video.h" @@ -82,10 +85,10 @@ nouveau_vp3_video_buffer_create(struct pipe_context *pipe, struct pipe_sampler_view sv_templ; struct pipe_surface surf_templ; - assert(templat->interlaced); if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12) return vl_video_buffer_create(pipe, templat); + assert(templat->interlaced); assert(templat->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); buffer = CALLOC_STRUCT(nouveau_vp3_video_buffer); @@ -138,8 +141,8 @@ nouveau_vp3_video_buffer_create(struct pipe_context *pipe, goto error; for (j = 0; j < nr_components; ++j, ++component) { - sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j; - sv_templ.swizzle_a = PIPE_SWIZZLE_ONE; + sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_X + j; + sv_templ.swizzle_a = PIPE_SWIZZLE_1; buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ); if (!buffer->sampler_view_components[component]) @@ -350,6 +353,84 @@ nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, return 0; } +static const struct nouveau_mclass +nouveau_decoder_msvld[] = { + { G98_MSVLD, -1 }, + { IGT21A_MSVLD, -1 }, + { GT212_MSVLD, -1 }, + { GF100_MSVLD, -1 }, + { GK104_MSVLD, -1 }, + {} +}; + +static int +firmware_present(struct pipe_screen *pscreen, enum pipe_video_profile profile) +{ + struct nouveau_screen *screen = nouveau_screen(pscreen); + int chipset = screen->device->chipset; + int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac; + int vp5 = chipset >= 0xd0; + int ret; + + /* For all chipsets, try to create a BSP objects. Assume that if firmware + * is present for it, firmware is also present for VP/PPP */ + if (!(screen->firmware_info.profiles_checked & 1)) { + struct nouveau_object *channel = NULL, *bsp = NULL; + struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202}; + struct nvc0_fifo nvc0_args = {}; + struct nve0_fifo nve0_args = {.engine = NVE0_FIFO_ENGINE_BSP}; + void *data = NULL; + int size; + + if (chipset < 0xc0) { + data = &nv04_data; + size = sizeof(nv04_data); + } else if (chipset < 0xe0) { + data = &nvc0_args; + size = sizeof(nvc0_args); + } else { + data = &nve0_args; + size = sizeof(nve0_args); + } + + /* kepler must have its own channel, so just do this for everyone */ + nouveau_object_new(&screen->device->object, 0, + NOUVEAU_FIFO_CHANNEL_CLASS, + data, size, &channel); + + if (channel) { + ret = nouveau_object_mclass(channel, nouveau_decoder_msvld); + if (ret >= 0) + nouveau_object_new(channel, 0, nouveau_decoder_msvld[ret].oclass, + NULL, 0, &bsp); + if (bsp) + screen->firmware_info.profiles_present |= 1; + nouveau_object_del(&bsp); + nouveau_object_del(&channel); + } + screen->firmware_info.profiles_checked |= 1; + } + + if (!(screen->firmware_info.profiles_present & 1)) + return 0; + + /* For vp3/vp4 chipsets, make sure that the relevant firmware is present */ + if (!vp5 && !(screen->firmware_info.profiles_checked & (1 << profile))) { + char path[PATH_MAX]; + struct stat s; + if (vp3) + vp3_getpath(profile, path); + else + vp4_getpath(profile, path); + ret = stat(path, &s); + if (!ret && s.st_size > 1000) + screen->firmware_info.profiles_present |= (1 << profile); + screen->firmware_info.profiles_checked |= (1 << profile); + } + + return vp5 || (screen->firmware_info.profiles_present & (1 << profile)); +} + int nouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen, enum pipe_video_profile profile, @@ -363,8 +444,11 @@ nouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen, switch (param) { case PIPE_VIDEO_CAP_SUPPORTED: /* VP3 does not support MPEG4, VP4+ do. */ - return profile >= PIPE_VIDEO_PROFILE_MPEG1 && ( - !vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4); + return entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM && + profile >= PIPE_VIDEO_PROFILE_MPEG1 && + profile < PIPE_VIDEO_PROFILE_HEVC_MAIN && + (!vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4) && + firmware_present(pscreen, profile); case PIPE_VIDEO_CAP_NPOT_TEXTURES: return 1; case PIPE_VIDEO_CAP_MAX_WIDTH: