aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs
blob: a3eea81a2072373bed1b68dad59edb911fd63793 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using System;
using System.Diagnostics;

namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
    internal struct TileInfo
    {
        private const int MinTileWidthB64 = 4;
        private const int MaxTileWidthB64 = 64;

        public int MiRowStart, MiRowEnd;
        public int MiColStart, MiColEnd;

        public static int MiColsAlignedToSb(int nMis)
        {
            return BitUtils.AlignPowerOfTwo(nMis, Constants.MiBlockSizeLog2);
        }

        private static int GetTileOffset(int idx, int mis, int log2)
        {
            int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
            int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;

            return Math.Min(offset, mis);
        }

        public void SetRow(ref Vp9Common cm, int row)
        {
            MiRowStart = GetTileOffset(row, cm.MiRows, cm.Log2TileRows);
            MiRowEnd = GetTileOffset(row + 1, cm.MiRows, cm.Log2TileRows);
        }

        public void SetCol(ref Vp9Common cm, int col)
        {
            MiColStart = GetTileOffset(col, cm.MiCols, cm.Log2TileCols);
            MiColEnd = GetTileOffset(col + 1, cm.MiCols, cm.Log2TileCols);
        }

        public void Init(ref Vp9Common cm, int row, int col)
        {
            SetRow(ref cm, row);
            SetCol(ref cm, col);
        }

        // Checks that the given miRow, miCol and search point
        // are inside the borders of the tile.
        public readonly bool IsInside(int miCol, int miRow, int miRows, ref Position miPos)
        {
            return !(miRow + miPos.Row < 0 ||
                     miCol + miPos.Col < MiColStart ||
                     miRow + miPos.Row >= miRows ||
                     miCol + miPos.Col >= MiColEnd);
        }

        private static int GetMinLog2TileCols(int sb64Cols)
        {
            int minLog2 = 0;
            while ((MaxTileWidthB64 << minLog2) < sb64Cols)
            {
                ++minLog2;
            }

            return minLog2;
        }

        private static int GetMaxLog2TileCols(int sb64Cols)
        {
            int maxLog2 = 1;
            while ((sb64Cols >> maxLog2) >= MinTileWidthB64)
            {
                ++maxLog2;
            }

            return maxLog2 - 1;
        }

        public static void GetTileNBits(int miCols, ref int minLog2TileCols, ref int maxLog2TileCols)
        {
            int sb64Cols = MiColsAlignedToSb(miCols) >> Constants.MiBlockSizeLog2;
            minLog2TileCols = GetMinLog2TileCols(sb64Cols);
            maxLog2TileCols = GetMaxLog2TileCols(sb64Cols);
            Debug.Assert(minLog2TileCols <= maxLog2TileCols);
        }
    }
}