Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv98_video.c
4574 views
/*1* Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#include "nv50/nv98_video.h"2324#include "util/u_sampler.h"25#include "util/format/u_format.h"2627#include <nvif/class.h>2829static void30nv98_decoder_decode_bitstream(struct pipe_video_codec *decoder,31struct pipe_video_buffer *video_target,32struct pipe_picture_desc *picture,33unsigned num_buffers,34const void *const *data,35const unsigned *num_bytes)36{37struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;38struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;39uint32_t comm_seq = ++dec->fence_seq;40union pipe_desc desc;4142unsigned vp_caps, is_ref;43ASSERTED unsigned ret; /* used in debug checks */44struct nouveau_vp3_video_buffer *refs[16] = {};4546desc.base = picture;4748assert(target->base.buffer_format == PIPE_FORMAT_NV12);4950ret = nv98_decoder_bsp(dec, desc, target, comm_seq,51num_buffers, data, num_bytes,52&vp_caps, &is_ref, refs);5354/* did we decode bitstream correctly? */55assert(ret == 2);5657nv98_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);58nv98_decoder_ppp(dec, desc, target, comm_seq);59}6061static const struct nouveau_mclass62nv98_decoder_msvld[] = {63{ G98_MSVLD, -1 },64{ IGT21A_MSVLD, -1 },65{ GT212_MSVLD, -1 },66{}67};6869static const struct nouveau_mclass70nv98_decoder_mspdec[] = {71{ G98_MSPDEC, -1 },72{ GT212_MSPDEC, -1 },73{}74};7576static const struct nouveau_mclass77nv98_decoder_msppp[] = {78{ G98_MSPPP, -1 },79{ GT212_MSPPP, -1 },80{}81};8283struct pipe_video_codec *84nv98_create_decoder(struct pipe_context *context,85const struct pipe_video_codec *templ)86{87struct nouveau_screen *screen = &((struct nv50_context *)context)->screen->base;88struct nouveau_vp3_decoder *dec;89struct nouveau_pushbuf **push;90struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202};9192int ret, i;93uint32_t codec = 1, ppp_codec = 3;94uint32_t timeout;95u32 tmp_size = 0;9697if (getenv("XVMC_VL"))98return vl_create_decoder(context, templ);99100if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {101debug_printf("%x\n", templ->entrypoint);102return NULL;103}104105dec = CALLOC_STRUCT(nouveau_vp3_decoder);106if (!dec)107return NULL;108dec->client = screen->client;109dec->base = *templ;110nouveau_vp3_decoder_init_common(&dec->base);111112dec->bsp_idx = 5;113dec->vp_idx = 6;114dec->ppp_idx = 7;115116ret = nouveau_object_new(&screen->device->object, 0,117NOUVEAU_FIFO_CHANNEL_CLASS,118&nv04_data, sizeof(nv04_data), &dec->channel[0]);119120if (!ret)121ret = nouveau_pushbuf_new(screen->client, dec->channel[0], 4,12232 * 1024, true, &dec->pushbuf[0]);123124for (i = 1; i < 3; ++i) {125dec->channel[i] = dec->channel[0];126dec->pushbuf[i] = dec->pushbuf[0];127}128push = dec->pushbuf;129130if (!ret) {131ret = nouveau_object_mclass(dec->channel[0], nv98_decoder_msvld);132if (ret >= 0) {133ret = nouveau_object_new(dec->channel[0], 0xbeef85b1,134nv98_decoder_msvld[ret].oclass, NULL, 0,135&dec->bsp);136}137}138139if (!ret) {140ret = nouveau_object_mclass(dec->channel[1], nv98_decoder_mspdec);141if (ret >= 0) {142ret = nouveau_object_new(dec->channel[1], 0xbeef85b2,143nv98_decoder_mspdec[ret].oclass, NULL, 0,144&dec->vp);145}146}147148if (!ret) {149ret = nouveau_object_mclass(dec->channel[2], nv98_decoder_msppp);150if (ret >= 0) {151ret = nouveau_object_new(dec->channel[2], 0xbeef85b3,152nv98_decoder_msppp[ret].oclass, NULL, 0,153&dec->ppp);154}155}156157if (ret)158goto fail;159160BEGIN_NV04(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);161PUSH_DATA (push[0], dec->bsp->handle);162163BEGIN_NV04(push[0], SUBC_BSP(0x180), 5);164for (i = 0; i < 5; i++)165PUSH_DATA (push[0], nv04_data.vram);166167BEGIN_NV04(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);168PUSH_DATA (push[1], dec->vp->handle);169170BEGIN_NV04(push[1], SUBC_VP(0x180), 6);171for (i = 0; i < 6; i++)172PUSH_DATA (push[1], nv04_data.vram);173174BEGIN_NV04(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);175PUSH_DATA (push[2], dec->ppp->handle);176177BEGIN_NV04(push[2], SUBC_PPP(0x180), 5);178for (i = 0; i < 5; i++)179PUSH_DATA (push[2], nv04_data.vram);180181dec->base.context = context;182dec->base.decode_bitstream = nv98_decoder_decode_bitstream;183184for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)185ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,1860, 1 << 20, NULL, &dec->bsp_bo[i]);187if (!ret)188ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,1890x100, 4 << 20, NULL, &dec->inter_bo[0]);190if (!ret)191nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);192if (ret)193goto fail;194195switch (u_reduce_video_profile(templ->profile)) {196case PIPE_VIDEO_FORMAT_MPEG12: {197codec = 1;198assert(templ->max_references <= 2);199break;200}201case PIPE_VIDEO_FORMAT_MPEG4: {202codec = 4;203tmp_size = mb(templ->height)*16 * mb(templ->width)*16;204assert(templ->max_references <= 2);205break;206}207case PIPE_VIDEO_FORMAT_VC1: {208ppp_codec = codec = 2;209tmp_size = mb(templ->height)*16 * mb(templ->width)*16;210assert(templ->max_references <= 2);211break;212}213case PIPE_VIDEO_FORMAT_MPEG4_AVC: {214codec = 3;215dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;216tmp_size = dec->tmp_stride * (templ->max_references + 1);217assert(templ->max_references <= 16);218break;219}220default:221fprintf(stderr, "invalid codec\n");222goto fail;223}224225ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,2260x4000, NULL, &dec->fw_bo);227if (ret)228goto fail;229230ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);231if (ret)232goto fw_fail;233234if (codec != 3) {235ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,2360x400, NULL, &dec->bitplane_bo);237if (ret)238goto fail;239}240241dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);242ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,243dec->ref_stride * (templ->max_references+2) + tmp_size,244NULL, &dec->ref_bo);245if (ret)246goto fail;247248timeout = 0;249250BEGIN_NV04(push[0], SUBC_BSP(0x200), 2);251PUSH_DATA (push[0], codec);252PUSH_DATA (push[0], timeout);253254BEGIN_NV04(push[1], SUBC_VP(0x200), 2);255PUSH_DATA (push[1], codec);256PUSH_DATA (push[1], timeout);257258BEGIN_NV04(push[2], SUBC_PPP(0x200), 2);259PUSH_DATA (push[2], ppp_codec);260PUSH_DATA (push[2], timeout);261262++dec->fence_seq;263264#if NOUVEAU_VP3_DEBUG_FENCE265ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,2660, 0x1000, NULL, &dec->fence_bo);267if (ret)268goto fail;269270nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);271dec->fence_map = dec->fence_bo->map;272dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;273dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));274275/* So lets test if the fence is working? */276nouveau_pushbuf_space(push[0], 16, 1, 0);277PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);278BEGIN_NV04(push[0], SUBC_BSP(0x240), 3);279PUSH_DATAh(push[0], dec->fence_bo->offset);280PUSH_DATA (push[0], dec->fence_bo->offset);281PUSH_DATA (push[0], dec->fence_seq);282283BEGIN_NV04(push[0], SUBC_BSP(0x304), 1);284PUSH_DATA (push[0], 0);285PUSH_KICK (push[0]);286287nouveau_pushbuf_space(push[1], 16, 1, 0);288PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);289BEGIN_NV04(push[1], SUBC_VP(0x240), 3);290PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));291PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));292PUSH_DATA (push[1], dec->fence_seq);293294BEGIN_NV04(push[1], SUBC_VP(0x304), 1);295PUSH_DATA (push[1], 0);296PUSH_KICK (push[1]);297298nouveau_pushbuf_space(push[2], 16, 1, 0);299PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);300BEGIN_NV04(push[2], SUBC_PPP(0x240), 3);301PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));302PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));303PUSH_DATA (push[2], dec->fence_seq);304305BEGIN_NV04(push[2], SUBC_PPP(0x304), 1);306PUSH_DATA (push[2], 0);307PUSH_KICK (push[2]);308309usleep(100);310while (dec->fence_seq > dec->fence_map[0] ||311dec->fence_seq > dec->fence_map[4] ||312dec->fence_seq > dec->fence_map[8]) {313debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);314usleep(100);315}316debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);317#endif318319return &dec->base;320321fw_fail:322debug_printf("Cannot create decoder without firmware..\n");323dec->base.destroy(&dec->base);324return NULL;325326fail:327debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);328dec->base.destroy(&dec->base);329return NULL;330}331332struct pipe_video_buffer *333nv98_video_buffer_create(struct pipe_context *pipe,334const struct pipe_video_buffer *templat)335{336return nouveau_vp3_video_buffer_create(337pipe, templat, NV50_RESOURCE_FLAG_VIDEO);338}339340341