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