1848b8605Smrg/* 2848b8605Smrg * Copyright 2011 Maarten Lankhorst 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice shall be included in 12848b8605Smrg * all copies or substantial portions of the Software. 13848b8605Smrg * 14848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 21848b8605Smrg */ 22848b8605Smrg 23848b8605Smrg#include "vl/vl_decoder.h" 24848b8605Smrg#include "vl/vl_video_buffer.h" 25848b8605Smrg 26848b8605Smrg#include "nouveau_screen.h" 27848b8605Smrg#include "nouveau_context.h" 28848b8605Smrg#include "nouveau_video.h" 29848b8605Smrg 30848b8605Smrg#include "nouveau_buffer.h" 31848b8605Smrg#include "util/u_video.h" 32848b8605Smrg#include "util/u_format.h" 33848b8605Smrg#include "util/u_sampler.h" 34848b8605Smrg 35848b8605Smrgstatic int 36848b8605Smrgnouveau_vpe_init(struct nouveau_decoder *dec) { 37848b8605Smrg int ret; 38848b8605Smrg if (dec->cmds) 39848b8605Smrg return 0; 40848b8605Smrg ret = nouveau_bo_map(dec->cmd_bo, NOUVEAU_BO_RDWR, dec->client); 41848b8605Smrg if (ret) { 42848b8605Smrg debug_printf("Mapping cmd bo: %s\n", strerror(-ret)); 43848b8605Smrg return ret; 44848b8605Smrg } 45848b8605Smrg ret = nouveau_bo_map(dec->data_bo, NOUVEAU_BO_RDWR, dec->client); 46848b8605Smrg if (ret) { 47848b8605Smrg debug_printf("Mapping data bo: %s\n", strerror(-ret)); 48848b8605Smrg return ret; 49848b8605Smrg } 50848b8605Smrg dec->cmds = dec->cmd_bo->map; 51848b8605Smrg dec->data = dec->data_bo->map; 52848b8605Smrg return ret; 53848b8605Smrg} 54848b8605Smrg 55848b8605Smrgstatic void 56848b8605Smrgnouveau_vpe_synch(struct nouveau_decoder *dec) { 57848b8605Smrg struct nouveau_pushbuf *push = dec->push; 58848b8605Smrg#if 0 59848b8605Smrg if (dec->fence_map) { 60848b8605Smrg BEGIN_NV04(push, NV84_MPEG(QUERY_COUNTER), 1); 61848b8605Smrg PUSH_DATA (push, ++dec->fence_seq); 62848b8605Smrg PUSH_KICK (push); 63848b8605Smrg while (dec->fence_map[0] != dec->fence_seq) 64848b8605Smrg usleep(1000); 65848b8605Smrg } else 66848b8605Smrg#endif 67848b8605Smrg PUSH_KICK(push); 68848b8605Smrg} 69848b8605Smrg 70848b8605Smrgstatic void 71848b8605Smrgnouveau_vpe_fini(struct nouveau_decoder *dec) { 72848b8605Smrg struct nouveau_pushbuf *push = dec->push; 73848b8605Smrg if (!dec->cmds) 74848b8605Smrg return; 75848b8605Smrg 76b8e80941Smrg nouveau_pushbuf_space(push, 16, 2, 0); 77848b8605Smrg nouveau_bufctx_reset(dec->bufctx, NV31_VIDEO_BIND_CMD); 78848b8605Smrg 79848b8605Smrg#define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_CMD, NOUVEAU_BO_RD 80848b8605Smrg 81848b8605Smrg BEGIN_NV04(push, NV31_MPEG(CMD_OFFSET), 2); 82848b8605Smrg PUSH_MTHDl(push, NV31_MPEG(CMD_OFFSET), dec->cmd_bo, 0, BCTX_ARGS); 83848b8605Smrg PUSH_DATA (push, dec->ofs * 4); 84848b8605Smrg 85848b8605Smrg BEGIN_NV04(push, NV31_MPEG(DATA_OFFSET), 2); 86848b8605Smrg PUSH_MTHDl(push, NV31_MPEG(DATA_OFFSET), dec->data_bo, 0, BCTX_ARGS); 87848b8605Smrg PUSH_DATA (push, dec->data_pos * 4); 88848b8605Smrg 89848b8605Smrg#undef BCTX_ARGS 90848b8605Smrg 91848b8605Smrg if (unlikely(nouveau_pushbuf_validate(dec->push))) 92848b8605Smrg return; 93848b8605Smrg 94848b8605Smrg BEGIN_NV04(push, NV31_MPEG(EXEC), 1); 95848b8605Smrg PUSH_DATA (push, 1); 96848b8605Smrg 97848b8605Smrg nouveau_vpe_synch(dec); 98848b8605Smrg dec->ofs = dec->data_pos = dec->num_surfaces = 0; 99848b8605Smrg dec->cmds = dec->data = NULL; 100848b8605Smrg dec->current = dec->future = dec->past = 8; 101848b8605Smrg} 102848b8605Smrg 103b8e80941Smrgstatic inline void 104848b8605Smrgnouveau_vpe_mb_dct_blocks(struct nouveau_decoder *dec, const struct pipe_mpeg12_macroblock *mb) 105848b8605Smrg{ 106848b8605Smrg int cbb; 107848b8605Smrg unsigned cbp = mb->coded_block_pattern; 108848b8605Smrg short *db = mb->blocks; 109848b8605Smrg for (cbb = 0x20; cbb > 0; cbb >>= 1) { 110848b8605Smrg if (cbb & cbp) { 111848b8605Smrg int i, found = 0; 112848b8605Smrg for (i = 0; i < 64; ++i) { 113848b8605Smrg if (!db[i]) continue; 114848b8605Smrg dec->data[dec->data_pos++] = (db[i] << 16) | (i * 2); 115848b8605Smrg found = 1; 116848b8605Smrg } 117848b8605Smrg if (found) 118848b8605Smrg dec->data[dec->data_pos - 1] |= 1; 119848b8605Smrg else 120848b8605Smrg dec->data[dec->data_pos++] = 1; 121848b8605Smrg db += 64; 122848b8605Smrg } else if (mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) { 123848b8605Smrg dec->data[dec->data_pos++] = 1; 124848b8605Smrg } 125848b8605Smrg } 126848b8605Smrg} 127848b8605Smrg 128b8e80941Smrgstatic inline void 129848b8605Smrgnouveau_vpe_mb_data_blocks(struct nouveau_decoder *dec, const struct pipe_mpeg12_macroblock *mb) 130848b8605Smrg{ 131848b8605Smrg int cbb; 132848b8605Smrg unsigned cbp = mb->coded_block_pattern; 133848b8605Smrg short *db = mb->blocks; 134848b8605Smrg for (cbb = 0x20; cbb > 0; cbb >>= 1) { 135848b8605Smrg if (cbb & cbp) { 136848b8605Smrg memcpy(&dec->data[dec->data_pos], db, 128); 137848b8605Smrg dec->data_pos += 32; 138848b8605Smrg db += 64; 139848b8605Smrg } else if (mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) { 140848b8605Smrg memset(&dec->data[dec->data_pos], 0, 128); 141848b8605Smrg dec->data_pos += 32; 142848b8605Smrg } 143848b8605Smrg } 144848b8605Smrg} 145848b8605Smrg 146b8e80941Smrgstatic inline void 147848b8605Smrgnouveau_vpe_mb_dct_header(struct nouveau_decoder *dec, 148848b8605Smrg const struct pipe_mpeg12_macroblock *mb, 149848b8605Smrg bool luma) 150848b8605Smrg{ 151848b8605Smrg unsigned base_dct, cbp; 152848b8605Smrg bool intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA; 153848b8605Smrg unsigned x = mb->x * 16; 154848b8605Smrg unsigned y = luma ? mb->y * 16 : mb->y * 8; 155848b8605Smrg 156848b8605Smrg /* Setup the base dct header */ 157848b8605Smrg base_dct = dec->current << NV17_MPEG_CMD_CHROMA_MB_HEADER_SURFACE__SHIFT; 158848b8605Smrg base_dct |= NV17_MPEG_CMD_CHROMA_MB_HEADER_RUN_SINGLE; 159848b8605Smrg 160848b8605Smrg if (!(mb->x & 1)) 161848b8605Smrg base_dct |= NV17_MPEG_CMD_CHROMA_MB_HEADER_X_COORD_EVEN; 162848b8605Smrg if (intra) 163848b8605Smrg cbp = 0x3f; 164848b8605Smrg else 165848b8605Smrg cbp = mb->coded_block_pattern; 166848b8605Smrg 167848b8605Smrg if (dec->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) { 168848b8605Smrg base_dct |= NV17_MPEG_CMD_CHROMA_MB_HEADER_TYPE_FRAME; 169848b8605Smrg if (luma && mb->macroblock_modes.bits.dct_type == PIPE_MPEG12_DCT_TYPE_FIELD) 170848b8605Smrg base_dct |= NV17_MPEG_CMD_CHROMA_MB_HEADER_FRAME_DCT_TYPE_FIELD; 171848b8605Smrg } else { 172848b8605Smrg if (dec->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM) 173848b8605Smrg base_dct |= NV17_MPEG_CMD_CHROMA_MB_HEADER_FIELD_BOTTOM; 174848b8605Smrg if (!intra) 175848b8605Smrg y *= 2; 176848b8605Smrg } 177848b8605Smrg 178848b8605Smrg if (luma) { 179848b8605Smrg base_dct |= NV17_MPEG_CMD_LUMA_MB_HEADER_OP_LUMA_MB_HEADER; 180848b8605Smrg base_dct |= (cbp >> 2) << NV17_MPEG_CMD_LUMA_MB_HEADER_CBP__SHIFT; 181848b8605Smrg } else { 182848b8605Smrg base_dct |= NV17_MPEG_CMD_CHROMA_MB_HEADER_OP_CHROMA_MB_HEADER; 183848b8605Smrg base_dct |= (cbp & 3) << NV17_MPEG_CMD_CHROMA_MB_HEADER_CBP__SHIFT; 184848b8605Smrg } 185848b8605Smrg nouveau_vpe_write(dec, base_dct); 186848b8605Smrg nouveau_vpe_write(dec, NV17_MPEG_CMD_MB_COORDS_OP_MB_COORDS | 187848b8605Smrg x | (y << NV17_MPEG_CMD_MB_COORDS_Y__SHIFT)); 188848b8605Smrg} 189848b8605Smrg 190b8e80941Smrgstatic inline unsigned int 191848b8605Smrgnouveau_vpe_mb_mv_flags(bool luma, int mv_h, int mv_v, bool forward, bool first, bool vert) 192848b8605Smrg{ 193848b8605Smrg unsigned mc_header = 0; 194848b8605Smrg if (luma) 195848b8605Smrg mc_header |= NV17_MPEG_CMD_LUMA_MV_HEADER_OP_LUMA_MV_HEADER; 196848b8605Smrg else 197848b8605Smrg mc_header |= NV17_MPEG_CMD_CHROMA_MV_HEADER_OP_CHROMA_MV_HEADER; 198848b8605Smrg if (mv_h & 1) 199848b8605Smrg mc_header |= NV17_MPEG_CMD_CHROMA_MV_HEADER_X_HALF; 200848b8605Smrg if (mv_v & 1) 201848b8605Smrg mc_header |= NV17_MPEG_CMD_CHROMA_MV_HEADER_Y_HALF; 202848b8605Smrg if (!forward) 203848b8605Smrg mc_header |= NV17_MPEG_CMD_CHROMA_MV_HEADER_DIRECTION_BACKWARD; 204848b8605Smrg if (!first) 205848b8605Smrg mc_header |= NV17_MPEG_CMD_CHROMA_MV_HEADER_IDX; 206848b8605Smrg if (vert) 207848b8605Smrg mc_header |= NV17_MPEG_CMD_LUMA_MV_HEADER_FIELD_BOTTOM; 208848b8605Smrg return mc_header; 209848b8605Smrg} 210848b8605Smrg 211848b8605Smrgstatic unsigned pos(int pos, int mov, int max) { 212848b8605Smrg int ret = pos + mov; 213848b8605Smrg if (pos < 0) 214848b8605Smrg return 0; 215848b8605Smrg if (pos >= max) 216848b8605Smrg return max-1; 217848b8605Smrg return ret; 218848b8605Smrg} 219848b8605Smrg 220848b8605Smrg/* because we want -1 / 2 = -1 */ 221848b8605Smrgstatic int div_down(int val, int mult) { 222848b8605Smrg val &= ~(mult - 1); 223848b8605Smrg return val / mult; 224848b8605Smrg} 225848b8605Smrg 226848b8605Smrgstatic int div_up(int val, int mult) { 227848b8605Smrg val += mult - 1; 228848b8605Smrg return val / mult; 229848b8605Smrg} 230848b8605Smrg 231b8e80941Smrgstatic inline void 232848b8605Smrgnouveau_vpe_mb_mv(struct nouveau_decoder *dec, unsigned mc_header, 233848b8605Smrg bool luma, bool frame, bool forward, bool vert, 234848b8605Smrg int x, int y, const short motions[2], 235848b8605Smrg unsigned surface, bool first) 236848b8605Smrg{ 237848b8605Smrg unsigned mc_vector; 238848b8605Smrg int mv_horizontal = motions[0]; 239848b8605Smrg int mv_vertical = motions[1]; 240848b8605Smrg int mv2 = mc_header & NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2; 241848b8605Smrg unsigned width = dec->base.width; 242848b8605Smrg unsigned height = dec->base.height; 243848b8605Smrg if (mv2) 244848b8605Smrg mv_vertical = div_down(mv_vertical, 2); 245848b8605Smrg assert(frame); // Untested for non-frames 246848b8605Smrg if (!frame) 247848b8605Smrg height *= 2; 248848b8605Smrg 249848b8605Smrg mc_header |= surface << NV17_MPEG_CMD_CHROMA_MV_HEADER_SURFACE__SHIFT; 250848b8605Smrg if (!luma) { 251848b8605Smrg mv_vertical = div_up(mv_vertical, 2); 252848b8605Smrg mv_horizontal = div_up(mv_horizontal, 2); 253848b8605Smrg height /= 2; 254848b8605Smrg } 255848b8605Smrg mc_header |= nouveau_vpe_mb_mv_flags(luma, mv_horizontal, mv_vertical, forward, first, vert); 256848b8605Smrg nouveau_vpe_write(dec, mc_header); 257848b8605Smrg 258848b8605Smrg mc_vector = NV17_MPEG_CMD_MV_COORDS_OP_MV_COORDS; 259848b8605Smrg if (luma) 260848b8605Smrg mc_vector |= pos(x, div_down(mv_horizontal, 2), width); 261848b8605Smrg else 262848b8605Smrg mc_vector |= pos(x, mv_horizontal & ~1, width); 263848b8605Smrg if (!mv2) 264848b8605Smrg mc_vector |= pos(y, div_down(mv_vertical, 2), height) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT; 265848b8605Smrg else 266848b8605Smrg mc_vector |= pos(y, mv_vertical & ~1, height) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT; 267848b8605Smrg nouveau_vpe_write(dec, mc_vector); 268848b8605Smrg} 269848b8605Smrg 270848b8605Smrgstatic void 271848b8605Smrgnouveau_vpe_mb_mv_header(struct nouveau_decoder *dec, 272848b8605Smrg const struct pipe_mpeg12_macroblock *mb, 273848b8605Smrg bool luma) 274848b8605Smrg{ 275848b8605Smrg bool frame = dec->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME; 276848b8605Smrg unsigned base; 277848b8605Smrg bool forward, backward; 278848b8605Smrg int y, y2, x = mb->x * 16; 279848b8605Smrg if (luma) 280848b8605Smrg y = mb->y * (frame ? 16 : 32); 281848b8605Smrg else 282848b8605Smrg y = mb->y * (frame ? 8 : 16); 283848b8605Smrg if (frame) 284848b8605Smrg y2 = y; 285848b8605Smrg else 286848b8605Smrg y2 = y + (luma ? 16 : 8); 287848b8605Smrg 288848b8605Smrg forward = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD; 289848b8605Smrg backward = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD; 290848b8605Smrg assert(!forward || dec->past < 8); 291848b8605Smrg assert(!backward || dec->future < 8); 292848b8605Smrg if (frame) { 293848b8605Smrg switch (mb->macroblock_modes.bits.frame_motion_type) { 294848b8605Smrg case PIPE_MPEG12_MO_TYPE_FRAME: goto mv1; 295848b8605Smrg case PIPE_MPEG12_MO_TYPE_FIELD: goto mv2; 296848b8605Smrg case PIPE_MPEG12_MO_TYPE_DUAL_PRIME: { 297848b8605Smrg base = NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2; 298848b8605Smrg if (forward) { 299b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, true, false, 300b8e80941Smrg x, y, mb->PMV[0][0], dec->past, true); 301b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, true, true, 302b8e80941Smrg x, y2, mb->PMV[0][0], dec->past, false); 303848b8605Smrg } 304848b8605Smrg if (backward && forward) { 305b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, !forward, true, 306b8e80941Smrg x, y, mb->PMV[1][0], dec->future, true); 307b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, !forward, false, 308b8e80941Smrg x, y2, mb->PMV[1][1], dec->future, false); 309848b8605Smrg } else assert(!backward); 310848b8605Smrg break; 311848b8605Smrg } 312848b8605Smrg default: assert(0); 313848b8605Smrg } 314848b8605Smrg } else { 315848b8605Smrg switch (mb->macroblock_modes.bits.field_motion_type) { 316848b8605Smrg case PIPE_MPEG12_MO_TYPE_FIELD: goto mv1; 317848b8605Smrg case PIPE_MPEG12_MO_TYPE_16x8: goto mv2; 318848b8605Smrg case PIPE_MPEG12_MO_TYPE_DUAL_PRIME: { 319848b8605Smrg base = NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB; 320848b8605Smrg if (frame) 321848b8605Smrg base |= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME; 322848b8605Smrg if (forward) 323b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, true, 324848b8605Smrg dec->picture_structure != PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP, 325b8e80941Smrg x, y, mb->PMV[0][0], dec->past, true); 326848b8605Smrg if (backward && forward) 327b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, false, 328848b8605Smrg dec->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP, 329b8e80941Smrg x, y, mb->PMV[0][1], dec->future, true); 330848b8605Smrg else assert(!backward); 331848b8605Smrg break; 332848b8605Smrg } 333848b8605Smrg default: assert(0); 334848b8605Smrg } 335848b8605Smrg } 336848b8605Smrg return; 337848b8605Smrg 338848b8605Smrgmv1: 339848b8605Smrg base = NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB; 340848b8605Smrg if (frame) 341848b8605Smrg base |= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME; 342848b8605Smrg /* frame 16x16 */ 343848b8605Smrg if (forward) 344b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, true, false, 345b8e80941Smrg x, y, mb->PMV[0][0], dec->past, true); 346848b8605Smrg if (backward) 347b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, !forward, false, 348b8e80941Smrg x, y, mb->PMV[0][1], dec->future, true); 349848b8605Smrg return; 350848b8605Smrg 351848b8605Smrgmv2: 352848b8605Smrg base = NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2; 353848b8605Smrg if (!frame) 354848b8605Smrg base |= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB; 355848b8605Smrg if (forward) { 356b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, true, 357848b8605Smrg mb->motion_vertical_field_select & PIPE_MPEG12_FS_FIRST_FORWARD, 358b8e80941Smrg x, y, mb->PMV[0][0], dec->past, true); 359b8e80941Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, true, 360848b8605Smrg mb->motion_vertical_field_select & PIPE_MPEG12_FS_SECOND_FORWARD, 361b8e80941Smrg x, y2, mb->PMV[1][0], dec->past, false); 362848b8605Smrg } 363848b8605Smrg if (backward) { 364848b8605Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, !forward, 365848b8605Smrg mb->motion_vertical_field_select & PIPE_MPEG12_FS_FIRST_BACKWARD, 366b8e80941Smrg x, y, mb->PMV[0][1], dec->future, true); 367848b8605Smrg nouveau_vpe_mb_mv(dec, base, luma, frame, !forward, 368848b8605Smrg mb->motion_vertical_field_select & PIPE_MPEG12_FS_SECOND_BACKWARD, 369b8e80941Smrg x, y2, mb->PMV[1][1], dec->future, false); 370848b8605Smrg } 371848b8605Smrg} 372848b8605Smrg 373848b8605Smrgstatic unsigned 374848b8605Smrgnouveau_decoder_surface_index(struct nouveau_decoder *dec, 375848b8605Smrg struct pipe_video_buffer *buffer) 376848b8605Smrg{ 377848b8605Smrg struct nouveau_video_buffer *buf = (struct nouveau_video_buffer *)buffer; 378848b8605Smrg struct nouveau_pushbuf *push = dec->push; 379848b8605Smrg struct nouveau_bo *bo_y = nv04_resource(buf->resources[0])->bo; 380848b8605Smrg struct nouveau_bo *bo_c = nv04_resource(buf->resources[1])->bo; 381848b8605Smrg 382848b8605Smrg unsigned i; 383848b8605Smrg 384848b8605Smrg for (i = 0; i < dec->num_surfaces; ++i) { 385848b8605Smrg if (dec->surfaces[i] == buf) 386848b8605Smrg return i; 387848b8605Smrg } 388848b8605Smrg assert(i < 8); 389848b8605Smrg dec->surfaces[i] = buf; 390848b8605Smrg dec->num_surfaces++; 391848b8605Smrg 392848b8605Smrg nouveau_bufctx_reset(dec->bufctx, NV31_VIDEO_BIND_IMG(i)); 393848b8605Smrg 394848b8605Smrg#define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_IMG(i), NOUVEAU_BO_RDWR 395848b8605Smrg BEGIN_NV04(push, NV31_MPEG(IMAGE_Y_OFFSET(i)), 2); 396848b8605Smrg PUSH_MTHDl(push, NV31_MPEG(IMAGE_Y_OFFSET(i)), bo_y, 0, BCTX_ARGS); 397848b8605Smrg PUSH_MTHDl(push, NV31_MPEG(IMAGE_C_OFFSET(i)), bo_c, 0, BCTX_ARGS); 398848b8605Smrg#undef BCTX_ARGS 399848b8605Smrg 400848b8605Smrg return i; 401848b8605Smrg} 402848b8605Smrg 403848b8605Smrgstatic void 404848b8605Smrgnouveau_decoder_begin_frame(struct pipe_video_codec *decoder, 405848b8605Smrg struct pipe_video_buffer *target, 406848b8605Smrg struct pipe_picture_desc *picture) 407848b8605Smrg{ 408848b8605Smrg} 409848b8605Smrg 410848b8605Smrgstatic void 411848b8605Smrgnouveau_decoder_decode_macroblock(struct pipe_video_codec *decoder, 412848b8605Smrg struct pipe_video_buffer *target, 413848b8605Smrg struct pipe_picture_desc *picture, 414848b8605Smrg const struct pipe_macroblock *pipe_mb, 415848b8605Smrg unsigned num_macroblocks) 416848b8605Smrg{ 417848b8605Smrg struct nouveau_decoder *dec = (struct nouveau_decoder *)decoder; 418848b8605Smrg struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc*)picture; 419848b8605Smrg const struct pipe_mpeg12_macroblock *mb; 420848b8605Smrg unsigned i; 421848b8605Smrg assert(target->width == decoder->width); 422848b8605Smrg assert(target->height == decoder->height); 423848b8605Smrg 424848b8605Smrg dec->current = nouveau_decoder_surface_index(dec, target); 425848b8605Smrg assert(dec->current < 8); 426848b8605Smrg dec->picture_structure = desc->picture_structure; 427848b8605Smrg if (desc->ref[1]) 428848b8605Smrg dec->future = nouveau_decoder_surface_index(dec, desc->ref[1]); 429848b8605Smrg if (desc->ref[0]) 430848b8605Smrg dec->past = nouveau_decoder_surface_index(dec, desc->ref[0]); 431848b8605Smrg 432848b8605Smrg if (nouveau_vpe_init(dec)) return; 433848b8605Smrg 434848b8605Smrg /* initialize scan order */ 435848b8605Smrg nouveau_vpe_write(dec, 0x720000c0); 436848b8605Smrg nouveau_vpe_write(dec, dec->data_pos); 437848b8605Smrg 438848b8605Smrg mb = (const struct pipe_mpeg12_macroblock *)pipe_mb; 439848b8605Smrg for (i = 0; i < num_macroblocks; ++i, mb++) { 440848b8605Smrg if (mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) { 441b8e80941Smrg nouveau_vpe_mb_dct_header(dec, mb, true); 442b8e80941Smrg nouveau_vpe_mb_dct_header(dec, mb, false); 443848b8605Smrg } else { 444b8e80941Smrg nouveau_vpe_mb_mv_header(dec, mb, true); 445b8e80941Smrg nouveau_vpe_mb_dct_header(dec, mb, true); 446848b8605Smrg 447b8e80941Smrg nouveau_vpe_mb_mv_header(dec, mb, false); 448b8e80941Smrg nouveau_vpe_mb_dct_header(dec, mb, false); 449848b8605Smrg } 450848b8605Smrg if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) 451848b8605Smrg nouveau_vpe_mb_dct_blocks(dec, mb); 452848b8605Smrg else 453848b8605Smrg nouveau_vpe_mb_data_blocks(dec, mb); 454848b8605Smrg } 455848b8605Smrg} 456848b8605Smrg 457848b8605Smrgstatic void 458848b8605Smrgnouveau_decoder_end_frame(struct pipe_video_codec *decoder, 459848b8605Smrg struct pipe_video_buffer *target, 460848b8605Smrg struct pipe_picture_desc *picture) 461848b8605Smrg{ 462848b8605Smrg} 463848b8605Smrg 464848b8605Smrgstatic void 465848b8605Smrgnouveau_decoder_flush(struct pipe_video_codec *decoder) 466848b8605Smrg{ 467848b8605Smrg struct nouveau_decoder *dec = (struct nouveau_decoder *)decoder; 468848b8605Smrg if (dec->ofs) 469848b8605Smrg nouveau_vpe_fini(dec); 470848b8605Smrg} 471848b8605Smrg 472848b8605Smrgstatic void 473848b8605Smrgnouveau_decoder_destroy(struct pipe_video_codec *decoder) 474848b8605Smrg{ 475848b8605Smrg struct nouveau_decoder *dec = (struct nouveau_decoder*)decoder; 476848b8605Smrg 477848b8605Smrg if (dec->data_bo) 478848b8605Smrg nouveau_bo_ref(NULL, &dec->data_bo); 479848b8605Smrg if (dec->cmd_bo) 480848b8605Smrg nouveau_bo_ref(NULL, &dec->cmd_bo); 481848b8605Smrg if (dec->fence_bo) 482848b8605Smrg nouveau_bo_ref(NULL, &dec->fence_bo); 483848b8605Smrg 484848b8605Smrg nouveau_object_del(&dec->mpeg); 485848b8605Smrg 486848b8605Smrg if (dec->bufctx) 487848b8605Smrg nouveau_bufctx_del(&dec->bufctx); 488848b8605Smrg if (dec->push) 489848b8605Smrg nouveau_pushbuf_del(&dec->push); 490848b8605Smrg if (dec->client) 491848b8605Smrg nouveau_client_del(&dec->client); 492848b8605Smrg if (dec->chan) 493848b8605Smrg nouveau_object_del(&dec->chan); 494848b8605Smrg 495848b8605Smrg FREE(dec); 496848b8605Smrg} 497848b8605Smrg 498848b8605Smrgstatic struct pipe_video_codec * 499848b8605Smrgnouveau_create_decoder(struct pipe_context *context, 500848b8605Smrg const struct pipe_video_codec *templ, 501848b8605Smrg struct nouveau_screen *screen) 502848b8605Smrg{ 503848b8605Smrg struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; 504848b8605Smrg unsigned width = templ->width, height = templ->height; 505848b8605Smrg struct nouveau_object *mpeg = NULL; 506848b8605Smrg struct nouveau_decoder *dec; 507848b8605Smrg struct nouveau_pushbuf *push; 508848b8605Smrg int ret; 509848b8605Smrg bool is8274 = screen->device->chipset > 0x80; 510848b8605Smrg 511848b8605Smrg debug_printf("Acceleration level: %s\n", templ->entrypoint <= PIPE_VIDEO_ENTRYPOINT_BITSTREAM ? "bit": 512848b8605Smrg templ->entrypoint == PIPE_VIDEO_ENTRYPOINT_IDCT ? "IDCT" : "MC"); 513848b8605Smrg 514848b8605Smrg if (getenv("XVMC_VL")) 515848b8605Smrg goto vl; 516848b8605Smrg if (u_reduce_video_profile(templ->profile) != PIPE_VIDEO_FORMAT_MPEG12) 517848b8605Smrg goto vl; 518848b8605Smrg if (screen->device->chipset >= 0x98 && screen->device->chipset != 0xa0) 519848b8605Smrg goto vl; 520848b8605Smrg if (screen->device->chipset < 0x40) 521848b8605Smrg goto vl; 522848b8605Smrg 523848b8605Smrg dec = CALLOC_STRUCT(nouveau_decoder); 524848b8605Smrg if (!dec) 525848b8605Smrg return NULL; 526848b8605Smrg 527848b8605Smrg ret = nouveau_object_new(&screen->device->object, 0, 528848b8605Smrg NOUVEAU_FIFO_CHANNEL_CLASS, 529848b8605Smrg &nv04_data, sizeof(nv04_data), &dec->chan); 530848b8605Smrg if (ret) 531848b8605Smrg goto fail; 532848b8605Smrg ret = nouveau_client_new(screen->device, &dec->client); 533848b8605Smrg if (ret) 534848b8605Smrg goto fail; 535848b8605Smrg ret = nouveau_pushbuf_new(dec->client, dec->chan, 2, 4096, 1, &dec->push); 536848b8605Smrg if (ret) 537848b8605Smrg goto fail; 538848b8605Smrg ret = nouveau_bufctx_new(dec->client, NV31_VIDEO_BIND_COUNT, &dec->bufctx); 539848b8605Smrg if (ret) 540848b8605Smrg goto fail; 541848b8605Smrg push = dec->push; 542848b8605Smrg 543848b8605Smrg width = align(width, 64); 544848b8605Smrg height = align(height, 64); 545848b8605Smrg 546848b8605Smrg if (is8274) 547848b8605Smrg ret = nouveau_object_new(dec->chan, 0xbeef8274, NV84_MPEG_CLASS, NULL, 0, 548848b8605Smrg &mpeg); 549848b8605Smrg else 550848b8605Smrg ret = nouveau_object_new(dec->chan, 0xbeef3174, NV31_MPEG_CLASS, NULL, 0, 551848b8605Smrg &mpeg); 552848b8605Smrg if (ret < 0) { 553848b8605Smrg debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret); 554b8e80941Smrg goto fail; 555848b8605Smrg } 556848b8605Smrg 557848b8605Smrg dec->mpeg = mpeg; 558848b8605Smrg dec->base = *templ; 559848b8605Smrg dec->base.context = context; 560848b8605Smrg dec->base.width = width; 561848b8605Smrg dec->base.height = height; 562848b8605Smrg dec->base.destroy = nouveau_decoder_destroy; 563848b8605Smrg dec->base.begin_frame = nouveau_decoder_begin_frame; 564848b8605Smrg dec->base.decode_macroblock = nouveau_decoder_decode_macroblock; 565848b8605Smrg dec->base.end_frame = nouveau_decoder_end_frame; 566848b8605Smrg dec->base.flush = nouveau_decoder_flush; 567848b8605Smrg dec->screen = screen; 568848b8605Smrg 569848b8605Smrg ret = nouveau_bo_new(dec->screen->device, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 570848b8605Smrg 0, 1024 * 1024, NULL, &dec->cmd_bo); 571848b8605Smrg if (ret) 572848b8605Smrg goto fail; 573848b8605Smrg 574848b8605Smrg ret = nouveau_bo_new(dec->screen->device, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 575848b8605Smrg 0, width * height * 6, NULL, &dec->data_bo); 576848b8605Smrg if (ret) 577848b8605Smrg goto fail; 578848b8605Smrg 579848b8605Smrg /* we don't need the fence, the kernel sync's for us */ 580848b8605Smrg#if 0 581848b8605Smrg ret = nouveau_bo_new(dec->screen->device, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 582848b8605Smrg 0, 4096, NULL, &dec->fence_bo); 583848b8605Smrg if (ret) 584848b8605Smrg goto fail; 585848b8605Smrg nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, NULL); 586848b8605Smrg dec->fence_map = dec->fence_bo->map; 587848b8605Smrg dec->fence_map[0] = 0; 588848b8605Smrg#endif 589848b8605Smrg 590848b8605Smrg nouveau_pushbuf_bufctx(dec->push, dec->bufctx); 591848b8605Smrg nouveau_pushbuf_space(push, 32, 4, 0); 592848b8605Smrg 593848b8605Smrg BEGIN_NV04(push, SUBC_MPEG(NV01_SUBCHAN_OBJECT), 1); 594848b8605Smrg PUSH_DATA (push, dec->mpeg->handle); 595848b8605Smrg 596848b8605Smrg BEGIN_NV04(push, NV31_MPEG(DMA_CMD), 1); 597848b8605Smrg PUSH_DATA (push, nv04_data.gart); 598848b8605Smrg 599848b8605Smrg BEGIN_NV04(push, NV31_MPEG(DMA_DATA), 1); 600848b8605Smrg PUSH_DATA (push, nv04_data.gart); 601848b8605Smrg 602848b8605Smrg BEGIN_NV04(push, NV31_MPEG(DMA_IMAGE), 1); 603848b8605Smrg PUSH_DATA (push, nv04_data.vram); 604848b8605Smrg 605848b8605Smrg BEGIN_NV04(push, NV31_MPEG(PITCH), 2); 606848b8605Smrg PUSH_DATA (push, width | NV31_MPEG_PITCH_UNK); 607848b8605Smrg PUSH_DATA (push, (height << NV31_MPEG_SIZE_H__SHIFT) | width); 608848b8605Smrg 609848b8605Smrg BEGIN_NV04(push, NV31_MPEG(FORMAT), 2); 610848b8605Smrg PUSH_DATA (push, 0); 611848b8605Smrg switch (templ->entrypoint) { 612848b8605Smrg case PIPE_VIDEO_ENTRYPOINT_IDCT: PUSH_DATA (push, 1); break; 613848b8605Smrg case PIPE_VIDEO_ENTRYPOINT_MC: PUSH_DATA (push, 0); break; 614848b8605Smrg default: assert(0); 615848b8605Smrg } 616848b8605Smrg 617848b8605Smrg if (is8274) { 618848b8605Smrg BEGIN_NV04(push, NV84_MPEG(DMA_QUERY), 1); 619848b8605Smrg PUSH_DATA (push, nv04_data.vram); 620848b8605Smrg#if 0 621848b8605Smrg BEGIN_NV04(push, NV84_MPEG(QUERY_OFFSET), 2); 622848b8605Smrg PUSH_DATA (push, dec->fence_bo->offset); 623848b8605Smrg PUSH_DATA (push, dec->fence_seq); 624848b8605Smrg#endif 625848b8605Smrg } 626848b8605Smrg 627848b8605Smrg ret = nouveau_vpe_init(dec); 628848b8605Smrg if (ret) 629848b8605Smrg goto fail; 630848b8605Smrg nouveau_vpe_fini(dec); 631848b8605Smrg return &dec->base; 632848b8605Smrg 633848b8605Smrgfail: 634848b8605Smrg nouveau_decoder_destroy(&dec->base); 635848b8605Smrg return NULL; 636848b8605Smrg 637848b8605Smrgvl: 638848b8605Smrg debug_printf("Using g3dvl renderer\n"); 639848b8605Smrg return vl_create_decoder(context, templ); 640848b8605Smrg} 641848b8605Smrg 642848b8605Smrgstatic struct pipe_sampler_view ** 643848b8605Smrgnouveau_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer) 644848b8605Smrg{ 645848b8605Smrg struct nouveau_video_buffer *buf = (struct nouveau_video_buffer *)buffer; 646848b8605Smrg struct pipe_sampler_view sv_templ; 647848b8605Smrg struct pipe_context *pipe; 648848b8605Smrg unsigned i; 649848b8605Smrg 650848b8605Smrg assert(buf); 651848b8605Smrg 652848b8605Smrg pipe = buf->base.context; 653848b8605Smrg 654848b8605Smrg for (i = 0; i < buf->num_planes; ++i ) { 655848b8605Smrg if (!buf->sampler_view_planes[i]) { 656848b8605Smrg memset(&sv_templ, 0, sizeof(sv_templ)); 657848b8605Smrg u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format); 658848b8605Smrg 659848b8605Smrg if (util_format_get_nr_components(buf->resources[i]->format) == 1) 660b8e80941Smrg sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_X; 661848b8605Smrg 662848b8605Smrg buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ); 663848b8605Smrg if (!buf->sampler_view_planes[i]) 664848b8605Smrg goto error; 665848b8605Smrg } 666848b8605Smrg } 667848b8605Smrg 668848b8605Smrg return buf->sampler_view_planes; 669848b8605Smrg 670848b8605Smrgerror: 671848b8605Smrg for (i = 0; i < buf->num_planes; ++i ) 672848b8605Smrg pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL); 673848b8605Smrg 674848b8605Smrg return NULL; 675848b8605Smrg} 676848b8605Smrg 677848b8605Smrgstatic struct pipe_sampler_view ** 678848b8605Smrgnouveau_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer) 679848b8605Smrg{ 680848b8605Smrg struct nouveau_video_buffer *buf = (struct nouveau_video_buffer *)buffer; 681848b8605Smrg struct pipe_sampler_view sv_templ; 682848b8605Smrg struct pipe_context *pipe; 683848b8605Smrg unsigned i, j, component; 684848b8605Smrg 685848b8605Smrg assert(buf); 686848b8605Smrg 687848b8605Smrg pipe = buf->base.context; 688848b8605Smrg 689848b8605Smrg for (component = 0, i = 0; i < buf->num_planes; ++i ) { 690848b8605Smrg unsigned nr_components = util_format_get_nr_components(buf->resources[i]->format); 691848b8605Smrg 692848b8605Smrg for (j = 0; j < nr_components; ++j, ++component) { 693848b8605Smrg assert(component < VL_NUM_COMPONENTS); 694848b8605Smrg 695848b8605Smrg if (!buf->sampler_view_components[component]) { 696848b8605Smrg memset(&sv_templ, 0, sizeof(sv_templ)); 697848b8605Smrg u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format); 698b8e80941Smrg sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_X + j; 699b8e80941Smrg sv_templ.swizzle_a = PIPE_SWIZZLE_1; 700848b8605Smrg buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ); 701848b8605Smrg if (!buf->sampler_view_components[component]) 702848b8605Smrg goto error; 703848b8605Smrg } 704848b8605Smrg } 705848b8605Smrg } 706848b8605Smrg 707848b8605Smrg return buf->sampler_view_components; 708848b8605Smrg 709848b8605Smrgerror: 710848b8605Smrg for (i = 0; i < 3; ++i ) 711848b8605Smrg pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); 712848b8605Smrg 713848b8605Smrg return NULL; 714848b8605Smrg} 715848b8605Smrg 716848b8605Smrgstatic struct pipe_surface ** 717848b8605Smrgnouveau_video_buffer_surfaces(struct pipe_video_buffer *buffer) 718848b8605Smrg{ 719848b8605Smrg struct nouveau_video_buffer *buf = (struct nouveau_video_buffer *)buffer; 720848b8605Smrg struct pipe_surface surf_templ; 721848b8605Smrg struct pipe_context *pipe; 722848b8605Smrg unsigned i; 723848b8605Smrg 724848b8605Smrg assert(buf); 725848b8605Smrg 726848b8605Smrg pipe = buf->base.context; 727848b8605Smrg 728848b8605Smrg for (i = 0; i < buf->num_planes; ++i ) { 729848b8605Smrg if (!buf->surfaces[i]) { 730848b8605Smrg memset(&surf_templ, 0, sizeof(surf_templ)); 731848b8605Smrg surf_templ.format = buf->resources[i]->format; 732848b8605Smrg buf->surfaces[i] = pipe->create_surface(pipe, buf->resources[i], &surf_templ); 733848b8605Smrg if (!buf->surfaces[i]) 734848b8605Smrg goto error; 735848b8605Smrg } 736848b8605Smrg } 737848b8605Smrg 738848b8605Smrg return buf->surfaces; 739848b8605Smrg 740848b8605Smrgerror: 741848b8605Smrg for (i = 0; i < buf->num_planes; ++i ) 742848b8605Smrg pipe_surface_reference(&buf->surfaces[i], NULL); 743848b8605Smrg 744848b8605Smrg return NULL; 745848b8605Smrg} 746848b8605Smrg 747848b8605Smrgstatic void 748848b8605Smrgnouveau_video_buffer_destroy(struct pipe_video_buffer *buffer) 749848b8605Smrg{ 750848b8605Smrg struct nouveau_video_buffer *buf = (struct nouveau_video_buffer *)buffer; 751848b8605Smrg unsigned i; 752848b8605Smrg 753848b8605Smrg assert(buf); 754848b8605Smrg 755848b8605Smrg for (i = 0; i < buf->num_planes; ++i) { 756848b8605Smrg pipe_surface_reference(&buf->surfaces[i], NULL); 757848b8605Smrg pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL); 758848b8605Smrg pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); 759848b8605Smrg pipe_resource_reference(&buf->resources[i], NULL); 760848b8605Smrg } 761848b8605Smrg for (;i < 3;++i) 762848b8605Smrg pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); 763848b8605Smrg 764848b8605Smrg FREE(buffer); 765848b8605Smrg} 766848b8605Smrg 767848b8605Smrgstatic struct pipe_video_buffer * 768848b8605Smrgnouveau_video_buffer_create(struct pipe_context *pipe, 769848b8605Smrg struct nouveau_screen *screen, 770848b8605Smrg const struct pipe_video_buffer *templat) 771848b8605Smrg{ 772848b8605Smrg struct nouveau_video_buffer *buffer; 773848b8605Smrg struct pipe_resource templ; 774848b8605Smrg unsigned width, height; 775848b8605Smrg 776848b8605Smrg /* Only do a linear surface when a hardware decoder is used 777848b8605Smrg * hardware decoder is only supported on some chipsets 778848b8605Smrg * and it only supports the NV12 format 779848b8605Smrg */ 780848b8605Smrg if (templat->buffer_format != PIPE_FORMAT_NV12 || getenv("XVMC_VL") || 781848b8605Smrg (screen->device->chipset >= 0x98 && screen->device->chipset != 0xa0) || 782848b8605Smrg screen->device->chipset < 0x40) 783848b8605Smrg return vl_video_buffer_create(pipe, templat); 784848b8605Smrg 785848b8605Smrg assert(templat->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); 786848b8605Smrg width = align(templat->width, 64); 787848b8605Smrg height = align(templat->height, 64); 788848b8605Smrg 789848b8605Smrg buffer = CALLOC_STRUCT(nouveau_video_buffer); 790848b8605Smrg if (!buffer) 791848b8605Smrg return NULL; 792848b8605Smrg 793848b8605Smrg buffer->base.context = pipe; 794848b8605Smrg buffer->base.destroy = nouveau_video_buffer_destroy; 795848b8605Smrg buffer->base.get_sampler_view_planes = nouveau_video_buffer_sampler_view_planes; 796848b8605Smrg buffer->base.get_sampler_view_components = nouveau_video_buffer_sampler_view_components; 797848b8605Smrg buffer->base.get_surfaces = nouveau_video_buffer_surfaces; 798848b8605Smrg buffer->base.chroma_format = templat->chroma_format; 799848b8605Smrg buffer->base.buffer_format = templat->buffer_format; 800848b8605Smrg buffer->base.width = width; 801848b8605Smrg buffer->base.height = height; 802848b8605Smrg buffer->num_planes = 2; 803848b8605Smrg 804848b8605Smrg memset(&templ, 0, sizeof(templ)); 805848b8605Smrg templ.target = PIPE_TEXTURE_2D; 806848b8605Smrg templ.format = PIPE_FORMAT_R8_UNORM; 807848b8605Smrg templ.width0 = width; 808848b8605Smrg templ.height0 = height; 809848b8605Smrg templ.depth0 = 1; 810848b8605Smrg templ.array_size = 1; 811848b8605Smrg templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 812848b8605Smrg templ.usage = PIPE_USAGE_DEFAULT; 813848b8605Smrg templ.flags = NOUVEAU_RESOURCE_FLAG_LINEAR; 814848b8605Smrg 815848b8605Smrg buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ); 816848b8605Smrg if (!buffer->resources[0]) 817848b8605Smrg goto error; 818848b8605Smrg templ.width0 /= 2; 819848b8605Smrg templ.height0 /= 2; 820848b8605Smrg templ.format = PIPE_FORMAT_R8G8_UNORM; 821848b8605Smrg buffer->resources[1] = pipe->screen->resource_create(pipe->screen, &templ); 822848b8605Smrg if (!buffer->resources[1]) 823848b8605Smrg goto error; 824848b8605Smrg return &buffer->base; 825848b8605Smrg 826848b8605Smrgerror: 827848b8605Smrg nouveau_video_buffer_destroy(&buffer->base); 828848b8605Smrg return NULL; 829848b8605Smrg} 830848b8605Smrg 831848b8605Smrgstatic int 832848b8605Smrgnouveau_screen_get_video_param(struct pipe_screen *pscreen, 833848b8605Smrg enum pipe_video_profile profile, 834b8e80941Smrg enum pipe_video_entrypoint entrypoint, 835848b8605Smrg enum pipe_video_cap param) 836848b8605Smrg{ 837848b8605Smrg switch (param) { 838848b8605Smrg case PIPE_VIDEO_CAP_SUPPORTED: 839848b8605Smrg return entrypoint >= PIPE_VIDEO_ENTRYPOINT_IDCT && 840848b8605Smrg u_reduce_video_profile(profile) == PIPE_VIDEO_FORMAT_MPEG12; 841848b8605Smrg case PIPE_VIDEO_CAP_NPOT_TEXTURES: 842848b8605Smrg return 1; 843848b8605Smrg case PIPE_VIDEO_CAP_MAX_WIDTH: 844848b8605Smrg case PIPE_VIDEO_CAP_MAX_HEIGHT: 845848b8605Smrg return vl_video_buffer_max_size(pscreen); 846848b8605Smrg case PIPE_VIDEO_CAP_PREFERED_FORMAT: 847848b8605Smrg return PIPE_FORMAT_NV12; 848848b8605Smrg case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 849848b8605Smrg return false; 850848b8605Smrg case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 851848b8605Smrg return false; 852848b8605Smrg case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 853848b8605Smrg return true; 854848b8605Smrg case PIPE_VIDEO_CAP_MAX_LEVEL: 855848b8605Smrg return vl_level_supported(pscreen, profile); 856848b8605Smrg default: 857848b8605Smrg debug_printf("unknown video param: %d\n", param); 858848b8605Smrg return 0; 859848b8605Smrg } 860848b8605Smrg} 861848b8605Smrg 862848b8605Smrgvoid 863848b8605Smrgnouveau_screen_init_vdec(struct nouveau_screen *screen) 864848b8605Smrg{ 865848b8605Smrg screen->base.get_video_param = nouveau_screen_get_video_param; 866848b8605Smrg screen->base.is_video_format_supported = vl_video_buffer_is_format_supported; 867848b8605Smrg} 868848b8605Smrg 869848b8605Smrgstatic struct pipe_video_codec * 870848b8605Smrgnouveau_context_create_decoder(struct pipe_context *context, 871848b8605Smrg const struct pipe_video_codec *templ) 872848b8605Smrg{ 873848b8605Smrg struct nouveau_screen *screen = nouveau_context(context)->screen; 874848b8605Smrg return nouveau_create_decoder(context, templ, screen); 875848b8605Smrg} 876848b8605Smrg 877848b8605Smrgstatic struct pipe_video_buffer * 878848b8605Smrgnouveau_context_video_buffer_create(struct pipe_context *pipe, 879848b8605Smrg const struct pipe_video_buffer *templat) 880848b8605Smrg{ 881848b8605Smrg struct nouveau_screen *screen = nouveau_context(pipe)->screen; 882848b8605Smrg return nouveau_video_buffer_create(pipe, screen, templat); 883848b8605Smrg} 884848b8605Smrg 885848b8605Smrgvoid 886848b8605Smrgnouveau_context_init_vdec(struct nouveau_context *nv) 887848b8605Smrg{ 888848b8605Smrg nv->pipe.create_video_codec = nouveau_context_create_decoder; 889848b8605Smrg nv->pipe.create_video_buffer = nouveau_context_video_buffer_create; 890848b8605Smrg} 891