#include "util/u_sampler.h"
#include "util/u_format.h"
-#include <sys/mman.h>
-#include <fcntl.h>
-
-int
-nvc0_screen_get_video_param(struct pipe_screen *pscreen,
- enum pipe_video_profile profile,
- enum pipe_video_cap param)
-{
- switch (param) {
- case PIPE_VIDEO_CAP_SUPPORTED:
- return profile >= PIPE_VIDEO_PROFILE_MPEG1;
- case PIPE_VIDEO_CAP_NPOT_TEXTURES:
- return 1;
- case PIPE_VIDEO_CAP_MAX_WIDTH:
- case PIPE_VIDEO_CAP_MAX_HEIGHT:
- return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096;
- 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;
- default:
- debug_printf("unknown video param: %d\n", param);
- return 0;
- }
-}
-
static void
nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *video_target,
const void *const *data,
const unsigned *num_bytes)
{
- struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
- struct nvc0_video_buffer *target = (struct nvc0_video_buffer *)video_target;
+ struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
+ struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
uint32_t comm_seq = ++dec->fence_seq;
union pipe_desc desc;
unsigned vp_caps, is_ref, ret;
- struct nvc0_video_buffer *refs[16] = {};
+ struct nouveau_vp3_video_buffer *refs[16] = {};
desc.base = picture;
nvc0_decoder_ppp(dec, desc, target, comm_seq);
}
-static void
-nvc0_decoder_flush(struct pipe_video_decoder *decoder)
-{
- struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
- (void)dec;
-}
-
-static void
-nvc0_decoder_begin_frame(struct pipe_video_decoder *decoder,
- struct pipe_video_buffer *target,
- struct pipe_picture_desc *picture)
-{
-}
-
-static void
-nvc0_decoder_end_frame(struct pipe_video_decoder *decoder,
- struct pipe_video_buffer *target,
- struct pipe_picture_desc *picture)
-{
-}
-
-static void
-nvc0_decoder_destroy(struct pipe_video_decoder *decoder)
-{
- struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
- int i;
-
- nouveau_bo_ref(NULL, &dec->ref_bo);
- nouveau_bo_ref(NULL, &dec->bitplane_bo);
- nouveau_bo_ref(NULL, &dec->inter_bo[0]);
- nouveau_bo_ref(NULL, &dec->inter_bo[1]);
-#ifdef NVC0_DEBUG_FENCE
- nouveau_bo_ref(NULL, &dec->fence_bo);
-#endif
- nouveau_bo_ref(NULL, &dec->fw_bo);
-
- for (i = 0; i < NVC0_VIDEO_QDEPTH; ++i)
- nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
-
- nouveau_object_del(&dec->bsp);
- nouveau_object_del(&dec->vp);
- nouveau_object_del(&dec->ppp);
-
- if (dec->channel[0] != dec->channel[1]) {
- for (i = 0; i < 3; ++i) {
- nouveau_pushbuf_del(&dec->pushbuf[i]);
- nouveau_object_del(&dec->channel[i]);
- }
- } else {
- nouveau_pushbuf_del(dec->pushbuf);
- nouveau_object_del(dec->channel);
- }
-
- FREE(dec);
-}
-
-static void nvc0_video_getpath(enum pipe_video_profile profile, char *path)
-{
- switch (u_reduce_video_profile(profile)) {
- case PIPE_VIDEO_CODEC_MPEG12: {
- sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
- break;
- }
- case PIPE_VIDEO_CODEC_MPEG4: {
- sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
- break;
- }
- case PIPE_VIDEO_CODEC_VC1: {
- sprintf(path, "/lib/firmware/nouveau/vuc-vc1-%u", profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE);
- break;
- }
- case PIPE_VIDEO_CODEC_MPEG4_AVC: {
- sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
- break;
- }
- default: assert(0);
- }
-}
-
struct pipe_video_decoder *
nvc0_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
bool chunked_decode)
{
struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
- struct nvc0_decoder *dec;
+ struct nouveau_vp3_decoder *dec;
struct nouveau_pushbuf **push;
union nouveau_bo_config cfg;
bool kepler = screen->device->chipset >= 0xe0;
return NULL;
}
- dec = CALLOC_STRUCT(nvc0_decoder);
+ dec = CALLOC_STRUCT(nouveau_vp3_decoder);
if (!dec)
return NULL;
dec->client = screen->client;
+ nouveau_vp3_decoder_init_common(&dec->base);
if (!kepler) {
dec->bsp_idx = 5;
dec->base.width = width;
dec->base.height = height;
dec->base.max_references = max_references;
- dec->base.destroy = nvc0_decoder_destroy;
- dec->base.flush = nvc0_decoder_flush;
dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
- dec->base.begin_frame = nvc0_decoder_begin_frame;
- dec->base.end_frame = nvc0_decoder_end_frame;
- for (i = 0; i < NVC0_VIDEO_QDEPTH && !ret; ++i)
+ for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
0, 1 << 20, &cfg, &dec->bsp_bo[i]);
if (!ret)
}
case PIPE_VIDEO_CODEC_MPEG4_AVC: {
codec = 3;
- dec->tmp_stride = 16 * mb_half(width) * nvc0_video_align(height) * 3 / 2;
+ dec->tmp_stride = 16 * mb_half(width) * nouveau_vp3_video_align(height) * 3 / 2;
tmp_size = dec->tmp_stride * (max_references + 1);
assert(max_references <= 16);
break;
}
if (screen->device->chipset < 0xd0) {
- int fd;
- char path[PATH_MAX];
- ssize_t r;
- uint32_t *end, endval;
-
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
0x4000, &cfg, &dec->fw_bo);
- if (!ret)
- ret = nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client);
if (ret)
goto fail;
- nvc0_video_getpath(profile, path);
-
- fd = open(path, O_RDONLY | O_CLOEXEC);
- if (fd < 0) {
- fprintf(stderr, "opening firmware file %s failed: %m\n", path);
- goto fw_fail;
- }
- r = read(fd, dec->fw_bo->map, 0x4000);
- close(fd);
-
- if (r < 0) {
- fprintf(stderr, "reading firmware file %s failed: %m\n", path);
- goto fw_fail;
- }
-
- if (r == 0x4000) {
- fprintf(stderr, "firmware file %s too large!\n", path);
- goto fw_fail;
- }
-
- if (r & 0xff) {
- fprintf(stderr, "firmware file %s wrong size!\n", path);
- goto fw_fail;
- }
-
- end = dec->fw_bo->map + r - 4;
- endval = *end;
- while (endval == *end)
- end--;
-
- r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
-
- switch (u_reduce_video_profile(profile)) {
- case PIPE_VIDEO_CODEC_MPEG12: {
- assert((r & 0xff) == 0xe0);
- dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
- break;
- }
- case PIPE_VIDEO_CODEC_MPEG4: {
- assert((r & 0xff) == 0xe0);
- dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
- break;
- }
- case PIPE_VIDEO_CODEC_VC1: {
- assert((r & 0xff) == 0xac);
- dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
- break;
- }
- case PIPE_VIDEO_CODEC_MPEG4_AVC: {
- assert((r & 0xff) == 0x70);
- dec->fw_sizes = (0x370<<16) | (r - 0x370);
- break;
- }
- default:
+ ret = nouveau_vp3_load_firmware(dec, profile, screen->device->chipset);
+ if (ret)
goto fw_fail;
- }
- munmap(dec->fw_bo->map, dec->fw_bo->size);
- dec->fw_bo->map = NULL;
}
if (codec != 3) {
goto fail;
}
- dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nvc0_video_align(height)/2);
+ dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nouveau_vp3_video_align(height)/2);
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
dec->ref_stride * (max_references+2) + tmp_size,
&cfg, &dec->ref_bo);
++dec->fence_seq;
-#if NVC0_DEBUG_FENCE
+#if NOUVEAU_VP3_DEBUG_FENCE
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
- 0, 0x1000, &cfg, &dec->fence_bo);
+ 0, 0x1000, NULL, &dec->fence_bo);
if (ret)
goto fail;
dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
/* So lets test if the fence is working? */
+ nouveau_pushbuf_space(push[0], 6, 1, 0);
+ PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
PUSH_DATAh(push[0], dec->fence_bo->offset);
PUSH_DATA (push[0], dec->fence_bo->offset);
PUSH_DATA (push[0], dec->fence_seq);
BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
- PUSH_DATA (push[0], 1);
+ PUSH_DATA (push[0], 0);
PUSH_KICK (push[0]);
+ nouveau_pushbuf_space(push[1], 6, 1, 0);
+ PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
PUSH_DATA (push[1], dec->fence_seq);
BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
- PUSH_DATA (push[1], 1);
+ PUSH_DATA (push[1], 0);
PUSH_KICK (push[1]);
+ nouveau_pushbuf_space(push[2], 6, 1, 0);
+ PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
PUSH_DATA (push[2], dec->fence_seq);
BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
- PUSH_DATA (push[2], 1);
+ PUSH_DATA (push[2], 0);
PUSH_KICK (push[2]);
usleep(100);
- while (dec->fence_seq > dec->fence_map[0] &&
- dec->fence_seq > dec->fence_map[4] &&
+ while (dec->fence_seq > dec->fence_map[0] ||
+ dec->fence_seq > dec->fence_map[4] ||
dec->fence_seq > dec->fence_map[8]) {
debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
usleep(100);
fw_fail:
debug_printf("Cannot create decoder without firmware..\n");
- nvc0_decoder_destroy(&dec->base);
+ dec->base.destroy(&dec->base);
return NULL;
fail:
debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
- nvc0_decoder_destroy(&dec->base);
+ dec->base.destroy(&dec->base);
return NULL;
}
-static struct pipe_sampler_view **
-nvc0_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
-{
- struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
- return buf->sampler_view_planes;
-}
-
-static struct pipe_sampler_view **
-nvc0_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
-{
- struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
- return buf->sampler_view_components;
-}
-
-static struct pipe_surface **
-nvc0_video_buffer_surfaces(struct pipe_video_buffer *buffer)
-{
- struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
- return buf->surfaces;
-}
-
-static void
-nvc0_video_buffer_destroy(struct pipe_video_buffer *buffer)
-{
- struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
- unsigned i;
-
- assert(buf);
-
- for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
- pipe_resource_reference(&buf->resources[i], NULL);
- pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
- pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
- pipe_surface_reference(&buf->surfaces[i * 2], NULL);
- pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
- }
- FREE(buffer);
-}
-
struct pipe_video_buffer *
nvc0_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *templat)
{
- struct nvc0_video_buffer *buffer;
- struct pipe_resource templ;
- unsigned i, j, component;
- 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->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
-
- buffer = CALLOC_STRUCT(nvc0_video_buffer);
- if (!buffer)
- return NULL;
- assert(!(templat->height % 4));
- assert(!(templat->width % 2));
-
- buffer->base.buffer_format = templat->buffer_format;
- buffer->base.context = pipe;
- buffer->base.destroy = nvc0_video_buffer_destroy;
- buffer->base.chroma_format = templat->chroma_format;
- buffer->base.width = templat->width;
- buffer->base.height = templat->height;
- buffer->base.get_sampler_view_planes = nvc0_video_buffer_sampler_view_planes;
- buffer->base.get_sampler_view_components = nvc0_video_buffer_sampler_view_components;
- buffer->base.get_surfaces = nvc0_video_buffer_surfaces;
- buffer->base.interlaced = true;
-
- memset(&templ, 0, sizeof(templ));
- templ.target = PIPE_TEXTURE_2D_ARRAY;
- templ.depth0 = 1;
- templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
- templ.format = PIPE_FORMAT_R8_UNORM;
- templ.width0 = buffer->base.width;
- templ.height0 = buffer->base.height/2;
- templ.flags = NVC0_RESOURCE_FLAG_VIDEO;
- templ.array_size = 2;
-
- buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
- if (!buffer->resources[0])
- goto error;
-
- templ.format = PIPE_FORMAT_R8G8_UNORM;
- buffer->num_planes = 2;
- templ.width0 /= 2;
- templ.height0 /= 2;
- for (i = 1; i < buffer->num_planes; ++i) {
- buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
- if (!buffer->resources[i])
- goto error;
- }
-
- memset(&sv_templ, 0, sizeof(sv_templ));
- for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
- struct pipe_resource *res = buffer->resources[i];
- unsigned nr_components = util_format_get_nr_components(res->format);
-
- u_sampler_view_default_template(&sv_templ, res, res->format);
- buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
- if (!buffer->sampler_view_planes[i])
- 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;
-
- buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
- if (!buffer->sampler_view_components[component])
- goto error;
- }
- }
-
- memset(&surf_templ, 0, sizeof(surf_templ));
- for (j = 0; j < buffer->num_planes; ++j) {
- surf_templ.format = buffer->resources[j]->format;
- surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
- buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
- if (!buffer->surfaces[j * 2])
- goto error;
-
- surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
- buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
- if (!buffer->surfaces[j * 2 + 1])
- goto error;
- }
-
- return &buffer->base;
-
-error:
- nvc0_video_buffer_destroy(&buffer->base);
- return NULL;
+ return nouveau_vp3_video_buffer_create(
+ pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
}