Commit 8315daf7 authored by Rupert Swarbrick's avatar Rupert Swarbrick Committed by Debargha Mukherjee

Correct has_bottom_left calculation for mixed vertical partitions

This patch regenerates the orders tables and generates both the normal
ones and also those for vertical partitions. I've added a long comment
above the definition of orders[] that explains how they work (there's
no change, but it took me a while to understand, so it's probably a
good thing to document). I've also slightly changed when we use the
orders_vert tables: they are now used for both PARTITION_VERT_A and
PARTITION_VERT_B.

The patch also removes the #if around the partition argument to
has_top_right and adds it to has_bottom_left. (I could have put it
inside an #if, but I shouldn't imagine there's any measurable
performance cost and the code is cleaner this way).

The tables were regenerated with a Haskell script which I've included
at the bottom of the commit message (so the next person doesn't have
to write it from scratch yet again). The output looks reasonably
clean, but clang-format does change it somewhat so you need to run
that afterwards. The tables are also output in a different order, so
you'll need to clean that up by hand too.

-- orders.hs: Print tables to stdout by calling printOrders

import Data.Foldable
import Data.List (findIndex)
import Data.Maybe
import System.Environment
import Text.Printf
import Text.Read

data Block = Block { lbw :: Int, lbh :: Int, vert :: Bool }

minLogBlockSize :: Bool -> Int
minLogBlockSize v = if v then 3 else 2

maxLogBlockSize = 7 :: Int

-- This code generates the inverse of what we want: a mapping from visit order
-- to raster order. That is, element i of the list will be the raster index of
-- the block that we visit at step i.
vrSplit :: Block -> Int -> Int -> Int -> [Int]
vrSplit b stride lsz off
  -- PARTITION_NONE
  | lbw b >= lsz && lbh b >= lsz = [off]
  -- Some form of horizontal partition
  | lbw b < lsz && lbh b >= lsz =
      [off,off + 1..off + 2^(lsz - lbw b) - 1]
  -- Some form of vertical partition
  | lbw b >= lsz && lbh b < lsz =
      [off,off + stride..off + (2^(lsz - lbh b) - 1)*stride]
  -- PARTITION_VERT_*
  | vert b && lbh b + 1 == lsz && lbw b + 1 == lsz =
      [off, off + stride, off + 1, off + stride + 1]
  -- PARTITION_SPLIT
  | otherwise =
    concatMap (vrSplit b stride (lsz - 1))
    [off, off + 2^(lsz - lbw b - 1), off + 2^(lsz - lbh b - 1) * stride,
     off + 2^(lsz - lbw b - 1) + 2^(lsz - lbh b - 1) * stride]

vrOrders :: Block -> [Int]
vrOrders b = vrSplit b (2 ^ (maxLogBlockSize - lbw b)) maxLogBlockSize 0

-- A simple function to invert the bijection generated by vrOrders (it's very
-- naive, but the list isn't exactly long)
invertList :: [Int] -> [Int]
invertList is = map (\ i -> fromJust $ findIndex ((==) i) is) [0..length is - 1]

genOrders :: Block -> [Int]
genOrders = invertList . vrOrders

-- Code to print everything out in the style used in the AOM codebase
forButLast_ :: Applicative f => [a] -> (a -> f b) -> f ()
forButLast_ [] f = pure ()
forButLast_ (a : as) f = fbl a as f
  where fbl a [] f = pure ()
        fbl a (a' : as) f = f a *> fbl a' as f

numDigits :: Int -> Int
numDigits n =
  if n == 0 then 1
  else ceiling $ logBase 10 $ fromIntegral $ 1 + n

printRow :: Int -> Int -> [Int] -> Bool -> IO ()
printRow indent fw as islast = do
  { if null as then return ()
    else do
      { printf "%*s" indent ""
      ; forButLast_ as (\ a -> printf "%d,%*s" a (postDent a) "")
      ; printf "%d%s" (last as) (if islast then "\n" else ",\n") } }
  where postDent a = 1 + fw - numDigits a

printInts :: Int -> Int -> Int -> [Int] -> IO ()
printInts width indent fw [] = return ()
printInts width indent fw as =
  let (row, rest) = splitAt eltsPerLine as in
    printRow indent fw row (null rest) >> printInts width indent fw rest
  where eltsPerLine = quot (width - indent + 1) (fw + 2)

printBlockOrders :: Block -> IO ()
printBlockOrders b = do
  { printf "static const uint16_t orders_%s%dx%d[%d] = {\n"
    (if vert b then "vert_" else "")
    ((2 :: Int) ^ lbw b) ((2 :: Int) ^ lbh b) numElts
  ; printInts 79 2 intWidth (genOrders b)
  ; printf "};\n" }
  where lsz = maxLogBlockSize
        numElts = (2 :: Int) ^ (lsz - lbw b + lsz - lbh b)
        intWidth = max 1 $ ceiling $ logBase 10 $ fromIntegral (numElts - 1)

blocksForWidth :: Bool -> Int -> [Block]
blocksForWidth v lbw = map (\ lbh -> Block lbw lbh v) [minLbh..maxLbh]
  where maxLogAspectRatio = if v then 0 else 2
        minLbh = max (minLogBlockSize v) (lbw - maxLogAspectRatio)
        maxLbh = min maxLogBlockSize (lbw + maxLogAspectRatio)

blocksForV :: Bool -> [Block]
blocksForV v = concatMap (blocksForWidth v) [minLbw..maxLbw]
  where minLbw = (minLogBlockSize v)
        maxLbw = maxLogBlockSize

blocks :: [Block]
blocks = blocksForV False ++ blocksForV True

printOrders :: IO ()
printOrders = traverse_ printBlockOrders blocks

-- Ends orders.hs

BUG=aomedia:914

Change-Id: I6c53e80caa0d203cdc11f88471b6c117c633baa6
parent cf772765
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment