From 2e6274fc3b123e7de695038054b5cbd20b11559a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20K=C3=B6nig?= Date: Sat, 23 Apr 2011 13:24:35 +0200 Subject: [PATCH] [g3dvl] make ycbcr stream and block data a public interface --- src/gallium/auxiliary/vl/vl_mpeg12_decoder.c | 210 +++++------------- src/gallium/auxiliary/vl/vl_mpeg12_decoder.h | 2 - src/gallium/auxiliary/vl/vl_vertex_buffers.c | 43 +--- src/gallium/auxiliary/vl/vl_vertex_buffers.h | 13 +- src/gallium/include/pipe/p_video_context.h | 24 +- src/gallium/include/pipe/p_video_state.h | 29 ++- .../vdpau/mpeg2_bitstream_parser.c | 2 + .../vdpau/mpeg2_bitstream_parser.h | 2 + .../state_trackers/xorg/xvmc/surface.c | 105 +++++++-- .../state_trackers/xorg/xvmc/xvmc_private.h | 7 +- 10 files changed, 189 insertions(+), 248 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c index 3b1d26d3db8..dcef6207afd 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c @@ -38,12 +38,6 @@ #define SCALE_FACTOR_SNORM (32768.0f / 256.0f) #define SCALE_FACTOR_SSCALED (1.0f / 256.0f) -static const unsigned const_empty_block_mask_420[3][2][2] = { - { { 0x20, 0x10 }, { 0x08, 0x04 } }, - { { 0x02, 0x02 }, { 0x02, 0x02 } }, - { { 0x01, 0x01 }, { 0x01, 0x01 } } -}; - static const enum pipe_format const_zscan_source_formats[] = { PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16_SSCALED @@ -78,108 +72,6 @@ static const enum pipe_format const_mc_source_formats[] = { static const unsigned num_mc_source_formats = sizeof(const_mc_source_formats) / sizeof(enum pipe_format); -static void -map_buffers(struct vl_mpeg12_decoder *ctx, struct vl_mpeg12_buffer *buffer) -{ - struct pipe_sampler_view **sampler_views; - struct pipe_resource *tex; - unsigned i; - - assert(ctx && buffer); - - sampler_views = buffer->zscan_source->get_sampler_views(buffer->zscan_source); - - assert(sampler_views); - - for (i = 0; i < VL_MAX_PLANES; ++i) { - tex = sampler_views[i]->texture; - - struct pipe_box rect = - { - 0, 0, 0, - tex->width0, - tex->height0, - 1 - }; - - buffer->tex_transfer[i] = ctx->pipe->get_transfer - ( - ctx->pipe, tex, - 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, - &rect - ); - - buffer->texels[i] = ctx->pipe->transfer_map(ctx->pipe, buffer->tex_transfer[i]); - } -} - -static void -upload_block(struct vl_mpeg12_buffer *buffer, unsigned plane, - unsigned x, unsigned y, short *block, - bool intra, enum pipe_mpeg12_dct_type type) -{ - short *texels; - unsigned idx; - - assert(buffer); - assert(block); - - idx = vl_vb_add_ycbcr(&buffer->vertex_stream, plane, x, y, intra, type); - - texels = buffer->texels[plane] + idx * BLOCK_WIDTH * BLOCK_HEIGHT; - - memcpy(texels, block, BLOCK_WIDTH * BLOCK_HEIGHT * sizeof(short)); -} - -static void -upload_buffer(struct vl_mpeg12_decoder *ctx, - struct vl_mpeg12_buffer *buffer, - struct pipe_mpeg12_macroblock *mb) -{ - short *blocks; - unsigned tb, x, y; - - assert(ctx); - assert(buffer); - assert(mb); - - blocks = mb->blocks; - - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x, ++tb) { - if (mb->cbp & (*ctx->empty_block_mask)[0][y][x]) { - upload_block(buffer, 0, mb->mbx * 2 + x, mb->mby * 2 + y, blocks, - mb->dct_intra, mb->dct_type); - blocks += BLOCK_WIDTH * BLOCK_HEIGHT; - } - } - } - - /* TODO: Implement 422, 444 */ - assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); - - for (tb = 1; tb < 3; ++tb) { - if (mb->cbp & (*ctx->empty_block_mask)[tb][0][0]) { - upload_block(buffer, tb, mb->mbx, mb->mby, blocks, - mb->dct_intra, mb->dct_type); - blocks += BLOCK_WIDTH * BLOCK_HEIGHT; - } - } -} - -static void -unmap_buffers(struct vl_mpeg12_decoder *ctx, struct vl_mpeg12_buffer *buffer) -{ - unsigned i; - - assert(ctx && buffer); - - for (i = 0; i < VL_MAX_PLANES; ++i) { - ctx->pipe->transfer_unmap(ctx->pipe, buffer->tex_transfer[i]); - ctx->pipe->transfer_destroy(ctx->pipe, buffer->tex_transfer[i]); - } -} - static bool init_zscan_buffer(struct vl_mpeg12_buffer *buffer) { @@ -364,57 +256,81 @@ vl_mpeg12_buffer_map(struct pipe_video_decode_buffer *buffer) { struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; struct vl_mpeg12_decoder *dec; + + struct pipe_sampler_view **sampler_views; + unsigned i; + assert(buf); dec = (struct vl_mpeg12_decoder *)buf->base.decoder; assert(dec); vl_vb_map(&buf->vertex_stream, dec->pipe); - map_buffers(dec, buf); + + sampler_views = buf->zscan_source->get_sampler_views(buf->zscan_source); + + assert(sampler_views); + + for (i = 0; i < VL_MAX_PLANES; ++i) { + struct pipe_resource *tex = sampler_views[i]->texture; + struct pipe_box rect = + { + 0, 0, 0, + tex->width0, + tex->height0, + 1 + }; + + buf->tex_transfer[i] = dec->pipe->get_transfer + ( + dec->pipe, tex, + 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, + &rect + ); + + buf->texels[i] = dec->pipe->transfer_map(dec->pipe, buf->tex_transfer[i]); + } } -static unsigned -vl_mpeg12_buffer_get_mv_stream_stride(struct pipe_video_decode_buffer *buffer) +static struct pipe_ycbcr_block * +vl_mpeg12_buffer_get_ycbcr_stream(struct pipe_video_decode_buffer *buffer, int component) { struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; assert(buf); - return vl_vb_get_mv_stream_stride(&buf->vertex_stream); + return vl_vb_get_ycbcr_stream(&buf->vertex_stream, component); } -static struct pipe_motionvector * -vl_mpeg12_buffer_get_mv_stream(struct pipe_video_decode_buffer *buffer, int ref_frame) +static short * +vl_mpeg12_buffer_get_ycbcr_buffer(struct pipe_video_decode_buffer *buffer, int component) { struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; assert(buf); + assert(component < VL_MAX_PLANES); - return vl_vb_get_mv_stream(&buf->vertex_stream, ref_frame); + return buf->texels[component]; } -static void -vl_mpeg12_buffer_add_macroblocks(struct pipe_video_decode_buffer *buffer, - unsigned num_macroblocks, - struct pipe_macroblock *macroblocks) +static unsigned +vl_mpeg12_buffer_get_mv_stream_stride(struct pipe_video_decode_buffer *buffer) { - struct pipe_mpeg12_macroblock *mb = (struct pipe_mpeg12_macroblock*)macroblocks; struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; - struct vl_mpeg12_decoder *dec; - unsigned i; assert(buf); - dec = (struct vl_mpeg12_decoder*)buf->base.decoder; - assert(dec); + return vl_vb_get_mv_stream_stride(&buf->vertex_stream); +} - assert(num_macroblocks); - assert(macroblocks); - assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12); +static struct pipe_motionvector * +vl_mpeg12_buffer_get_mv_stream(struct pipe_video_decode_buffer *buffer, int ref_frame) +{ + struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; - for ( i = 0; i < num_macroblocks; ++i ) { - upload_buffer(dec, buf, &mb[i]); - } + assert(buf); + + return vl_vb_get_mv_stream(&buf->vertex_stream, ref_frame); } static void @@ -422,13 +338,19 @@ vl_mpeg12_buffer_unmap(struct pipe_video_decode_buffer *buffer) { struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; struct vl_mpeg12_decoder *dec; + unsigned i; + assert(buf); dec = (struct vl_mpeg12_decoder *)buf->base.decoder; assert(dec); vl_vb_unmap(&buf->vertex_stream, dec->pipe); - unmap_buffers(dec, buf); + + for (i = 0; i < VL_MAX_PLANES; ++i) { + dec->pipe->transfer_unmap(dec->pipe, buf->tex_transfer[i]); + dec->pipe->transfer_destroy(dec->pipe, buf->tex_transfer[i]); + } } static void @@ -483,9 +405,10 @@ vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder) buffer->base.decoder = decoder; buffer->base.destroy = vl_mpeg12_buffer_destroy; buffer->base.map = vl_mpeg12_buffer_map; + buffer->base.get_ycbcr_stream = vl_mpeg12_buffer_get_ycbcr_stream; + buffer->base.get_ycbcr_buffer = vl_mpeg12_buffer_get_ycbcr_buffer; buffer->base.get_mv_stream_stride = vl_mpeg12_buffer_get_mv_stream_stride; buffer->base.get_mv_stream = vl_mpeg12_buffer_get_mv_stream; - buffer->base.add_macroblocks = vl_mpeg12_buffer_add_macroblocks; buffer->base.unmap = vl_mpeg12_buffer_unmap; vl_vb_init(&buffer->vertex_stream, dec->pipe, @@ -550,6 +473,7 @@ error_vertex_stream: static void vl_mpeg12_decoder_flush_buffer(struct pipe_video_decode_buffer *buffer, + unsigned num_ycbcr_blocks[3], struct pipe_video_buffer *refs[2], struct pipe_video_buffer *dst, struct pipe_fence_handle **fence) @@ -593,34 +517,22 @@ vl_mpeg12_decoder_flush_buffer(struct pipe_video_decode_buffer *buffer, dec->pipe->bind_vertex_elements_state(dec->pipe, dec->ves_ycbcr); for (i = 0; i < VL_MAX_PLANES; ++i) { - unsigned num_instances = vl_vb_restart(&buf->vertex_stream, i); + if (num_ycbcr_blocks[i] == 0) continue; vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, i); dec->pipe->set_vertex_buffers(dec->pipe, 2, vb); - vl_zscan_render(&buf->zscan[i] , num_instances); + vl_zscan_render(&buf->zscan[i] , num_ycbcr_blocks[i]); if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) - vl_idct_flush(i == 0 ? &dec->idct_y : &dec->idct_c, &buf->idct[i], num_instances); + vl_idct_flush(i == 0 ? &dec->idct_y : &dec->idct_c, &buf->idct[i], num_ycbcr_blocks[i]); - vl_mc_render_ycbcr(&buf->mc[i], num_instances); + vl_mc_render_ycbcr(&buf->mc[i], num_ycbcr_blocks[i]); } dec->pipe->flush(dec->pipe, fence); } -static void -vl_mpeg12_decoder_clear_buffer(struct pipe_video_decode_buffer *buffer) -{ - struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer *)buffer; - unsigned i; - - assert(buf); - - for (i = 0; i < VL_MAX_PLANES; ++i) - vl_vb_restart(&buf->vertex_stream, i); -} - static bool init_pipe_state(struct vl_mpeg12_decoder *dec) { @@ -819,7 +731,6 @@ vl_create_mpeg12_decoder(struct pipe_video_context *context, dec->base.destroy = vl_mpeg12_destroy; dec->base.create_buffer = vl_mpeg12_create_buffer; dec->base.flush_buffer = vl_mpeg12_decoder_flush_buffer; - dec->base.clear_buffer = vl_mpeg12_decoder_clear_buffer; dec->base.width = align(width, MACROBLOCK_WIDTH); dec->base.height = align(height, MACROBLOCK_HEIGHT); @@ -838,7 +749,6 @@ vl_create_mpeg12_decoder(struct pipe_video_context *context, /* TODO: Implement 422, 444 */ assert(dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); - dec->empty_block_mask = &const_empty_block_mask_420; dec->mc_source_format = find_first_supported_format(dec, const_mc_source_formats, num_mc_source_formats, PIPE_TEXTURE_3D); diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h index b94f12a9b7a..9d5768816fb 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h +++ b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h @@ -49,8 +49,6 @@ struct vl_mpeg12_decoder unsigned blocks_per_line; unsigned max_blocks; - - const unsigned (*empty_block_mask)[3][2][2]; unsigned nr_of_idct_render_targets; enum pipe_format zscan_source_format; diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.c b/src/gallium/auxiliary/vl/vl_vertex_buffers.c index d2025f76b86..d2e03988acf 100644 --- a/src/gallium/auxiliary/vl/vl_vertex_buffers.c +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.c @@ -30,14 +30,6 @@ #include "vl_vertex_buffers.h" #include "vl_types.h" -struct vl_ycbcr_vertex_stream -{ - uint8_t x; - uint8_t y; - uint8_t intra; - uint8_t field; -}; - /* vertices for a quad covering a block */ static const struct vertex2f block_quad[4] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} @@ -221,13 +213,12 @@ vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, size = width * height; for (i = 0; i < VL_MAX_PLANES; ++i) { - buffer->ycbcr[i].num_instances = 0; buffer->ycbcr[i].resource = pipe_buffer_create ( pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, - sizeof(struct vl_ycbcr_vertex_stream) * size * 4 + sizeof(struct pipe_ycbcr_block) * size * 4 ); } @@ -251,7 +242,7 @@ vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component) assert(buffer); - buf.stride = sizeof(struct vl_ycbcr_vertex_stream); + buf.stride = sizeof(struct pipe_ycbcr_block); buf.buffer_offset = 0; buf.buffer = buffer->ycbcr[component].resource; @@ -301,23 +292,13 @@ vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) } -unsigned -vl_vb_add_ycbcr(struct vl_vertex_buffer *buffer, - unsigned component, unsigned x, unsigned y, - bool intra, enum pipe_mpeg12_dct_type type) +struct pipe_ycbcr_block * +vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component) { - struct vl_ycbcr_vertex_stream *stream; - assert(buffer); - assert(buffer->ycbcr[component].num_instances < buffer->width * buffer->height * 4); - - stream = buffer->ycbcr[component].vertex_stream++; - stream->x = x; - stream->y = y; - stream->intra = intra; - stream->field = type == PIPE_MPEG12_DCT_TYPE_FIELD; + assert(component < VL_MAX_PLANES); - return buffer->ycbcr[component].num_instances++; + return buffer->ycbcr[component].vertex_stream; } unsigned @@ -353,18 +334,6 @@ vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) } } -unsigned -vl_vb_restart(struct vl_vertex_buffer *buffer, int component) -{ - unsigned num_instances; - - assert(buffer); - - num_instances = buffer->ycbcr[component].num_instances; - buffer->ycbcr[component].num_instances = 0; - return num_instances; -} - void vl_vb_cleanup(struct vl_vertex_buffer *buffer) { diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.h b/src/gallium/auxiliary/vl/vl_vertex_buffers.h index 89d455225ad..5293820ffca 100644 --- a/src/gallium/auxiliary/vl/vl_vertex_buffers.h +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.h @@ -55,10 +55,9 @@ struct vl_vertex_buffer unsigned width, height; struct { - unsigned num_instances; - struct pipe_resource *resource; - struct pipe_transfer *transfer; - struct vl_ycbcr_vertex_stream *vertex_stream; + struct pipe_resource *resource; + struct pipe_transfer *transfer; + struct pipe_ycbcr_block *vertex_stream; } ycbcr[VL_MAX_PLANES]; struct { @@ -84,9 +83,7 @@ void vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe); struct pipe_vertex_buffer vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component); -unsigned vl_vb_add_ycbcr(struct vl_vertex_buffer *buffer, - unsigned component, unsigned x, unsigned y, - bool intra, enum pipe_mpeg12_dct_type type); +struct pipe_ycbcr_block *vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component); struct pipe_vertex_buffer vl_vb_get_mv(struct vl_vertex_buffer *buffer, int ref_frame); @@ -96,8 +93,6 @@ struct pipe_motionvector *vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, i void vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe); -unsigned vl_vb_restart(struct vl_vertex_buffer *buffer, int component); - void vl_vb_cleanup(struct vl_vertex_buffer *buffer); #endif /* vl_vertex_buffers_h */ diff --git a/src/gallium/include/pipe/p_video_context.h b/src/gallium/include/pipe/p_video_context.h index 1eb96420fb7..8775bbb2705 100644 --- a/src/gallium/include/pipe/p_video_context.h +++ b/src/gallium/include/pipe/p_video_context.h @@ -158,15 +158,10 @@ struct pipe_video_decoder * flush decoder buffer to video hardware */ void (*flush_buffer)(struct pipe_video_decode_buffer *decbuf, + unsigned num_ycbcr_blocks[3], struct pipe_video_buffer *ref_frames[2], struct pipe_video_buffer *dst, struct pipe_fence_handle **fence); - - /** - * clear decoder buffers todo list - */ - void (*clear_buffer)(struct pipe_video_decode_buffer *decbuf); - }; /** @@ -186,6 +181,16 @@ struct pipe_video_decode_buffer */ void (*map)(struct pipe_video_decode_buffer *decbuf); + /** + * get the pointer where to put the ycbcr blocks of a component + */ + struct pipe_ycbcr_block *(*get_ycbcr_stream)(struct pipe_video_decode_buffer *, int component); + + /** + * get the pointer where to put the ycbcr dct block data of a component + */ + short *(*get_ycbcr_buffer)(struct pipe_video_decode_buffer *, int component); + /** * get the stride of the mv buffer */ @@ -205,13 +210,6 @@ struct pipe_video_decode_buffer struct pipe_buffer **bitstream_buf); #endif - /** - * add macroblocks to decoder buffer - */ - void (*add_macroblocks)(struct pipe_video_decode_buffer *decbuf, - unsigned num_macroblocks, - struct pipe_macroblock *macroblocks); - /** * unmap decoder buffer before flushing */ diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index dcb64d3c220..8bd84c2846a 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -50,10 +50,16 @@ enum pipe_mpeg12_picture_type PIPE_MPEG12_PICTURE_TYPE_FRAME }; +enum pipe_mpeg12_dct_intra +{ + PIPE_MPEG12_DCT_DELTA = 0, + PIPE_MPEG12_DCT_INTRA = 1 +}; + enum pipe_mpeg12_dct_type { - PIPE_MPEG12_DCT_TYPE_FIELD, - PIPE_MPEG12_DCT_TYPE_FRAME + PIPE_MPEG12_DCT_TYPE_FRAME = 0, + PIPE_MPEG12_DCT_TYPE_FIELD = 1 }; enum pipe_video_field_select @@ -75,11 +81,6 @@ enum pipe_video_mv_weight PIPE_VIDEO_MV_WEIGHT_MAX = 256 }; -struct pipe_macroblock -{ - enum pipe_video_codec codec; -}; - /* bitfields because this is used as a vertex buffer element */ struct pipe_motionvector { @@ -90,16 +91,12 @@ struct pipe_motionvector } top, bottom; }; -struct pipe_mpeg12_macroblock +/* bitfields because this is used as a vertex buffer element */ +struct pipe_ycbcr_block { - struct pipe_macroblock base; - - unsigned mbx; - unsigned mby; - bool dct_intra; - enum pipe_mpeg12_dct_type dct_type; - unsigned cbp; - short *blocks; + unsigned x:8, y:8; + enum pipe_mpeg12_dct_intra intra:8; + enum pipe_mpeg12_dct_type coding:8; }; #if 0 diff --git a/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c index 7b285079a19..182f3d44c45 100644 --- a/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c +++ b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.c @@ -28,6 +28,7 @@ #include #include "mpeg2_bitstream_parser.h" +#if 0 int vlVdpMPEG2NextStartCode(struct vdpMPEG2BitstreamParser *parser) { @@ -130,3 +131,4 @@ vlVdpMPEG2BitstreamToMacroblock(struct pipe_screen *screen, return 0; } +#endif diff --git a/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h index 1fa425fdcdb..2f8a14996c5 100644 --- a/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h +++ b/src/gallium/state_trackers/vdpau/mpeg2_bitstream_parser.h @@ -53,11 +53,13 @@ struct vdpMPEG2BitstreamParser uint32_t horizontal_size_value; }; +#if 0 int vlVdpMPEG2BitstreamToMacroblock(struct pipe_screen *screen, VdpBitstreamBuffer const *bitstream_buffers, uint32_t bitstream_buffer_count, unsigned int *num_macroblocks, struct pipe_mpeg12_macroblock **pipe_macroblocks); +#endif #endif // MPEG2_BITSTREAM_PARSER_H diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 567484e993d..f8a0f3c7fd9 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -42,6 +42,12 @@ #include "xvmc_private.h" +static const unsigned const_empty_block_mask_420[3][2][2] = { + { { 0x20, 0x10 }, { 0x08, 0x04 } }, + { { 0x02, 0x02 }, { 0x02, 0x02 } }, + { { 0x01, 0x01 }, { 0x01, 0x01 } } +}; + static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic) { switch (xvmc_pic) { @@ -136,34 +142,89 @@ MotionVectorToPipe(const XvMCMacroBlock *xvmc_mb, unsigned vector, return mv; } +static inline void +UploadYcbcrBlocks(XvMCSurfacePrivate *surface, + const XvMCMacroBlock *xvmc_mb, + const XvMCBlockArray *xvmc_blocks) +{ + enum pipe_mpeg12_dct_intra intra; + enum pipe_mpeg12_dct_type coding; + + unsigned tb, x, y; + short *blocks; + + assert(surface); + assert(xvmc_mb); + + intra = xvmc_mb->macroblock_type & XVMC_MB_TYPE_INTRA ? + PIPE_MPEG12_DCT_INTRA : PIPE_MPEG12_DCT_DELTA; + + coding = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ? + PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME; + + blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; + + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x, ++tb) { + if (xvmc_mb->coded_block_pattern & const_empty_block_mask_420[0][y][x]) { + + struct pipe_ycbcr_block *stream = surface->ycbcr[0].stream; + stream->x = xvmc_mb->x * 2 + x; + stream->y = xvmc_mb->y * 2 + y; + stream->intra = intra; + stream->coding = coding; + + memcpy(surface->ycbcr[0].buffer, blocks, BLOCK_SIZE_BYTES); + + surface->ycbcr[0].num_blocks_added++; + surface->ycbcr[0].stream++; + surface->ycbcr[0].buffer += BLOCK_SIZE_SAMPLES; + blocks += BLOCK_SIZE_SAMPLES; + } + } + } + + /* TODO: Implement 422, 444 */ + //assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); + + for (tb = 1; tb < 3; ++tb) { + if (xvmc_mb->coded_block_pattern & const_empty_block_mask_420[tb][0][0]) { + + struct pipe_ycbcr_block *stream = surface->ycbcr[tb].stream; + stream->x = xvmc_mb->x; + stream->y = xvmc_mb->y; + stream->intra = intra; + stream->coding = PIPE_MPEG12_DCT_TYPE_FRAME; + + memcpy(surface->ycbcr[tb].buffer, blocks, BLOCK_SIZE_BYTES); + + surface->ycbcr[tb].num_blocks_added++; + surface->ycbcr[tb].stream++; + surface->ycbcr[tb].buffer += BLOCK_SIZE_SAMPLES; + blocks += BLOCK_SIZE_SAMPLES; + } + } + +} + static void MacroBlocksToPipe(XvMCSurfacePrivate *surface, unsigned int xvmc_picture_structure, const XvMCMacroBlock *xvmc_mb, const XvMCBlockArray *xvmc_blocks, - unsigned int num_macroblocks, - struct pipe_mpeg12_macroblock *mb) + unsigned int num_macroblocks) { unsigned int i, j; assert(xvmc_mb); assert(xvmc_blocks); - assert(mb); assert(num_macroblocks); for (i = 0; i < num_macroblocks; ++i) { unsigned mv_pos = xvmc_mb->x + surface->mv_stride * xvmc_mb->y; unsigned mv_weights[2]; - mb->base.codec = PIPE_VIDEO_CODEC_MPEG12; - mb->mbx = xvmc_mb->x; - mb->mby = xvmc_mb->y; - - mb->dct_intra = xvmc_mb->macroblock_type & XVMC_MB_TYPE_INTRA; - mb->dct_type = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ? - PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME; - mb->cbp = xvmc_mb->coded_block_pattern; - mb->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; + UploadYcbcrBlocks(surface, xvmc_mb, xvmc_blocks); MacroBlockTypeToPipeWeights(xvmc_mb, mv_weights); @@ -176,10 +237,8 @@ MacroBlocksToPipe(XvMCSurfacePrivate *surface, j ? XVMC_SELECT_FIRST_BACKWARD : XVMC_SELECT_FIRST_FORWARD, mv_weights[j] ); - } - ++mb; ++xvmc_mb; } } @@ -189,7 +248,7 @@ unmap_and_flush_surface(XvMCSurfacePrivate *surface) { struct pipe_video_buffer *ref_frames[2]; XvMCContextPrivate *context_priv; - unsigned i; + unsigned i, num_ycbcr_blocks[3]; assert(surface); @@ -211,7 +270,10 @@ unmap_and_flush_surface(XvMCSurfacePrivate *surface) if (surface->mapped) { surface->decode_buffer->unmap(surface->decode_buffer); + for (i = 0; i < 3; ++i) + num_ycbcr_blocks[i] = surface->ycbcr[i].num_blocks_added; context_priv->decoder->flush_buffer(surface->decode_buffer, + num_ycbcr_blocks, ref_frames, surface->video_buffer, &surface->flush_fence); @@ -289,8 +351,6 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur unsigned i; - struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks]; - XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n", target_surface, past_surface, future_surface); @@ -357,6 +417,12 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur if (!target_surface_priv->mapped) { t_buffer->map(t_buffer); + for (i = 0; i < 3; ++i) { + target_surface_priv->ycbcr[i].num_blocks_added = 0; + target_surface_priv->ycbcr[i].stream = t_buffer->get_ycbcr_stream(t_buffer, i); + target_surface_priv->ycbcr[i].buffer = t_buffer->get_ycbcr_buffer(t_buffer, i); + } + for (i = 0; i < 2; ++i) { target_surface_priv->ref[i].surface = i == 0 ? past_surface : future_surface; @@ -365,12 +431,11 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur else target_surface_priv->ref[i].mv = NULL; } + target_surface_priv->mapped = 1; } - MacroBlocksToPipe(target_surface_priv, picture_structure, xvmc_mb, blocks, num_macroblocks, pipe_macroblocks); - - t_buffer->add_macroblocks(t_buffer, num_macroblocks, &pipe_macroblocks->base); + MacroBlocksToPipe(target_surface_priv, picture_structure, xvmc_mb, blocks, num_macroblocks); XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h index a85d58a519c..bdcda3bb56f 100644 --- a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h +++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h @@ -71,8 +71,13 @@ typedef struct bool mapped; // are we still mapped to memory? - unsigned mv_stride; + struct { + unsigned num_blocks_added; + struct pipe_ycbcr_block *stream; + short *buffer; + } ycbcr[3]; + unsigned mv_stride; struct { XvMCSurface *surface; struct pipe_motionvector *mv; -- 2.30.2