• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
2 /**********************************************************
3  *
4  * Copyright (c) 2024 Broadcom.
5  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
6  *
7  **********************************************************/
8 #ifndef VMW_SURF_DEFS_H
9 #define VMW_SURF_DEFS_H
10 
11 #include "util/macros.h"
12 #include "svga3d_surfacedefs.h"
13 #include "svga3d_types.h"
14 
15 static inline uint32
clamped_umul32(uint32 a,uint32 b)16 clamped_umul32(uint32 a, uint32 b)
17 {
18    uint64_t tmp = (uint64_t)a * b;
19    return (tmp > (uint64_t)((uint32)-1)) ? (uint32)-1 : tmp;
20 }
21 
22 static inline uint32
clamped_uadd32(uint32 a,uint32 b)23 clamped_uadd32(uint32 a, uint32 b)
24 {
25    uint32 c = a + b;
26    if (c < a || c < b) {
27       return MAX_UINT32;
28    }
29    return c;
30 }
31 
32 static inline const struct SVGA3dSurfaceDesc *
vmw_surf_get_desc(SVGA3dSurfaceFormat format)33 vmw_surf_get_desc(SVGA3dSurfaceFormat format)
34 {
35    if (format < ARRAY_SIZE(g_SVGA3dSurfaceDescs))
36       return &g_SVGA3dSurfaceDescs[format];
37 
38    return &g_SVGA3dSurfaceDescs[SVGA3D_FORMAT_INVALID];
39 }
40 
41 static inline SVGA3dSize
vmw_surf_get_mip_size(SVGA3dSize base_level,uint32 mip_level)42 vmw_surf_get_mip_size(SVGA3dSize base_level, uint32 mip_level)
43 {
44    SVGA3dSize size;
45 
46    size.width = MAX2(base_level.width >> mip_level, 1);
47    size.height = MAX2(base_level.height >> mip_level, 1);
48    size.depth = MAX2(base_level.depth >> mip_level, 1);
49    return size;
50 }
51 
52 static inline void
vmw_surf_get_size_in_blocks(const struct SVGA3dSurfaceDesc * desc,const SVGA3dSize * pixel_size,SVGA3dSize * block_size)53 vmw_surf_get_size_in_blocks(const struct SVGA3dSurfaceDesc *desc,
54                             const SVGA3dSize *pixel_size,
55                             SVGA3dSize *block_size)
56 {
57    block_size->width = DIV_ROUND_UP(pixel_size->width, desc->blockSize.width);
58    block_size->height =
59       DIV_ROUND_UP(pixel_size->height, desc->blockSize.height);
60    block_size->depth = DIV_ROUND_UP(pixel_size->depth, desc->blockSize.depth);
61 }
62 
63 static inline bool
vmw_surf_is_planar_surface(const struct SVGA3dSurfaceDesc * desc)64 vmw_surf_is_planar_surface(const struct SVGA3dSurfaceDesc *desc)
65 {
66    return (desc->blockDesc & SVGA3DBLOCKDESC_PLANAR_YUV) != 0;
67 }
68 
69 static inline uint32
vmw_surf_calculate_pitch(const struct SVGA3dSurfaceDesc * desc,const SVGA3dSize * size)70 vmw_surf_calculate_pitch(const struct SVGA3dSurfaceDesc *desc,
71                          const SVGA3dSize *size)
72 {
73    uint32 pitch;
74    SVGA3dSize blocks;
75 
76    vmw_surf_get_size_in_blocks(desc, size, &blocks);
77 
78    pitch = blocks.width * desc->pitchBytesPerBlock;
79 
80    return pitch;
81 }
82 
83 static inline uint32
vmw_surf_get_image_buffer_size(const struct SVGA3dSurfaceDesc * desc,const SVGA3dSize * size,uint32 pitch)84 vmw_surf_get_image_buffer_size(const struct SVGA3dSurfaceDesc *desc,
85                                const SVGA3dSize *size, uint32 pitch)
86 {
87    SVGA3dSize image_blocks;
88    uint32 slice_size, total_size;
89 
90    vmw_surf_get_size_in_blocks(desc, size, &image_blocks);
91 
92    if (vmw_surf_is_planar_surface(desc)) {
93       total_size = clamped_umul32(image_blocks.width, image_blocks.height);
94       total_size = clamped_umul32(total_size, image_blocks.depth);
95       total_size = clamped_umul32(total_size, desc->bytesPerBlock);
96       return total_size;
97    }
98 
99    if (pitch == 0)
100       pitch = vmw_surf_calculate_pitch(desc, size);
101 
102    slice_size = clamped_umul32(image_blocks.height, pitch);
103    total_size = clamped_umul32(slice_size, image_blocks.depth);
104 
105    return total_size;
106 }
107 
108 static inline uint32
vmw_surf_get_serialized_size(SVGA3dSurfaceFormat format,SVGA3dSize base_level_size,uint32 num_mip_levels,uint32 num_layers)109 vmw_surf_get_serialized_size(SVGA3dSurfaceFormat format,
110                              SVGA3dSize base_level_size, uint32 num_mip_levels,
111                              uint32 num_layers)
112 {
113    const struct SVGA3dSurfaceDesc *desc = vmw_surf_get_desc(format);
114    uint64_t total_size = 0;
115    uint32 mip;
116 
117    for (mip = 0; mip < num_mip_levels; mip++) {
118       SVGA3dSize size = vmw_surf_get_mip_size(base_level_size, mip);
119       total_size += vmw_surf_get_image_buffer_size(desc, &size, 0);
120    }
121 
122    total_size *= num_layers;
123 
124    return (total_size > (uint64_t)MAX_UINT32) ? MAX_UINT32 : (uint32)total_size;
125 }
126 
127 /**
128  * vmw_surf_get_serialized_size_extended - Returns the number of bytes
129  * required for a surface with given parameters. Support for sample count.
130  *
131  */
132 static inline uint32
vmw_surf_get_serialized_size_extended(SVGA3dSurfaceFormat format,SVGA3dSize base_level_size,uint32 num_mip_levels,uint32 num_layers,uint32 num_samples)133 vmw_surf_get_serialized_size_extended(SVGA3dSurfaceFormat format,
134                                       SVGA3dSize base_level_size,
135                                       uint32 num_mip_levels, uint32 num_layers,
136                                       uint32 num_samples)
137 {
138    uint64_t total_size = vmw_surf_get_serialized_size(
139       format, base_level_size, num_mip_levels, num_layers);
140 
141    total_size *= (num_samples > 1 ? num_samples : 1);
142 
143    return (total_size > (uint64_t)MAX_UINT32) ? MAX_UINT32 : (uint32)total_size;
144 }
145 
146 static inline uint32
vmw_surf_get_image_offset(SVGA3dSurfaceFormat format,SVGA3dSize baseLevelSize,uint32 numMipLevels,uint32 layer,uint32 mip)147 vmw_surf_get_image_offset(SVGA3dSurfaceFormat format, SVGA3dSize baseLevelSize,
148                           uint32 numMipLevels, uint32 layer, uint32 mip)
149 
150 {
151    uint32 offset;
152    uint32 mipChainBytes;
153    uint32 mipChainBytesToLevel;
154    uint32 i;
155    const struct SVGA3dSurfaceDesc *desc;
156    SVGA3dSize mipSize;
157    uint32 bytes;
158 
159    desc = vmw_surf_get_desc(format);
160 
161    mipChainBytes = 0;
162    mipChainBytesToLevel = 0;
163    for (i = 0; i < numMipLevels; i++) {
164       mipSize = vmw_surf_get_mip_size(baseLevelSize, i);
165       bytes = vmw_surf_get_image_buffer_size(desc, &mipSize, 0);
166       mipChainBytes += bytes;
167       if (i < mip) {
168          mipChainBytesToLevel += bytes;
169       }
170    }
171 
172    offset = mipChainBytes * layer + mipChainBytesToLevel;
173 
174    return offset;
175 }
176 
177 /**
178  * Compute the offset (in bytes) to a pixel in an image (or volume).
179  * 'width' is the image width in pixels
180  * 'height' is the image height in pixels
181  */
182 static inline uint32
vmw_surf_get_pixel_offset(SVGA3dSurfaceFormat format,uint32 width,uint32 height,uint32 x,uint32 y,uint32 z)183 vmw_surf_get_pixel_offset(SVGA3dSurfaceFormat format, uint32 width,
184                           uint32 height, uint32 x, uint32 y, uint32 z)
185 {
186    const struct SVGA3dSurfaceDesc *desc = vmw_surf_get_desc(format);
187    const uint32 bw = desc->blockSize.width, bh = desc->blockSize.height;
188    const uint32 bd = desc->blockSize.depth;
189    const uint32 rowstride = DIV_ROUND_UP(width, bw) * desc->bytesPerBlock;
190    const uint32 imgstride = DIV_ROUND_UP(height, bh) * rowstride;
191    const uint32 offset =
192       (z / bd * imgstride + y / bh * rowstride + x / bw * desc->bytesPerBlock);
193    return offset;
194 }
195 
196 #endif /* VMW_SURF_DEFS_H */
197