X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgallium%2Fdrivers%2Fnouveau%2Fnouveau_vp3_video.c;h=f3a64b22c5758c2a7460515bee3e494e19b06b7a;hb=6f7371619c5edcde647ae8f4822d1b5bae050ef6;hp=a3387b3e5652f27ef97ef29e35ccf96d97290add;hpb=9255019a53506737210a25995f525986bec7b836;p=mesa.git diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.c b/src/gallium/drivers/nouveau/nouveau_vp3_video.c index a3387b3e565..f3a64b22c57 100644 --- a/src/gallium/drivers/nouveau/nouveau_vp3_video.c +++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.c @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -169,26 +170,26 @@ error: } static void -nouveau_vp3_decoder_flush(struct pipe_video_decoder *decoder) +nouveau_vp3_decoder_flush(struct pipe_video_codec *decoder) { } static void -nouveau_vp3_decoder_begin_frame(struct pipe_video_decoder *decoder, +nouveau_vp3_decoder_begin_frame(struct pipe_video_codec *decoder, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) { } static void -nouveau_vp3_decoder_end_frame(struct pipe_video_decoder *decoder, +nouveau_vp3_decoder_end_frame(struct pipe_video_codec *decoder, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) { } static void -nouveau_vp3_decoder_destroy(struct pipe_video_decoder *decoder) +nouveau_vp3_decoder_destroy(struct pipe_video_codec *decoder) { struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder; int i; @@ -223,7 +224,7 @@ nouveau_vp3_decoder_destroy(struct pipe_video_decoder *decoder) } void -nouveau_vp3_decoder_init_common(struct pipe_video_decoder *dec) +nouveau_vp3_decoder_init_common(struct pipe_video_codec *dec) { dec->destroy = nouveau_vp3_decoder_destroy; dec->flush = nouveau_vp3_decoder_flush; @@ -231,22 +232,41 @@ nouveau_vp3_decoder_init_common(struct pipe_video_decoder *dec) dec->end_frame = nouveau_vp3_decoder_end_frame; } +static void vp3_getpath(enum pipe_video_profile profile, char *path) +{ + switch (u_reduce_video_profile(profile)) { + case PIPE_VIDEO_FORMAT_MPEG12: { + sprintf(path, "/lib/firmware/nouveau/vuc-vp3-mpeg12-0"); + break; + } + case PIPE_VIDEO_FORMAT_VC1: { + sprintf(path, "/lib/firmware/nouveau/vuc-vp3-vc1-0"); + break; + } + case PIPE_VIDEO_FORMAT_MPEG4_AVC: { + sprintf(path, "/lib/firmware/nouveau/vuc-vp3-h264-0"); + break; + } + default: assert(0); + } +} + static void vp4_getpath(enum pipe_video_profile profile, char *path) { switch (u_reduce_video_profile(profile)) { - case PIPE_VIDEO_CODEC_MPEG12: { + case PIPE_VIDEO_FORMAT_MPEG12: { sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0"); break; } - case PIPE_VIDEO_CODEC_MPEG4: { + case PIPE_VIDEO_FORMAT_MPEG4: { sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0"); break; } - case PIPE_VIDEO_CODEC_VC1: { + case PIPE_VIDEO_FORMAT_VC1: { sprintf(path, "/lib/firmware/nouveau/vuc-vc1-0"); break; } - case PIPE_VIDEO_CODEC_MPEG4_AVC: { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: { sprintf(path, "/lib/firmware/nouveau/vuc-h264-0"); break; } @@ -264,7 +284,10 @@ nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, ssize_t r; uint32_t *end, endval; - vp4_getpath(profile, path); + if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac) + vp4_getpath(profile, path); + else + vp3_getpath(profile, path); if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client)) return 1; @@ -300,22 +323,22 @@ nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4; switch (u_reduce_video_profile(profile)) { - case PIPE_VIDEO_CODEC_MPEG12: { + case PIPE_VIDEO_FORMAT_MPEG12: { assert((r & 0xff) == 0xe0); dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0); break; } - case PIPE_VIDEO_CODEC_MPEG4: { + case PIPE_VIDEO_FORMAT_MPEG4: { assert((r & 0xff) == 0xe0); dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0); break; } - case PIPE_VIDEO_CODEC_VC1: { + case PIPE_VIDEO_FORMAT_VC1: { assert((r & 0xff) == 0xac); dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac); break; } - case PIPE_VIDEO_CODEC_MPEG4_AVC: { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: { assert((r & 0xff) == 0x70); dec->fw_sizes = (0x370<<16) | (r - 0x370); break; @@ -327,3 +350,146 @@ nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, dec->fw_bo->map = NULL; return 0; } + +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, oclass; + if (chipset < 0xc0) + oclass = 0x85b1; + else if (chipset < 0xe0) + oclass = 0x90b1; + else + oclass = 0x95b1; + + 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) { + nouveau_object_new(channel, 0, 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, + enum pipe_video_entrypoint entrypoint, + enum pipe_video_cap param) +{ + int chipset = nouveau_screen(pscreen)->device->chipset; + int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac; + int vp5 = chipset >= 0xd0; + enum pipe_video_format codec = u_reduce_video_profile(profile); + switch (param) { + case PIPE_VIDEO_CAP_SUPPORTED: + /* VP3 does not support MPEG4, VP4+ do. */ + return entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM && + profile >= PIPE_VIDEO_PROFILE_MPEG1 && + (!vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4) && + firmware_present(pscreen, profile); + case PIPE_VIDEO_CAP_NPOT_TEXTURES: + return 1; + case PIPE_VIDEO_CAP_MAX_WIDTH: + case PIPE_VIDEO_CAP_MAX_HEIGHT: + return vp5 ? 4096 : 2048; + case PIPE_VIDEO_CAP_PREFERED_FORMAT: + return PIPE_FORMAT_NV12; + case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: + case PIPE_VIDEO_CAP_PREFERS_INTERLACED: + return true; + case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: + return false; + case PIPE_VIDEO_CAP_MAX_LEVEL: + switch (profile) { + case PIPE_VIDEO_PROFILE_MPEG1: + return 0; + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + return 3; + case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: + return 3; + case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: + return 5; + case PIPE_VIDEO_PROFILE_VC1_SIMPLE: + return 1; + case PIPE_VIDEO_PROFILE_VC1_MAIN: + return 2; + case PIPE_VIDEO_PROFILE_VC1_ADVANCED: + return 4; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: + return 41; + default: + debug_printf("unknown video profile: %d\n", profile); + return 0; + } + default: + debug_printf("unknown video param: %d\n", param); + return 0; + } +} + +boolean +nouveau_vp3_screen_video_supported(struct pipe_screen *screen, + enum pipe_format format, + enum pipe_video_profile profile, + enum pipe_video_entrypoint entrypoint) +{ + if (profile != PIPE_VIDEO_PROFILE_UNKNOWN) + return format == PIPE_FORMAT_NV12; + + return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint); +}