~emersion/go-drm

ref: 8e5be5ed85406cb0f3e906d4d6aaa3bae5a2452b go-drm/fourcc.go -rw-r--r-- 2.8 KiB
8e5be5edSimon Ser Parse ARM modifiers a month ago
                                                                                
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package drm

//go:generate ./fourcc.py

import (
	"fmt"
	"strings"
)

type Format uint32

func (f Format) Name() string {
	if name := f.str(); name != "" {
		return name
	}
	return "unknown"
}

func (f Format) String() string {
	return fmt.Sprintf("%s (0x%X)", f.Name(), uint32(f))
}

type ModifierVendor uint8

func (vendor ModifierVendor) String() string {
	if name := vendor.str(); name != "" {
		return name
	}
	return "unknown"
}

type Modifier uint64

func (mod Modifier) Vendor() ModifierVendor {
	return ModifierVendor(mod >> 56)
}

func (mod Modifier) Name() string {
	var name string
	switch mod.Vendor() {
	case ModifierVendorNVIDIA:
		name = modifierNameNVIDIA(uint64(mod))
	case ModifierVendorARM:
		name = modifierNameARM(uint64(mod))
	}
	if name != "" {
		return name
	}

	if name := mod.str(); name != "" {
		return name
	}
	if vendor := mod.Vendor().str(); vendor != "" {
		return fmt.Sprintf("%s(unknown)", strings.ToUpper(vendor))
	}
	return "unknown"
}

func (mod Modifier) String() string {
	return fmt.Sprintf("%s (0x%X)", mod.Name(), uint64(mod))
}

func modifierNameNVIDIA(mod uint64) string {
	if mod&0x10 == 0 {
		return ""
	}

	h := mod & 0xF
	k := (mod >> 12) & 0xFF
	g := (mod >> 20) & 0x3
	s := (mod >> 22) & 0x1
	c := (mod >> 23) & 0x7

	return fmt.Sprintf("NVIDIA_BLOCK_LINEAR_2D(h=%v, k=%v, g=%v, s=%v, c=%v)", h, k, g, s, c)
}

type (
	armModifierType uint64
	armAFBC         uint64
)

func modifierNameARM(mod uint64) string {
	typ := armModifierType((mod >> 52) & 0xF)
	value := mod & 0x000FFFFFFFFFFFFF

	switch typ {
	case armModifierTypeAFBC:
		blockSize := armAFBC(value) & armAFBC_BLOCK_SIZE_MASK

		props := []string{
			fmt.Sprintf("BLOCK_SIZE = %v", armAFBCBlockSizeStr(blockSize)),
		}

		if armAFBC(value)&armAFBC_YTR != 0 {
			props = append(props, "YTR")
		}
		if armAFBC(value)&armAFBC_SPLIT != 0 {
			props = append(props, "SPLIT")
		}
		if armAFBC(value)&armAFBC_SPARSE != 0 {
			props = append(props, "SPARSE")
		}
		if armAFBC(value)&armAFBC_CBR != 0 {
			props = append(props, "CBR")
		}
		if armAFBC(value)&armAFBC_TILED != 0 {
			props = append(props, "TILED")
		}
		if armAFBC(value)&armAFBC_SC != 0 {
			props = append(props, "SC")
		}
		if armAFBC(value)&armAFBC_DB != 0 {
			props = append(props, "DB")
		}
		if armAFBC(value)&armAFBC_BCH != 0 {
			props = append(props, "BCH")
		}
		if armAFBC(value)&armAFBC_USM != 0 {
			props = append(props, "USM")
		}

		return fmt.Sprintf("ARM_AFBC(%v)", strings.Join(props, ", "))
	case armModifierTypeMISC:
		// Simple modifiers handled by the fallback path
		return ""
	default:
		return ""
	}
}

func armAFBCBlockSizeStr(blockSize armAFBC) string {
	switch blockSize {
	case armAFBC_BLOCK_SIZE_16x16:
		return "16x16"
	case armAFBC_BLOCK_SIZE_32x8:
		return "32x8"
	case armAFBC_BLOCK_SIZE_64x4:
		return "64x4"
	case armAFBC_BLOCK_SIZE_32x8_64x4:
		return "32x8_64x4"
	default:
		return "unknown"
	}
}