From 4fad211502d8fcc6a4906549e6458b3306dcc27c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Sun, 2 Dec 2012 12:07:35 +0100 Subject: [PATCH] nvc0: Add support for video buffer --- src/gallium/drivers/nvc0/Makefile.sources | 3 +- src/gallium/drivers/nvc0/nvc0_context.c | 3 +- src/gallium/drivers/nvc0/nvc0_context.h | 19 ++ src/gallium/drivers/nvc0/nvc0_miptree.c | 13 +- src/gallium/drivers/nvc0/nvc0_screen.c | 15 +- src/gallium/drivers/nvc0/nvc0_video.c | 214 ++++++++++++++++++++++ src/gallium/drivers/nvc0/nvc0_video.h | 54 ++++++ 7 files changed, 310 insertions(+), 11 deletions(-) create mode 100644 src/gallium/drivers/nvc0/nvc0_video.c create mode 100644 src/gallium/drivers/nvc0/nvc0_video.h diff --git a/src/gallium/drivers/nvc0/Makefile.sources b/src/gallium/drivers/nvc0/Makefile.sources index d0e213b40af..12eedf96231 100644 --- a/src/gallium/drivers/nvc0/Makefile.sources +++ b/src/gallium/drivers/nvc0/Makefile.sources @@ -13,4 +13,5 @@ C_SOURCES := \ nvc0_vbo_translate.c \ nvc0_program.c \ nvc0_shader_state.c \ - nvc0_query.c + nvc0_query.c \ + nvc0_video.c diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c index 23059a097b9..75bd1551b8f 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nvc0/nvc0_context.c @@ -261,7 +261,8 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0)); #endif - nouveau_context_init_vdec(&nvc0->base); + pipe->create_video_decoder = nvc0_create_decoder; + pipe->create_video_buffer = nvc0_video_buffer_create; /* shader builtin library is per-screen, but we need a context for m2mf */ nvc0_program_library_upload(nvc0); diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index 8e2aaff08a7..f5b0b6b849e 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -293,6 +293,25 @@ void nvc0_vertex_arrays_validate(struct nvc0_context *); void nvc0_idxbuf_validate(struct nvc0_context *); +/* nvc0_video.c */ +struct pipe_video_decoder * +nvc0_create_decoder(struct pipe_context *context, + enum pipe_video_profile profile, + enum pipe_video_entrypoint entrypoint, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, + unsigned max_references, + bool expect_chunked_decode); + +struct pipe_video_buffer * +nvc0_video_buffer_create(struct pipe_context *pipe, + const struct pipe_video_buffer *templat); + +int +nvc0_screen_get_video_param(struct pipe_screen *pscreen, + enum pipe_video_profile profile, + enum pipe_video_cap param); + /* nvc0_push.c */ void nvc0_push_vbo(struct nvc0_context *, const struct pipe_draw_info *); diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c index dd415d0ef6c..8c4d7240603 100644 --- a/src/gallium/drivers/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nvc0/nvc0_miptree.c @@ -167,18 +167,15 @@ nvc0_miptree_init_layout_video(struct nv50_miptree *mt) const struct pipe_resource *pt = &mt->base.base; const unsigned blocksize = util_format_get_blocksize(pt->format); - unsigned nbx = util_format_get_nblocksx(pt->format, pt->width0); - unsigned nby = util_format_get_nblocksy(pt->format, pt->height0); - assert(pt->last_level == 0); - assert(mt->ms_x == 0 && - mt->ms_y == 0); + assert(mt->ms_x == 0 && mt->ms_y == 0); assert(!util_format_is_compressed(pt->format)); - assert(nby > 8); + mt->layout_3d = pt->target == PIPE_TEXTURE_3D; + mt->level[0].tile_mode = 0x10; - mt->level[0].pitch = align(nbx * blocksize, 64); - mt->total_size = align(nby, 16) * mt->level[0].pitch; + mt->level[0].pitch = align(pt->width0 * blocksize, 64); + mt->total_size = align(pt->height0, 16) * mt->level[0].pitch * (mt->layout_3d ? pt->depth0 : 1); if (pt->array_size > 1) { mt->layer_stride = align(mt->total_size, NVC0_TILE_SIZE(0x10)); diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index d491bd3cfd9..de0513baff1 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -63,6 +63,18 @@ nvc0_screen_is_format_supported(struct pipe_screen *pscreen, return (nvc0_format_table[format].usage & bindings) == bindings; } +static boolean +nvc0_screen_video_supported(struct pipe_screen *screen, + enum pipe_format format, + enum pipe_video_profile profile) +{ + if (profile != PIPE_VIDEO_PROFILE_UNKNOWN) + return format == PIPE_FORMAT_NV12; + + return vl_video_buffer_is_format_supported(screen, format, profile); +} + + static int nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { @@ -446,7 +458,8 @@ nvc0_screen_create(struct nouveau_device *dev) nvc0_screen_init_resource_functions(pscreen); - nouveau_screen_init_vdec(&screen->base); + screen->base.base.get_video_param = nvc0_screen_get_video_param; + screen->base.base.is_video_format_supported = nvc0_screen_video_supported; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, NULL, &screen->fence.bo); diff --git a/src/gallium/drivers/nvc0/nvc0_video.c b/src/gallium/drivers/nvc0/nvc0_video.c new file mode 100644 index 00000000000..5cf16e79b2b --- /dev/null +++ b/src/gallium/drivers/nvc0/nvc0_video.c @@ -0,0 +1,214 @@ +/* + * Copyright 2011 Maarten Lankhorst + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "nvc0_video.h" + +#include "util/u_sampler.h" +#include "util/u_format.h" + +#include +#include + +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; + } +} + +struct pipe_video_decoder * +nvc0_create_decoder(struct pipe_context *context, + enum pipe_video_profile profile, + enum pipe_video_entrypoint entrypoint, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height, unsigned max_references, + bool chunked_decode) +{ + if (getenv("XVMC_VL")) + return vl_create_decoder(context, profile, entrypoint, + chroma_format, width, height, + max_references, chunked_decode); + + if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { + debug_printf("%x\n", entrypoint); + return NULL; + } + + 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_3D; + templ.depth0 = 2; + 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.last_level = 0; + templ.array_size = 1; + + 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; +} diff --git a/src/gallium/drivers/nvc0/nvc0_video.h b/src/gallium/drivers/nvc0/nvc0_video.h new file mode 100644 index 00000000000..e2cfc3d5902 --- /dev/null +++ b/src/gallium/drivers/nvc0/nvc0_video.h @@ -0,0 +1,54 @@ +/* + * Copyright 2011 Maarten Lankhorst + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "nvc0_context.h" +#include "nvc0_screen.h" + +#include "vl/vl_decoder.h" +#include "vl/vl_video_buffer.h" +#include "vl/vl_types.h" + +#include "util/u_video.h" + +struct nvc0_video_buffer { + struct pipe_video_buffer base; + unsigned num_planes, valid_ref; + struct pipe_resource *resources[VL_NUM_COMPONENTS]; + struct pipe_sampler_view *sampler_view_planes[VL_NUM_COMPONENTS]; + struct pipe_sampler_view *sampler_view_components[VL_NUM_COMPONENTS]; + struct pipe_surface *surfaces[VL_NUM_COMPONENTS * 2]; +}; + +static INLINE uint32_t nvc0_video_align(uint32_t h) +{ + return ((h+0x3f)&~0x3f); +}; + +static INLINE uint32_t mb(uint32_t coord) +{ + return (coord + 0xf)>>4; +} + +static INLINE uint32_t mb_half(uint32_t coord) +{ + return (coord + 0x1f)>>5; +} -- 2.30.2