Warning: This file is not a C or C++ file. It does not have highlighting.
| 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ |
|---|---|
| 2 | /********************************************************** |
| 3 | * |
| 4 | * Copyright (c) 2021-2024 Broadcom. All Rights Reserved. The term |
| 5 | * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. |
| 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person |
| 8 | * obtaining a copy of this software and associated documentation |
| 9 | * files (the "Software"), to deal in the Software without |
| 10 | * restriction, including without limitation the rights to use, copy, |
| 11 | * modify, merge, publish, distribute, sublicense, and/or sell copies |
| 12 | * of the Software, and to permit persons to whom the Software is |
| 13 | * furnished to do so, subject to the following conditions: |
| 14 | * |
| 15 | * The above copyright notice and this permission notice shall be |
| 16 | * included in all copies or substantial portions of the Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 22 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 23 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 25 | * SOFTWARE. |
| 26 | * |
| 27 | **********************************************************/ |
| 28 | |
| 29 | #ifndef VMW_SURFACE_CACHE_H |
| 30 | #define VMW_SURFACE_CACHE_H |
| 31 | |
| 32 | #include "device_include/svga3d_surfacedefs.h" |
| 33 | |
| 34 | #include <drm/vmwgfx_drm.h> |
| 35 | |
| 36 | #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) ((svga3d_flags) >> 32) |
| 37 | #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \ |
| 38 | ((svga3d_flags) & ((uint64_t)U32_MAX)) |
| 39 | |
| 40 | static inline u32 clamped_umul32(u32 a, u32 b) |
| 41 | { |
| 42 | uint64_t tmp = (uint64_t) a*b; |
| 43 | return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp; |
| 44 | } |
| 45 | |
| 46 | /** |
| 47 | * vmw_surface_get_desc - Look up the appropriate SVGA3dSurfaceDesc for the |
| 48 | * given format. |
| 49 | */ |
| 50 | static inline const SVGA3dSurfaceDesc * |
| 51 | vmw_surface_get_desc(SVGA3dSurfaceFormat format) |
| 52 | { |
| 53 | if (format < ARRAY_SIZE(g_SVGA3dSurfaceDescs)) |
| 54 | return &g_SVGA3dSurfaceDescs[format]; |
| 55 | |
| 56 | return &g_SVGA3dSurfaceDescs[SVGA3D_FORMAT_INVALID]; |
| 57 | } |
| 58 | |
| 59 | /** |
| 60 | * vmw_surface_get_mip_size - Given a base level size and the mip level, |
| 61 | * compute the size of the mip level. |
| 62 | */ |
| 63 | static inline struct drm_vmw_size |
| 64 | vmw_surface_get_mip_size(struct drm_vmw_size base_level, u32 mip_level) |
| 65 | { |
| 66 | struct drm_vmw_size size = { |
| 67 | .width = max_t(u32, base_level.width >> mip_level, 1), |
| 68 | .height = max_t(u32, base_level.height >> mip_level, 1), |
| 69 | .depth = max_t(u32, base_level.depth >> mip_level, 1) |
| 70 | }; |
| 71 | |
| 72 | return size; |
| 73 | } |
| 74 | |
| 75 | static inline void |
| 76 | vmw_surface_get_size_in_blocks(const SVGA3dSurfaceDesc *desc, |
| 77 | const struct drm_vmw_size *pixel_size, |
| 78 | SVGA3dSize *block_size) |
| 79 | { |
| 80 | block_size->width = __KERNEL_DIV_ROUND_UP(pixel_size->width, |
| 81 | desc->blockSize.width); |
| 82 | block_size->height = __KERNEL_DIV_ROUND_UP(pixel_size->height, |
| 83 | desc->blockSize.height); |
| 84 | block_size->depth = __KERNEL_DIV_ROUND_UP(pixel_size->depth, |
| 85 | desc->blockSize.depth); |
| 86 | } |
| 87 | |
| 88 | static inline bool |
| 89 | vmw_surface_is_planar_surface(const SVGA3dSurfaceDesc *desc) |
| 90 | { |
| 91 | return (desc->blockDesc & SVGA3DBLOCKDESC_PLANAR_YUV) != 0; |
| 92 | } |
| 93 | |
| 94 | static inline u32 |
| 95 | vmw_surface_calculate_pitch(const SVGA3dSurfaceDesc *desc, |
| 96 | const struct drm_vmw_size *size) |
| 97 | { |
| 98 | u32 pitch; |
| 99 | SVGA3dSize blocks; |
| 100 | |
| 101 | vmw_surface_get_size_in_blocks(desc, size, &blocks); |
| 102 | |
| 103 | pitch = blocks.width * desc->pitchBytesPerBlock; |
| 104 | |
| 105 | return pitch; |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * vmw_surface_get_image_buffer_size - Calculates image buffer size. |
| 110 | * |
| 111 | * Return the number of bytes of buffer space required to store one image of a |
| 112 | * surface, optionally using the specified pitch. |
| 113 | * |
| 114 | * If pitch is zero, it is assumed that rows are tightly packed. |
| 115 | * |
| 116 | * This function is overflow-safe. If the result would have overflowed, instead |
| 117 | * we return MAX_UINT32. |
| 118 | */ |
| 119 | static inline u32 |
| 120 | vmw_surface_get_image_buffer_size(const SVGA3dSurfaceDesc *desc, |
| 121 | const struct drm_vmw_size *size, |
| 122 | u32 pitch) |
| 123 | { |
| 124 | SVGA3dSize image_blocks; |
| 125 | u32 slice_size, total_size; |
| 126 | |
| 127 | vmw_surface_get_size_in_blocks(desc, size, &image_blocks); |
| 128 | |
| 129 | if (vmw_surface_is_planar_surface(desc)) { |
| 130 | total_size = clamped_umul32(image_blocks.width, |
| 131 | image_blocks.height); |
| 132 | total_size = clamped_umul32(total_size, image_blocks.depth); |
| 133 | total_size = clamped_umul32(total_size, desc->bytesPerBlock); |
| 134 | return total_size; |
| 135 | } |
| 136 | |
| 137 | if (pitch == 0) |
| 138 | pitch = vmw_surface_calculate_pitch(desc, size); |
| 139 | |
| 140 | slice_size = clamped_umul32(image_blocks.height, pitch); |
| 141 | total_size = clamped_umul32(slice_size, image_blocks.depth); |
| 142 | |
| 143 | return total_size; |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * vmw_surface_get_serialized_size - Get the serialized size for the image. |
| 148 | */ |
| 149 | static inline u32 |
| 150 | vmw_surface_get_serialized_size(SVGA3dSurfaceFormat format, |
| 151 | struct drm_vmw_size base_level_size, |
| 152 | u32 num_mip_levels, |
| 153 | u32 num_layers) |
| 154 | { |
| 155 | const SVGA3dSurfaceDesc *desc = vmw_surface_get_desc(format); |
| 156 | u32 total_size = 0; |
| 157 | u32 mip; |
| 158 | |
| 159 | for (mip = 0; mip < num_mip_levels; mip++) { |
| 160 | struct drm_vmw_size size = |
| 161 | vmw_surface_get_mip_size(base_level_size, mip); |
| 162 | total_size += vmw_surface_get_image_buffer_size(desc, |
| 163 | &size, 0); |
| 164 | } |
| 165 | |
| 166 | return total_size * num_layers; |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * vmw_surface_get_serialized_size_extended - Returns the number of bytes |
| 171 | * required for a surface with given parameters. Support for sample count. |
| 172 | */ |
| 173 | static inline u32 |
| 174 | vmw_surface_get_serialized_size_extended(SVGA3dSurfaceFormat format, |
| 175 | struct drm_vmw_size base_level_size, |
| 176 | u32 num_mip_levels, |
| 177 | u32 num_layers, |
| 178 | u32 num_samples) |
| 179 | { |
| 180 | uint64_t total_size = |
| 181 | vmw_surface_get_serialized_size(format, |
| 182 | base_level_size, |
| 183 | num_mip_levels, |
| 184 | num_layers); |
| 185 | total_size *= max_t(u32, 1, num_samples); |
| 186 | |
| 187 | return min_t(uint64_t, total_size, (uint64_t)U32_MAX); |
| 188 | } |
| 189 | |
| 190 | /** |
| 191 | * vmw_surface_get_pixel_offset - Compute the offset (in bytes) to a pixel |
| 192 | * in an image (or volume). |
| 193 | * |
| 194 | * @width: The image width in pixels. |
| 195 | * @height: The image height in pixels |
| 196 | */ |
| 197 | static inline u32 |
| 198 | vmw_surface_get_pixel_offset(SVGA3dSurfaceFormat format, |
| 199 | u32 width, u32 height, |
| 200 | u32 x, u32 y, u32 z) |
| 201 | { |
| 202 | const SVGA3dSurfaceDesc *desc = vmw_surface_get_desc(format); |
| 203 | const u32 bw = desc->blockSize.width, bh = desc->blockSize.height; |
| 204 | const u32 bd = desc->blockSize.depth; |
| 205 | const u32 rowstride = __KERNEL_DIV_ROUND_UP(width, bw) * |
| 206 | desc->bytesPerBlock; |
| 207 | const u32 imgstride = __KERNEL_DIV_ROUND_UP(height, bh) * rowstride; |
| 208 | const u32 offset = (z / bd * imgstride + |
| 209 | y / bh * rowstride + |
| 210 | x / bw * desc->bytesPerBlock); |
| 211 | return offset; |
| 212 | } |
| 213 | |
| 214 | static inline u32 |
| 215 | vmw_surface_get_image_offset(SVGA3dSurfaceFormat format, |
| 216 | struct drm_vmw_size baseLevelSize, |
| 217 | u32 numMipLevels, |
| 218 | u32 face, |
| 219 | u32 mip) |
| 220 | |
| 221 | { |
| 222 | u32 offset; |
| 223 | u32 mipChainBytes; |
| 224 | u32 mipChainBytesToLevel; |
| 225 | u32 i; |
| 226 | const SVGA3dSurfaceDesc *desc; |
| 227 | struct drm_vmw_size mipSize; |
| 228 | u32 bytes; |
| 229 | |
| 230 | desc = vmw_surface_get_desc(format); |
| 231 | |
| 232 | mipChainBytes = 0; |
| 233 | mipChainBytesToLevel = 0; |
| 234 | for (i = 0; i < numMipLevels; i++) { |
| 235 | mipSize = vmw_surface_get_mip_size(baseLevelSize, i); |
| 236 | bytes = vmw_surface_get_image_buffer_size(desc, &mipSize, 0); |
| 237 | mipChainBytes += bytes; |
| 238 | if (i < mip) |
| 239 | mipChainBytesToLevel += bytes; |
| 240 | } |
| 241 | |
| 242 | offset = mipChainBytes * face + mipChainBytesToLevel; |
| 243 | |
| 244 | return offset; |
| 245 | } |
| 246 | |
| 247 | |
| 248 | /** |
| 249 | * vmw_surface_is_gb_screen_target_format - Is the specified format usable as |
| 250 | * a ScreenTarget? |
| 251 | * (with just the GBObjects cap-bit |
| 252 | * set) |
| 253 | * @format: format to queried |
| 254 | * |
| 255 | * RETURNS: |
| 256 | * true if queried format is valid for screen targets |
| 257 | */ |
| 258 | static inline bool |
| 259 | vmw_surface_is_gb_screen_target_format(SVGA3dSurfaceFormat format) |
| 260 | { |
| 261 | return (format == SVGA3D_X8R8G8B8 || |
| 262 | format == SVGA3D_A8R8G8B8 || |
| 263 | format == SVGA3D_R5G6B5 || |
| 264 | format == SVGA3D_X1R5G5B5 || |
| 265 | format == SVGA3D_A1R5G5B5 || |
| 266 | format == SVGA3D_P8); |
| 267 | } |
| 268 | |
| 269 | |
| 270 | /** |
| 271 | * vmw_surface_is_dx_screen_target_format - Is the specified format usable as |
| 272 | * a ScreenTarget? |
| 273 | * (with DX10 enabled) |
| 274 | * |
| 275 | * @format: format to queried |
| 276 | * |
| 277 | * Results: |
| 278 | * true if queried format is valid for screen targets |
| 279 | */ |
| 280 | static inline bool |
| 281 | vmw_surface_is_dx_screen_target_format(SVGA3dSurfaceFormat format) |
| 282 | { |
| 283 | return (format == SVGA3D_R8G8B8A8_UNORM || |
| 284 | format == SVGA3D_B8G8R8A8_UNORM || |
| 285 | format == SVGA3D_B8G8R8X8_UNORM); |
| 286 | } |
| 287 | |
| 288 | |
| 289 | /** |
| 290 | * vmw_surface_is_screen_target_format - Is the specified format usable as a |
| 291 | * ScreenTarget? |
| 292 | * (for some combination of caps) |
| 293 | * |
| 294 | * @format: format to queried |
| 295 | * |
| 296 | * Results: |
| 297 | * true if queried format is valid for screen targets |
| 298 | */ |
| 299 | static inline bool |
| 300 | vmw_surface_is_screen_target_format(SVGA3dSurfaceFormat format) |
| 301 | { |
| 302 | if (vmw_surface_is_gb_screen_target_format(format)) { |
| 303 | return true; |
| 304 | } |
| 305 | return vmw_surface_is_dx_screen_target_format(format); |
| 306 | } |
| 307 | |
| 308 | /** |
| 309 | * struct vmw_surface_mip - Mimpmap level information |
| 310 | * @bytes: Bytes required in the backing store of this mipmap level. |
| 311 | * @img_stride: Byte stride per image. |
| 312 | * @row_stride: Byte stride per block row. |
| 313 | * @size: The size of the mipmap. |
| 314 | */ |
| 315 | struct vmw_surface_mip { |
| 316 | size_t bytes; |
| 317 | size_t img_stride; |
| 318 | size_t row_stride; |
| 319 | struct drm_vmw_size size; |
| 320 | |
| 321 | }; |
| 322 | |
| 323 | /** |
| 324 | * struct vmw_surface_cache - Cached surface information |
| 325 | * @desc: Pointer to the surface descriptor |
| 326 | * @mip: Array of mipmap level information. Valid size is @num_mip_levels. |
| 327 | * @mip_chain_bytes: Bytes required in the backing store for the whole chain |
| 328 | * of mip levels. |
| 329 | * @sheet_bytes: Bytes required in the backing store for a sheet |
| 330 | * representing a single sample. |
| 331 | * @num_mip_levels: Valid size of the @mip array. Number of mipmap levels in |
| 332 | * a chain. |
| 333 | * @num_layers: Number of slices in an array texture or number of faces in |
| 334 | * a cubemap texture. |
| 335 | */ |
| 336 | struct vmw_surface_cache { |
| 337 | const SVGA3dSurfaceDesc *desc; |
| 338 | struct vmw_surface_mip mip[DRM_VMW_MAX_MIP_LEVELS]; |
| 339 | size_t mip_chain_bytes; |
| 340 | size_t sheet_bytes; |
| 341 | u32 num_mip_levels; |
| 342 | u32 num_layers; |
| 343 | }; |
| 344 | |
| 345 | /** |
| 346 | * struct vmw_surface_loc - Surface location |
| 347 | * @sheet: The multisample sheet. |
| 348 | * @sub_resource: Surface subresource. Defined as layer * num_mip_levels + |
| 349 | * mip_level. |
| 350 | * @x: X coordinate. |
| 351 | * @y: Y coordinate. |
| 352 | * @z: Z coordinate. |
| 353 | */ |
| 354 | struct vmw_surface_loc { |
| 355 | u32 sheet; |
| 356 | u32 sub_resource; |
| 357 | u32 x, y, z; |
| 358 | }; |
| 359 | |
| 360 | /** |
| 361 | * vmw_surface_subres - Compute the subresource from layer and mipmap. |
| 362 | * @cache: Surface layout data. |
| 363 | * @mip_level: The mipmap level. |
| 364 | * @layer: The surface layer (face or array slice). |
| 365 | * |
| 366 | * Return: The subresource. |
| 367 | */ |
| 368 | static inline u32 vmw_surface_subres(const struct vmw_surface_cache *cache, |
| 369 | u32 mip_level, u32 layer) |
| 370 | { |
| 371 | return cache->num_mip_levels * layer + mip_level; |
| 372 | } |
| 373 | |
| 374 | /** |
| 375 | * vmw_surface_setup_cache - Build a surface cache entry |
| 376 | * @size: The surface base level dimensions. |
| 377 | * @format: The surface format. |
| 378 | * @num_mip_levels: Number of mipmap levels. |
| 379 | * @num_layers: Number of layers. |
| 380 | * @cache: Pointer to a struct vmw_surface_cach object to be filled in. |
| 381 | * |
| 382 | * Return: Zero on success, -EINVAL on invalid surface layout. |
| 383 | */ |
| 384 | static inline int vmw_surface_setup_cache(const struct drm_vmw_size *size, |
| 385 | SVGA3dSurfaceFormat format, |
| 386 | u32 num_mip_levels, |
| 387 | u32 num_layers, |
| 388 | u32 num_samples, |
| 389 | struct vmw_surface_cache *cache) |
| 390 | { |
| 391 | const SVGA3dSurfaceDesc *desc; |
| 392 | u32 i; |
| 393 | |
| 394 | memset(cache, 0, sizeof(*cache)); |
| 395 | cache->desc = desc = vmw_surface_get_desc(format); |
| 396 | cache->num_mip_levels = num_mip_levels; |
| 397 | cache->num_layers = num_layers; |
| 398 | for (i = 0; i < cache->num_mip_levels; i++) { |
| 399 | struct vmw_surface_mip *mip = &cache->mip[i]; |
| 400 | |
| 401 | mip->size = vmw_surface_get_mip_size(*size, i); |
| 402 | mip->bytes = vmw_surface_get_image_buffer_size |
| 403 | (desc, &mip->size, 0); |
| 404 | mip->row_stride = |
| 405 | __KERNEL_DIV_ROUND_UP(mip->size.width, |
| 406 | desc->blockSize.width) * |
| 407 | desc->bytesPerBlock * num_samples; |
| 408 | if (!mip->row_stride) |
| 409 | goto invalid_dim; |
| 410 | |
| 411 | mip->img_stride = |
| 412 | __KERNEL_DIV_ROUND_UP(mip->size.height, |
| 413 | desc->blockSize.height) * |
| 414 | mip->row_stride; |
| 415 | if (!mip->img_stride) |
| 416 | goto invalid_dim; |
| 417 | |
| 418 | cache->mip_chain_bytes += mip->bytes; |
| 419 | } |
| 420 | cache->sheet_bytes = cache->mip_chain_bytes * num_layers; |
| 421 | if (!cache->sheet_bytes) |
| 422 | goto invalid_dim; |
| 423 | |
| 424 | return 0; |
| 425 | |
| 426 | invalid_dim: |
| 427 | VMW_DEBUG_USER("Invalid surface layout for dirty tracking.\n"); |
| 428 | return -EINVAL; |
| 429 | } |
| 430 | |
| 431 | /** |
| 432 | * vmw_surface_get_loc - Get a surface location from an offset into the |
| 433 | * backing store |
| 434 | * @cache: Surface layout data. |
| 435 | * @loc: Pointer to a struct vmw_surface_loc to be filled in. |
| 436 | * @offset: Offset into the surface backing store. |
| 437 | */ |
| 438 | static inline void |
| 439 | vmw_surface_get_loc(const struct vmw_surface_cache *cache, |
| 440 | struct vmw_surface_loc *loc, |
| 441 | size_t offset) |
| 442 | { |
| 443 | const struct vmw_surface_mip *mip = &cache->mip[0]; |
| 444 | const SVGA3dSurfaceDesc *desc = cache->desc; |
| 445 | u32 layer; |
| 446 | int i; |
| 447 | |
| 448 | loc->sheet = offset / cache->sheet_bytes; |
| 449 | offset -= loc->sheet * cache->sheet_bytes; |
| 450 | |
| 451 | layer = offset / cache->mip_chain_bytes; |
| 452 | offset -= layer * cache->mip_chain_bytes; |
| 453 | for (i = 0; i < cache->num_mip_levels; ++i, ++mip) { |
| 454 | if (mip->bytes > offset) |
| 455 | break; |
| 456 | offset -= mip->bytes; |
| 457 | } |
| 458 | |
| 459 | loc->sub_resource = vmw_surface_subres(cache, i, layer); |
| 460 | loc->z = offset / mip->img_stride; |
| 461 | offset -= loc->z * mip->img_stride; |
| 462 | loc->z *= desc->blockSize.depth; |
| 463 | loc->y = offset / mip->row_stride; |
| 464 | offset -= loc->y * mip->row_stride; |
| 465 | loc->y *= desc->blockSize.height; |
| 466 | loc->x = offset / desc->bytesPerBlock; |
| 467 | loc->x *= desc->blockSize.width; |
| 468 | } |
| 469 | |
| 470 | /** |
| 471 | * vmw_surface_inc_loc - Clamp increment a surface location with one block |
| 472 | * size |
| 473 | * in each dimension. |
| 474 | * @loc: Pointer to a struct vmw_surface_loc to be incremented. |
| 475 | * |
| 476 | * When computing the size of a range as size = end - start, the range does not |
| 477 | * include the end element. However a location representing the last byte |
| 478 | * of a touched region in the backing store *is* included in the range. |
| 479 | * This function modifies such a location to match the end definition |
| 480 | * given as start + size which is the one used in a SVGA3dBox. |
| 481 | */ |
| 482 | static inline void |
| 483 | vmw_surface_inc_loc(const struct vmw_surface_cache *cache, |
| 484 | struct vmw_surface_loc *loc) |
| 485 | { |
| 486 | const SVGA3dSurfaceDesc *desc = cache->desc; |
| 487 | u32 mip = loc->sub_resource % cache->num_mip_levels; |
| 488 | const struct drm_vmw_size *size = &cache->mip[mip].size; |
| 489 | |
| 490 | loc->sub_resource++; |
| 491 | loc->x += desc->blockSize.width; |
| 492 | if (loc->x > size->width) |
| 493 | loc->x = size->width; |
| 494 | loc->y += desc->blockSize.height; |
| 495 | if (loc->y > size->height) |
| 496 | loc->y = size->height; |
| 497 | loc->z += desc->blockSize.depth; |
| 498 | if (loc->z > size->depth) |
| 499 | loc->z = size->depth; |
| 500 | } |
| 501 | |
| 502 | /** |
| 503 | * vmw_surface_min_loc - The start location in a subresource |
| 504 | * @cache: Surface layout data. |
| 505 | * @sub_resource: The subresource. |
| 506 | * @loc: Pointer to a struct vmw_surface_loc to be filled in. |
| 507 | */ |
| 508 | static inline void |
| 509 | vmw_surface_min_loc(const struct vmw_surface_cache *cache, |
| 510 | u32 sub_resource, |
| 511 | struct vmw_surface_loc *loc) |
| 512 | { |
| 513 | loc->sheet = 0; |
| 514 | loc->sub_resource = sub_resource; |
| 515 | loc->x = loc->y = loc->z = 0; |
| 516 | } |
| 517 | |
| 518 | /** |
| 519 | * vmw_surface_min_loc - The end location in a subresource |
| 520 | * @cache: Surface layout data. |
| 521 | * @sub_resource: The subresource. |
| 522 | * @loc: Pointer to a struct vmw_surface_loc to be filled in. |
| 523 | * |
| 524 | * Following the end definition given in vmw_surface_inc_loc(), |
| 525 | * Compute the end location of a surface subresource. |
| 526 | */ |
| 527 | static inline void |
| 528 | vmw_surface_max_loc(const struct vmw_surface_cache *cache, |
| 529 | u32 sub_resource, |
| 530 | struct vmw_surface_loc *loc) |
| 531 | { |
| 532 | const struct drm_vmw_size *size; |
| 533 | u32 mip; |
| 534 | |
| 535 | loc->sheet = 0; |
| 536 | loc->sub_resource = sub_resource + 1; |
| 537 | mip = sub_resource % cache->num_mip_levels; |
| 538 | size = &cache->mip[mip].size; |
| 539 | loc->x = size->width; |
| 540 | loc->y = size->height; |
| 541 | loc->z = size->depth; |
| 542 | } |
| 543 | |
| 544 | |
| 545 | #endif /* VMW_SURFACE_CACHE_H */ |
| 546 |
Warning: This file is not a C or C++ file. It does not have highlighting.
