spi: Do not require a completion
[cascardo/linux.git] / drivers / gpu / drm / vmwgfx / svga3d_surfacedefs.h
1 /**************************************************************************
2  *
3  * Copyright © 2008-2012 VMware, Inc., Palo Alto, CA., USA
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27
28 #ifdef __KERNEL__
29
30 #include <drm/vmwgfx_drm.h>
31 #define surf_size_struct struct drm_vmw_size
32
33 #else /* __KERNEL__ */
34
35 #ifndef ARRAY_SIZE
36 #define ARRAY_SIZE(_A) (sizeof(_A) / sizeof((_A)[0]))
37 #endif /* ARRAY_SIZE */
38
39 #define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
40 #define max_t(type, x, y)  ((x) > (y) ? (x) : (y))
41 #define surf_size_struct SVGA3dSize
42 #define u32 uint32
43
44 #endif /* __KERNEL__ */
45
46 #include "svga3d_reg.h"
47
48 /*
49  * enum svga3d_block_desc describes the active data channels in a block.
50  *
51  * There can be at-most four active channels in a block:
52  *    1. Red, bump W, luminance and depth are stored in the first channel.
53  *    2. Green, bump V and stencil are stored in the second channel.
54  *    3. Blue and bump U are stored in the third channel.
55  *    4. Alpha and bump Q are stored in the fourth channel.
56  *
57  * Block channels can be used to store compressed and buffer data:
58  *    1. For compressed formats, only the data channel is used and its size
59  *       is equal to that of a singular block in the compression scheme.
60  *    2. For buffer formats, only the data channel is used and its size is
61  *       exactly one byte in length.
62  *    3. In each case the bit depth represent the size of a singular block.
63  *
64  * Note: Compressed and IEEE formats do not use the bitMask structure.
65  */
66
67 enum svga3d_block_desc {
68         SVGA3DBLOCKDESC_NONE        = 0,         /* No channels are active */
69         SVGA3DBLOCKDESC_BLUE        = 1 << 0,    /* Block with red channel
70                                                     data */
71         SVGA3DBLOCKDESC_U           = 1 << 0,    /* Block with bump U channel
72                                                     data */
73         SVGA3DBLOCKDESC_UV_VIDEO    = 1 << 7,    /* Block with alternating video
74                                                     U and V */
75         SVGA3DBLOCKDESC_GREEN       = 1 << 1,    /* Block with green channel
76                                                     data */
77         SVGA3DBLOCKDESC_V           = 1 << 1,    /* Block with bump V channel
78                                                     data */
79         SVGA3DBLOCKDESC_STENCIL     = 1 << 1,    /* Block with a stencil
80                                                     channel */
81         SVGA3DBLOCKDESC_RED         = 1 << 2,    /* Block with blue channel
82                                                     data */
83         SVGA3DBLOCKDESC_W           = 1 << 2,    /* Block with bump W channel
84                                                     data */
85         SVGA3DBLOCKDESC_LUMINANCE   = 1 << 2,    /* Block with luminance channel
86                                                     data */
87         SVGA3DBLOCKDESC_Y           = 1 << 2,    /* Block with video luminance
88                                                     data */
89         SVGA3DBLOCKDESC_DEPTH       = 1 << 2,    /* Block with depth channel */
90         SVGA3DBLOCKDESC_ALPHA       = 1 << 3,    /* Block with an alpha
91                                                     channel */
92         SVGA3DBLOCKDESC_Q           = 1 << 3,    /* Block with bump Q channel
93                                                     data */
94         SVGA3DBLOCKDESC_BUFFER      = 1 << 4,    /* Block stores 1 byte of
95                                                     data */
96         SVGA3DBLOCKDESC_COMPRESSED  = 1 << 5,    /* Block stores n bytes of
97                                                     data depending on the
98                                                     compression method used */
99         SVGA3DBLOCKDESC_IEEE_FP     = 1 << 6,    /* Block stores data in an IEEE
100                                                     floating point
101                                                     representation in
102                                                     all channels */
103         SVGA3DBLOCKDESC_PLANAR_YUV  = 1 << 8,    /* Three separate blocks store
104                                                     data. */
105         SVGA3DBLOCKDESC_U_VIDEO     = 1 << 9,    /* Block with U video data */
106         SVGA3DBLOCKDESC_V_VIDEO     = 1 << 10,   /* Block with V video data */
107         SVGA3DBLOCKDESC_EXP         = 1 << 11,   /* Shared exponent */
108         SVGA3DBLOCKDESC_SRGB        = 1 << 12,   /* Data is in sRGB format */
109         SVGA3DBLOCKDESC_2PLANAR_YUV = 1 << 13,   /* 2 planes of Y, UV,
110                                                     e.g., NV12. */
111         SVGA3DBLOCKDESC_3PLANAR_YUV = 1 << 14,   /* 3 planes of separate
112                                                     Y, U, V, e.g., YV12. */
113
114         SVGA3DBLOCKDESC_RG         = SVGA3DBLOCKDESC_RED |
115         SVGA3DBLOCKDESC_GREEN,
116         SVGA3DBLOCKDESC_RGB        = SVGA3DBLOCKDESC_RG |
117         SVGA3DBLOCKDESC_BLUE,
118         SVGA3DBLOCKDESC_RGB_SRGB   = SVGA3DBLOCKDESC_RGB |
119         SVGA3DBLOCKDESC_SRGB,
120         SVGA3DBLOCKDESC_RGBA       = SVGA3DBLOCKDESC_RGB |
121         SVGA3DBLOCKDESC_ALPHA,
122         SVGA3DBLOCKDESC_RGBA_SRGB  = SVGA3DBLOCKDESC_RGBA |
123         SVGA3DBLOCKDESC_SRGB,
124         SVGA3DBLOCKDESC_UV         = SVGA3DBLOCKDESC_U |
125         SVGA3DBLOCKDESC_V,
126         SVGA3DBLOCKDESC_UVL        = SVGA3DBLOCKDESC_UV |
127         SVGA3DBLOCKDESC_LUMINANCE,
128         SVGA3DBLOCKDESC_UVW        = SVGA3DBLOCKDESC_UV |
129         SVGA3DBLOCKDESC_W,
130         SVGA3DBLOCKDESC_UVWA       = SVGA3DBLOCKDESC_UVW |
131         SVGA3DBLOCKDESC_ALPHA,
132         SVGA3DBLOCKDESC_UVWQ       = SVGA3DBLOCKDESC_U |
133         SVGA3DBLOCKDESC_V |
134         SVGA3DBLOCKDESC_W |
135         SVGA3DBLOCKDESC_Q,
136         SVGA3DBLOCKDESC_LA         = SVGA3DBLOCKDESC_LUMINANCE |
137         SVGA3DBLOCKDESC_ALPHA,
138         SVGA3DBLOCKDESC_R_FP       = SVGA3DBLOCKDESC_RED |
139         SVGA3DBLOCKDESC_IEEE_FP,
140         SVGA3DBLOCKDESC_RG_FP      = SVGA3DBLOCKDESC_R_FP |
141         SVGA3DBLOCKDESC_GREEN,
142         SVGA3DBLOCKDESC_RGB_FP     = SVGA3DBLOCKDESC_RG_FP |
143         SVGA3DBLOCKDESC_BLUE,
144         SVGA3DBLOCKDESC_RGBA_FP    = SVGA3DBLOCKDESC_RGB_FP |
145         SVGA3DBLOCKDESC_ALPHA,
146         SVGA3DBLOCKDESC_DS         = SVGA3DBLOCKDESC_DEPTH |
147         SVGA3DBLOCKDESC_STENCIL,
148         SVGA3DBLOCKDESC_YUV        = SVGA3DBLOCKDESC_UV_VIDEO |
149         SVGA3DBLOCKDESC_Y,
150         SVGA3DBLOCKDESC_AYUV       = SVGA3DBLOCKDESC_ALPHA |
151         SVGA3DBLOCKDESC_Y |
152         SVGA3DBLOCKDESC_U_VIDEO |
153         SVGA3DBLOCKDESC_V_VIDEO,
154         SVGA3DBLOCKDESC_RGBE       = SVGA3DBLOCKDESC_RGB |
155         SVGA3DBLOCKDESC_EXP,
156         SVGA3DBLOCKDESC_COMPRESSED_SRGB = SVGA3DBLOCKDESC_COMPRESSED |
157         SVGA3DBLOCKDESC_SRGB,
158         SVGA3DBLOCKDESC_NV12       = SVGA3DBLOCKDESC_PLANAR_YUV |
159         SVGA3DBLOCKDESC_2PLANAR_YUV,
160         SVGA3DBLOCKDESC_YV12       = SVGA3DBLOCKDESC_PLANAR_YUV |
161         SVGA3DBLOCKDESC_3PLANAR_YUV,
162 };
163
164 /*
165  * SVGA3dSurfaceDesc describes the actual pixel data.
166  *
167  * This structure provides the following information:
168  *    1. Block description.
169  *    2. Dimensions of a block in the surface.
170  *    3. Size of block in bytes.
171  *    4. Bit depth of the pixel data.
172  *    5. Channel bit depths and masks (if applicable).
173  */
174 #define SVGA3D_CHANNEL_DEF(type)                \
175         struct {                                \
176                 union {                         \
177                         type blue;              \
178                         type u;                 \
179                         type uv_video;          \
180                         type u_video;           \
181                 };                              \
182                 union {                         \
183                         type green;             \
184                         type v;                 \
185                         type stencil;           \
186                         type v_video;           \
187                 };                              \
188                 union {                         \
189                         type red;               \
190                         type w;                 \
191                         type luminance;         \
192                         type y;                 \
193                         type depth;             \
194                         type data;              \
195                 };                              \
196                 union {                         \
197                         type alpha;             \
198                         type q;                 \
199                         type exp;               \
200                 };                              \
201         }
202
203 struct svga3d_surface_desc {
204         enum svga3d_block_desc block_desc;
205         surf_size_struct block_size;
206         u32 bytes_per_block;
207         u32 pitch_bytes_per_block;
208
209         struct {
210                 u32 total;
211                 SVGA3D_CHANNEL_DEF(uint8);
212         } bit_depth;
213
214         struct {
215                 SVGA3D_CHANNEL_DEF(uint8);
216         } bit_offset;
217 };
218
219 static const struct svga3d_surface_desc svga3d_surface_descs[] = {
220         {SVGA3DBLOCKDESC_NONE,
221          {1, 1, 1},  0, 0, {0, {{0}, {0}, {0}, {0} } },
222          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_FORMAT_INVALID */
223
224         {SVGA3DBLOCKDESC_RGB,
225          {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
226          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_X8R8G8B8 */
227
228         {SVGA3DBLOCKDESC_RGBA,
229          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
230          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_A8R8G8B8 */
231
232         {SVGA3DBLOCKDESC_RGB,
233          {1, 1, 1},  2, 2, {16, {{5}, {6}, {5}, {0} } },
234          {{{0}, {5}, {11}, {0} } } },    /* SVGA3D_R5G6B5 */
235
236         {SVGA3DBLOCKDESC_RGB,
237          {1, 1, 1},  2, 2, {15, {{5}, {5}, {5}, {0} } },
238          {{{0}, {5}, {10}, {0} } } },    /* SVGA3D_X1R5G5B5 */
239
240         {SVGA3DBLOCKDESC_RGBA,
241          {1, 1, 1},  2, 2, {16, {{5}, {5}, {5}, {1} } },
242          {{{0}, {5}, {10}, {15} } } },   /* SVGA3D_A1R5G5B5 */
243
244         {SVGA3DBLOCKDESC_RGBA,
245          {1, 1, 1},  2, 2, {16, {{4}, {4}, {4}, {4} } },
246          {{{0}, {4}, {8}, {12} } } },    /* SVGA3D_A4R4G4B4 */
247
248         {SVGA3DBLOCKDESC_DEPTH,
249          {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
250          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_Z_D32 */
251
252         {SVGA3DBLOCKDESC_DEPTH,
253          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
254          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_Z_D16 */
255
256         {SVGA3DBLOCKDESC_DS,
257          {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
258          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_D24S8 */
259
260         {SVGA3DBLOCKDESC_DS,
261          {1, 1, 1},  2, 2, {16, {{0}, {1}, {15}, {0} } },
262          {{{0}, {15}, {0}, {0} } } },    /* SVGA3D_Z_D15S1 */
263
264         {SVGA3DBLOCKDESC_LUMINANCE,
265          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
266          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_LUMINANCE8 */
267
268         {SVGA3DBLOCKDESC_LA,
269          {1, 1, 1},  1, 1, {8, {{0}, {0}, {4}, {4} } },
270          {{{0}, {0}, {0}, {4} } } },     /* SVGA3D_LUMINANCE4_ALPHA4 */
271
272         {SVGA3DBLOCKDESC_LUMINANCE,
273          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
274          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_LUMINANCE16 */
275
276         {SVGA3DBLOCKDESC_LA,
277          {1, 1, 1},  2, 2, {16, {{0}, {0}, {8}, {8} } },
278          {{{0}, {0}, {0}, {8} } } },     /* SVGA3D_LUMINANCE8_ALPHA8 */
279
280         {SVGA3DBLOCKDESC_COMPRESSED,
281          {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
282          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT1 */
283
284         {SVGA3DBLOCKDESC_COMPRESSED,
285          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
286          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT2 */
287
288         {SVGA3DBLOCKDESC_COMPRESSED,
289          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
290          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT3 */
291
292         {SVGA3DBLOCKDESC_COMPRESSED,
293          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
294          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT4 */
295
296         {SVGA3DBLOCKDESC_COMPRESSED,
297          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
298          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT5 */
299
300         {SVGA3DBLOCKDESC_UV,
301          {1, 1, 1},  2, 2, {16, {{0}, {0}, {8}, {8} } },
302          {{{0}, {0}, {0}, {8} } } },     /* SVGA3D_BUMPU8V8 */
303
304         {SVGA3DBLOCKDESC_UVL,
305          {1, 1, 1},  2, 2, {16, {{5}, {5}, {6}, {0} } },
306          {{{11}, {6}, {0}, {0} } } },    /* SVGA3D_BUMPL6V5U5 */
307
308         {SVGA3DBLOCKDESC_UVL,
309          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {0} } },
310          {{{16}, {8}, {0}, {0} } } },    /* SVGA3D_BUMPX8L8V8U8 */
311
312         {SVGA3DBLOCKDESC_UVL,
313          {1, 1, 1},  3, 3, {24, {{8}, {8}, {8}, {0} } },
314          {{{16}, {8}, {0}, {0} } } },    /* SVGA3D_BUMPL8V8U8 */
315
316         {SVGA3DBLOCKDESC_RGBA_FP,
317          {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
318          {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_ARGB_S10E5 */
319
320         {SVGA3DBLOCKDESC_RGBA_FP,
321          {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
322          {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_ARGB_S23E8 */
323
324         {SVGA3DBLOCKDESC_RGBA,
325          {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
326          {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_A2R10G10B10 */
327
328         {SVGA3DBLOCKDESC_UV,
329          {1, 1, 1},  2, 2, {16, {{8}, {8}, {0}, {0} } },
330          {{{8}, {0}, {0}, {0} } } },     /* SVGA3D_V8U8 */
331
332         {SVGA3DBLOCKDESC_UVWQ,
333          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
334          {{{24}, {16}, {8}, {0} } } },   /* SVGA3D_Q8W8V8U8 */
335
336         {SVGA3DBLOCKDESC_UV,
337          {1, 1, 1},  2, 2, {16, {{8}, {8}, {0}, {0} } },
338          {{{8}, {0}, {0}, {0} } } },     /* SVGA3D_CxV8U8 */
339
340         {SVGA3DBLOCKDESC_UVL,
341          {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
342          {{{16}, {8}, {0}, {0} } } },    /* SVGA3D_X8L8V8U8 */
343
344         {SVGA3DBLOCKDESC_UVWA,
345          {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
346          {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_A2W10V10U10 */
347
348         {SVGA3DBLOCKDESC_ALPHA,
349          {1, 1, 1},  1, 1, {8, {{0}, {0}, {0}, {8} } },
350          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_ALPHA8 */
351
352         {SVGA3DBLOCKDESC_R_FP,
353          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
354          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R_S10E5 */
355
356         {SVGA3DBLOCKDESC_R_FP,
357          {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
358          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R_S23E8 */
359
360         {SVGA3DBLOCKDESC_RG_FP,
361          {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
362          {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_RG_S10E5 */
363
364         {SVGA3DBLOCKDESC_RG_FP,
365          {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
366          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_RG_S23E8 */
367
368         {SVGA3DBLOCKDESC_BUFFER,
369          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
370          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BUFFER */
371
372         {SVGA3DBLOCKDESC_DEPTH,
373          {1, 1, 1},  4, 4, {32, {{0}, {0}, {24}, {0} } },
374          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_D24X8 */
375
376         {SVGA3DBLOCKDESC_UV,
377          {1, 1, 1},  4, 4, {32, {{16}, {16}, {0}, {0} } },
378          {{{16}, {0}, {0}, {0} } } },    /* SVGA3D_V16U16 */
379
380         {SVGA3DBLOCKDESC_RG,
381          {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
382          {{{0}, {0}, {16}, {0} } } },    /* SVGA3D_G16R16 */
383
384         {SVGA3DBLOCKDESC_RGBA,
385          {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
386          {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_A16B16G16R16 */
387
388         {SVGA3DBLOCKDESC_YUV,
389          {1, 1, 1},  2, 2, {16, {{8}, {0}, {8}, {0} } },
390          {{{0}, {0}, {8}, {0} } } },     /* SVGA3D_UYVY */
391
392         {SVGA3DBLOCKDESC_YUV,
393          {1, 1, 1},  2, 2, {16, {{8}, {0}, {8}, {0} } },
394          {{{8}, {0}, {0}, {0} } } },     /* SVGA3D_YUY2 */
395
396         {SVGA3DBLOCKDESC_NV12,
397          {2, 2, 1},  6, 2, {48, {{0}, {0}, {48}, {0} } },
398          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_NV12 */
399
400         {SVGA3DBLOCKDESC_AYUV,
401          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
402          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_AYUV */
403
404         {SVGA3DBLOCKDESC_RGBA,
405          {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
406          {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_R32G32B32A32_TYPELESS */
407
408         {SVGA3DBLOCKDESC_RGBA,
409          {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
410          {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_R32G32B32A32_UINT */
411
412         {SVGA3DBLOCKDESC_UVWQ,
413          {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
414          {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_R32G32B32A32_SINT */
415
416         {SVGA3DBLOCKDESC_RGB,
417          {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
418          {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_TYPELESS */
419
420         {SVGA3DBLOCKDESC_RGB_FP,
421          {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
422          {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_FLOAT */
423
424         {SVGA3DBLOCKDESC_RGB,
425          {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
426          {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_UINT */
427
428         {SVGA3DBLOCKDESC_UVW,
429          {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
430          {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_SINT */
431
432         {SVGA3DBLOCKDESC_RGBA,
433          {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
434          {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_TYPELESS */
435
436         {SVGA3DBLOCKDESC_RGBA,
437          {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
438          {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_UINT */
439
440         {SVGA3DBLOCKDESC_UVWQ,
441          {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
442          {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_SNORM */
443
444         {SVGA3DBLOCKDESC_UVWQ,
445          {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
446          {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_SINT */
447
448         {SVGA3DBLOCKDESC_RG,
449          {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
450          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G32_TYPELESS */
451
452         {SVGA3DBLOCKDESC_RG,
453          {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
454          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G32_UINT */
455
456         {SVGA3DBLOCKDESC_UV,
457          {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
458          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G32_SINT */
459
460         {SVGA3DBLOCKDESC_RG,
461          {1, 1, 1},  8, 8, {64, {{0}, {8}, {32}, {0} } },
462          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G8X24_TYPELESS */
463
464         {SVGA3DBLOCKDESC_DS,
465          {1, 1, 1},  8, 8, {64, {{0}, {8}, {32}, {0} } },
466          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_D32_FLOAT_S8X24_UINT */
467
468         {SVGA3DBLOCKDESC_R_FP,
469          {1, 1, 1},  8, 8, {64, {{0}, {0}, {32}, {0} } },
470          {{{0}, {0}, {0}, {0} } } },    /* SVGA3D_R32_FLOAT_X8_X24_TYPELESS */
471
472         {SVGA3DBLOCKDESC_GREEN,
473          {1, 1, 1},  8, 8, {64, {{0}, {8}, {0}, {0} } },
474          {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_X32_TYPELESS_G8X24_UINT */
475
476         {SVGA3DBLOCKDESC_RGBA,
477          {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
478          {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_R10G10B10A2_TYPELESS */
479
480         {SVGA3DBLOCKDESC_RGBA,
481          {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
482          {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_R10G10B10A2_UINT */
483
484         {SVGA3DBLOCKDESC_RGB_FP,
485          {1, 1, 1},  4, 4, {32, {{10}, {11}, {11}, {0} } },
486          {{{0}, {10}, {21}, {0} } } },  /* SVGA3D_R11G11B10_FLOAT */
487
488         {SVGA3DBLOCKDESC_RGBA,
489          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
490          {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_TYPELESS */
491
492         {SVGA3DBLOCKDESC_RGBA,
493          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
494          {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_UNORM */
495
496         {SVGA3DBLOCKDESC_RGBA_SRGB,
497          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
498          {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_UNORM_SRGB */
499
500         {SVGA3DBLOCKDESC_RGBA,
501          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
502          {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_UINT */
503
504         {SVGA3DBLOCKDESC_RGBA,
505          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
506          {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_SINT */
507
508         {SVGA3DBLOCKDESC_RG,
509          {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
510          {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_R16G16_TYPELESS */
511
512         {SVGA3DBLOCKDESC_RG_FP,
513          {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
514          {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_R16G16_UINT */
515
516         {SVGA3DBLOCKDESC_UV,
517          {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
518          {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_R16G16_SINT */
519
520         {SVGA3DBLOCKDESC_RED,
521          {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
522          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R32_TYPELESS */
523
524         {SVGA3DBLOCKDESC_DEPTH,
525          {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
526          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_D32_FLOAT */
527
528         {SVGA3DBLOCKDESC_RED,
529          {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
530          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R32_UINT */
531
532         {SVGA3DBLOCKDESC_RED,
533          {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
534          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R32_SINT */
535
536         {SVGA3DBLOCKDESC_RG,
537          {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
538          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_R24G8_TYPELESS */
539
540         {SVGA3DBLOCKDESC_DS,
541          {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
542          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_D24_UNORM_S8_UINT */
543
544         {SVGA3DBLOCKDESC_RED,
545          {1, 1, 1},  4, 4, {32, {{0}, {0}, {24}, {0} } },
546          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R24_UNORM_X8_TYPELESS */
547
548         {SVGA3DBLOCKDESC_GREEN,
549          {1, 1, 1},  4, 4, {32, {{0}, {8}, {0}, {0} } },
550          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_X24_TYPELESS_G8_UINT */
551
552         {SVGA3DBLOCKDESC_RG,
553          {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
554          {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_TYPELESS */
555
556         {SVGA3DBLOCKDESC_RG,
557          {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
558          {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_UNORM */
559
560         {SVGA3DBLOCKDESC_RG,
561          {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
562          {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_UINT */
563
564         {SVGA3DBLOCKDESC_UV,
565          {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
566          {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_SINT */
567
568         {SVGA3DBLOCKDESC_RED,
569          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
570          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_TYPELESS */
571
572         {SVGA3DBLOCKDESC_RED,
573          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
574          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_UNORM */
575
576         {SVGA3DBLOCKDESC_RED,
577          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
578          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_UINT */
579
580         {SVGA3DBLOCKDESC_U,
581          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
582          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_SNORM */
583
584         {SVGA3DBLOCKDESC_U,
585          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
586          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_SINT */
587
588         {SVGA3DBLOCKDESC_RED,
589          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
590          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_TYPELESS */
591
592         {SVGA3DBLOCKDESC_RED,
593          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
594          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_UNORM */
595
596         {SVGA3DBLOCKDESC_RED,
597          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
598          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_UINT */
599
600         {SVGA3DBLOCKDESC_U,
601          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
602          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_SNORM */
603
604         {SVGA3DBLOCKDESC_U,
605          {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
606          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_SINT */
607
608         {SVGA3DBLOCKDESC_RED,
609          {8, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
610          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R1_UNORM */
611
612         {SVGA3DBLOCKDESC_RGBE,
613          {1, 1, 1},  4, 4, {32, {{9}, {9}, {9}, {5} } },
614          {{{18}, {9}, {0}, {27} } } },   /* SVGA3D_R9G9B9E5_SHAREDEXP */
615
616         {SVGA3DBLOCKDESC_RG,
617          {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
618          {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_B8G8_UNORM */
619
620         {SVGA3DBLOCKDESC_RG,
621          {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
622          {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_G8R8_G8B8_UNORM */
623
624         {SVGA3DBLOCKDESC_COMPRESSED,
625          {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
626          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC1_TYPELESS */
627
628         {SVGA3DBLOCKDESC_COMPRESSED_SRGB,
629          {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
630          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC1_UNORM_SRGB */
631
632         {SVGA3DBLOCKDESC_COMPRESSED,
633          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
634          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC2_TYPELESS */
635
636         {SVGA3DBLOCKDESC_COMPRESSED_SRGB,
637          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
638          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC2_UNORM_SRGB */
639
640         {SVGA3DBLOCKDESC_COMPRESSED,
641          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
642          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC3_TYPELESS */
643
644         {SVGA3DBLOCKDESC_COMPRESSED_SRGB,
645          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
646          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC3_UNORM_SRGB */
647
648         {SVGA3DBLOCKDESC_COMPRESSED,
649          {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
650          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC4_TYPELESS */
651
652         {SVGA3DBLOCKDESC_COMPRESSED,
653          {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
654          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC4_UNORM */
655
656         {SVGA3DBLOCKDESC_COMPRESSED,
657          {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
658          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC4_SNORM */
659
660         {SVGA3DBLOCKDESC_COMPRESSED,
661          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
662          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC5_TYPELESS */
663
664         {SVGA3DBLOCKDESC_COMPRESSED,
665          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
666          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC5_UNORM */
667
668         {SVGA3DBLOCKDESC_COMPRESSED,
669          {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
670          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC5_SNORM */
671
672         {SVGA3DBLOCKDESC_RGBA,
673          {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
674          {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_R10G10B10_XR_BIAS_A2_UNORM */
675
676         {SVGA3DBLOCKDESC_RGBA,
677          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
678          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8A8_TYPELESS */
679
680         {SVGA3DBLOCKDESC_RGBA_SRGB,
681          {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
682          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8A8_UNORM_SRGB */
683
684         {SVGA3DBLOCKDESC_RGB,
685          {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
686          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8X8_TYPELESS */
687
688         {SVGA3DBLOCKDESC_RGB_SRGB,
689          {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
690          {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8X8_UNORM_SRGB */
691
692         {SVGA3DBLOCKDESC_DEPTH,
693          {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
694          {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_Z_DF16 */
695
696         {SVGA3DBLOCKDESC_DS,
697          {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
698          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_DF24 */
699
700         {SVGA3DBLOCKDESC_DS,
701          {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
702          {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_D24S8_INT */
703 };
704
705 static inline u32 clamped_umul32(u32 a, u32 b)
706 {
707         uint64_t tmp = (uint64_t) a*b;
708         return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
709 }
710
711 static inline const struct svga3d_surface_desc *
712 svga3dsurface_get_desc(SVGA3dSurfaceFormat format)
713 {
714         if (format < ARRAY_SIZE(svga3d_surface_descs))
715                 return &svga3d_surface_descs[format];
716
717         return &svga3d_surface_descs[SVGA3D_FORMAT_INVALID];
718 }
719
720 /*
721  *----------------------------------------------------------------------
722  *
723  * svga3dsurface_get_mip_size --
724  *
725  *      Given a base level size and the mip level, compute the size of
726  *      the mip level.
727  *
728  * Results:
729  *      See above.
730  *
731  * Side effects:
732  *      None.
733  *
734  *----------------------------------------------------------------------
735  */
736
737 static inline surf_size_struct
738 svga3dsurface_get_mip_size(surf_size_struct base_level, u32 mip_level)
739 {
740         surf_size_struct size;
741
742         size.width = max_t(u32, base_level.width >> mip_level, 1);
743         size.height = max_t(u32, base_level.height >> mip_level, 1);
744         size.depth = max_t(u32, base_level.depth >> mip_level, 1);
745         return size;
746 }
747
748 static inline void
749 svga3dsurface_get_size_in_blocks(const struct svga3d_surface_desc *desc,
750                                  const surf_size_struct *pixel_size,
751                                  surf_size_struct *block_size)
752 {
753         block_size->width = DIV_ROUND_UP(pixel_size->width,
754                                          desc->block_size.width);
755         block_size->height = DIV_ROUND_UP(pixel_size->height,
756                                           desc->block_size.height);
757         block_size->depth = DIV_ROUND_UP(pixel_size->depth,
758                                          desc->block_size.depth);
759 }
760
761 static inline bool
762 svga3dsurface_is_planar_surface(const struct svga3d_surface_desc *desc)
763 {
764         return (desc->block_desc & SVGA3DBLOCKDESC_PLANAR_YUV) != 0;
765 }
766
767 static inline u32
768 svga3dsurface_calculate_pitch(const struct svga3d_surface_desc *desc,
769                               const surf_size_struct *size)
770 {
771         u32 pitch;
772         surf_size_struct blocks;
773
774         svga3dsurface_get_size_in_blocks(desc, size, &blocks);
775
776         pitch = blocks.width * desc->pitch_bytes_per_block;
777
778         return pitch;
779 }
780
781 /*
782  *-----------------------------------------------------------------------------
783  *
784  * svga3dsurface_get_image_buffer_size --
785  *
786  *      Return the number of bytes of buffer space required to store
787  *      one image of a surface, optionally using the specified pitch.
788  *
789  *      If pitch is zero, it is assumed that rows are tightly packed.
790  *
791  *      This function is overflow-safe. If the result would have
792  *      overflowed, instead we return MAX_UINT32.
793  *
794  * Results:
795  *      Byte count.
796  *
797  * Side effects:
798  *      None.
799  *
800  *-----------------------------------------------------------------------------
801  */
802
803 static inline u32
804 svga3dsurface_get_image_buffer_size(const struct svga3d_surface_desc *desc,
805                                     const surf_size_struct *size,
806                                     u32 pitch)
807 {
808         surf_size_struct image_blocks;
809         u32 slice_size, total_size;
810
811         svga3dsurface_get_size_in_blocks(desc, size, &image_blocks);
812
813         if (svga3dsurface_is_planar_surface(desc)) {
814                 total_size = clamped_umul32(image_blocks.width,
815                                             image_blocks.height);
816                 total_size = clamped_umul32(total_size, image_blocks.depth);
817                 total_size = clamped_umul32(total_size, desc->bytes_per_block);
818                 return total_size;
819         }
820
821         if (pitch == 0)
822                 pitch = svga3dsurface_calculate_pitch(desc, size);
823
824         slice_size = clamped_umul32(image_blocks.height, pitch);
825         total_size = clamped_umul32(slice_size, image_blocks.depth);
826
827         return total_size;
828 }
829
830 static inline u32
831 svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
832                                   surf_size_struct base_level_size,
833                                   u32 num_mip_levels,
834                                   bool cubemap)
835 {
836         const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
837         u32 total_size = 0;
838         u32 mip;
839
840         for (mip = 0; mip < num_mip_levels; mip++) {
841                 surf_size_struct size =
842                         svga3dsurface_get_mip_size(base_level_size, mip);
843                 total_size += svga3dsurface_get_image_buffer_size(desc,
844                                                                   &size, 0);
845         }
846
847         if (cubemap)
848                 total_size *= SVGA3D_MAX_SURFACE_FACES;
849
850         return total_size;
851 }
852
853
854 /**
855  * svga3dsurface_get_pixel_offset - Compute the offset (in bytes) to a pixel
856  * in an image (or volume).
857  *
858  * @width: The image width in pixels.
859  * @height: The image height in pixels
860  */
861 static inline u32
862 svga3dsurface_get_pixel_offset(SVGA3dSurfaceFormat format,
863                                u32 width, u32 height,
864                                u32 x, u32 y, u32 z)
865 {
866         const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
867         const u32 bw = desc->block_size.width, bh = desc->block_size.height;
868         const u32 bd = desc->block_size.depth;
869         const u32 rowstride = DIV_ROUND_UP(width, bw) * desc->bytes_per_block;
870         const u32 imgstride = DIV_ROUND_UP(height, bh) * rowstride;
871         const u32 offset = (z / bd * imgstride +
872                             y / bh * rowstride +
873                             x / bw * desc->bytes_per_block);
874         return offset;
875 }
876
877
878 static inline u32
879 svga3dsurface_get_image_offset(SVGA3dSurfaceFormat format,
880                                surf_size_struct baseLevelSize,
881                                u32 numMipLevels,
882                                u32 face,
883                                u32 mip)
884
885 {
886         u32 offset;
887         u32 mipChainBytes;
888         u32 mipChainBytesToLevel;
889         u32 i;
890         const struct svga3d_surface_desc *desc;
891         surf_size_struct mipSize;
892         u32 bytes;
893
894         desc = svga3dsurface_get_desc(format);
895
896         mipChainBytes = 0;
897         mipChainBytesToLevel = 0;
898         for (i = 0; i < numMipLevels; i++) {
899                 mipSize = svga3dsurface_get_mip_size(baseLevelSize, i);
900                 bytes = svga3dsurface_get_image_buffer_size(desc, &mipSize, 0);
901                 mipChainBytes += bytes;
902                 if (i < mip)
903                         mipChainBytesToLevel += bytes;
904         }
905
906         offset = mipChainBytes * face + mipChainBytesToLevel;
907
908         return offset;
909 }