r600_uvd.c revision 848b8605
1/************************************************************************** 2 * 3 * Copyright 2011 Advanced Micro Devices, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/* 29 * Authors: 30 * Christian König <christian.koenig@amd.com> 31 * 32 */ 33 34#include <sys/types.h> 35#include <assert.h> 36#include <errno.h> 37#include <unistd.h> 38 39#include "pipe/p_video_codec.h" 40 41#include "util/u_memory.h" 42#include "util/u_video.h" 43 44#include "vl/vl_defines.h" 45#include "vl/vl_mpeg12_decoder.h" 46 47#include "r600_pipe.h" 48#include "radeon/radeon_video.h" 49#include "radeon/radeon_uvd.h" 50#include "r600d.h" 51 52/** 53 * creates an video buffer with an UVD compatible memory layout 54 */ 55struct pipe_video_buffer *r600_video_buffer_create(struct pipe_context *pipe, 56 const struct pipe_video_buffer *tmpl) 57{ 58 struct r600_context *ctx = (struct r600_context *)pipe; 59 struct r600_texture *resources[VL_NUM_COMPONENTS] = {}; 60 struct radeon_surface* surfaces[VL_NUM_COMPONENTS] = {}; 61 struct pb_buffer **pbs[VL_NUM_COMPONENTS] = {}; 62 const enum pipe_format *resource_formats; 63 struct pipe_video_buffer template; 64 struct pipe_resource templ; 65 unsigned i, array_size; 66 67 assert(pipe); 68 69 /* first create the needed resources as "normal" textures */ 70 resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format); 71 if (!resource_formats) 72 return NULL; 73 74 array_size = tmpl->interlaced ? 2 : 1; 75 template = *tmpl; 76 template.width = align(tmpl->width, VL_MACROBLOCK_WIDTH); 77 template.height = align(tmpl->height / array_size, VL_MACROBLOCK_HEIGHT); 78 79 vl_video_buffer_template(&templ, &template, resource_formats[0], 1, array_size, PIPE_USAGE_DEFAULT, 0); 80 if (ctx->b.chip_class < EVERGREEN || tmpl->interlaced) 81 templ.bind = PIPE_BIND_LINEAR; 82 resources[0] = (struct r600_texture *) 83 pipe->screen->resource_create(pipe->screen, &templ); 84 if (!resources[0]) 85 goto error; 86 87 if (resource_formats[1] != PIPE_FORMAT_NONE) { 88 vl_video_buffer_template(&templ, &template, resource_formats[1], 1, array_size, PIPE_USAGE_DEFAULT, 1); 89 if (ctx->b.chip_class < EVERGREEN || tmpl->interlaced) 90 templ.bind = PIPE_BIND_LINEAR; 91 resources[1] = (struct r600_texture *) 92 pipe->screen->resource_create(pipe->screen, &templ); 93 if (!resources[1]) 94 goto error; 95 } 96 97 if (resource_formats[2] != PIPE_FORMAT_NONE) { 98 vl_video_buffer_template(&templ, &template, resource_formats[2], 1, array_size, PIPE_USAGE_DEFAULT, 2); 99 if (ctx->b.chip_class < EVERGREEN || tmpl->interlaced) 100 templ.bind = PIPE_BIND_LINEAR; 101 resources[2] = (struct r600_texture *) 102 pipe->screen->resource_create(pipe->screen, &templ); 103 if (!resources[2]) 104 goto error; 105 } 106 107 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 108 if (!resources[i]) 109 continue; 110 111 pbs[i] = &resources[i]->resource.buf; 112 surfaces[i] = &resources[i]->surface; 113 } 114 115 rvid_join_surfaces(ctx->b.ws, templ.bind, pbs, surfaces); 116 117 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 118 if (!resources[i]) 119 continue; 120 121 /* recreate the CS handle */ 122 resources[i]->resource.cs_buf = ctx->b.ws->buffer_get_cs_handle( 123 resources[i]->resource.buf); 124 resources[i]->resource.gpu_address = ctx->b.ws->buffer_get_virtual_address( 125 resources[i]->resource.cs_buf); 126 } 127 128 template.height *= array_size; 129 return vl_video_buffer_create_ex2(pipe, &template, (struct pipe_resource **)resources); 130 131error: 132 for (i = 0; i < VL_NUM_COMPONENTS; ++i) 133 pipe_resource_reference((struct pipe_resource **)&resources[i], NULL); 134 135 return NULL; 136} 137 138/* hw encode the number of memory banks */ 139static uint32_t eg_num_banks(uint32_t nbanks) 140{ 141 switch (nbanks) { 142 case 2: 143 return 0; 144 case 4: 145 return 1; 146 case 8: 147 default: 148 return 2; 149 case 16: 150 return 3; 151 } 152} 153 154/* set the decoding target buffer offsets */ 155static struct radeon_winsys_cs_handle* r600_uvd_set_dtb(struct ruvd_msg *msg, struct vl_video_buffer *buf) 156{ 157 struct r600_screen *rscreen = (struct r600_screen*)buf->base.context->screen; 158 struct r600_texture *luma = (struct r600_texture *)buf->resources[0]; 159 struct r600_texture *chroma = (struct r600_texture *)buf->resources[1]; 160 161 msg->body.decode.dt_field_mode = buf->base.interlaced; 162 msg->body.decode.dt_surf_tile_config |= RUVD_NUM_BANKS(eg_num_banks(rscreen->b.tiling_info.num_banks)); 163 164 ruvd_set_dt_surfaces(msg, &luma->surface, &chroma->surface); 165 166 return luma->resource.cs_buf; 167} 168 169/* create decoder */ 170struct pipe_video_codec *r600_uvd_create_decoder(struct pipe_context *context, 171 const struct pipe_video_codec *templat) 172{ 173 return ruvd_create_decoder(context, templat, r600_uvd_set_dtb); 174} 175