static uint32_t setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format format) { struct pipe_resource *prsc = &rsc->base.b; enum util_format_layout layout = util_format_description(format)->layout; uint32_t level, size = 0; uint32_t width = prsc->width0; uint32_t height = prsc->height0; uint32_t depth = prsc->depth0; /* in layer_first layout, the level (slice) contains just one * layer (since in fact the layer contains the slices) */ uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size; for (level = 0; level <= prsc->last_level; level++) { struct fd_resource_slice *slice = fd_resource_slice(rsc, level); uint32_t blocks; if (layout == UTIL_FORMAT_LAYOUT_ASTC) slice->pitch = width = util_align_npot(width, 32 * util_format_get_blockwidth(format)); else slice->pitch = width = align(width, 32); slice->offset = size; blocks = util_format_get_nblocks(format, width, height); /* 1d array and 2d array textures must all have the same layer size * for each miplevel on a3xx. 3d textures can have different layer * sizes for high levels, but the hw auto-sizer is buggy (or at least * different than what this code does), so as soon as the layer size * range gets into range, we stop reducing it. */ if (prsc->target == PIPE_TEXTURE_3D && ( level == 1 || (level > 1 && rsc->slices[level - 1].size0 > 0xf000))) slice->size0 = align(blocks * rsc->cpp, alignment); else if (level == 0 || rsc->layer_first || alignment == 1) slice->size0 = align(blocks * rsc->cpp, alignment); else slice->size0 = rsc->slices[level - 1].size0; size += slice->size0 * depth * layers_in_level; width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } return size; }
static void r300_setup_cmask_properties(struct r300_screen *screen, struct r300_resource *tex) { static unsigned cmask_align_x[4] = {16, 32, 48, 32}; static unsigned cmask_align_y[4] = {16, 16, 16, 32}; unsigned pipes, stride, cmask_num_dw, cmask_max_size; /* We need an AA colorbuffer, no mipmaps. */ if (tex->b.b.nr_samples <= 1 || tex->b.b.last_level > 0 || util_format_is_depth_or_stencil(tex->b.b.format)) { return; } /* FP16 AA needs R500 and a fairly new DRM. */ if ((tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || tex->b.b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && (!screen->caps.is_r500 || screen->info.drm_minor < 29)) { return; } if (SCREEN_DBG_ON(screen, DBG_NO_CMASK)) { return; } /* CMASK is part of raster pipes. The number of Z pipes doesn't matter. */ pipes = screen->info.r300_num_gb_pipes; /* The single-pipe cards have 5120 dwords of CMASK RAM, * the other cards have 4096 dwords of CMASK RAM per pipe. */ cmask_max_size = pipes == 1 ? 5120 : pipes * 4096; stride = r300_stride_to_width(tex->b.b.format, tex->tex.stride_in_bytes[0]); stride = align(stride, 16); /* Get the CMASK size in dwords. */ cmask_num_dw = r300_pixels_to_dwords(stride, tex->b.b.height0, cmask_align_x[pipes-1], cmask_align_y[pipes-1]); /* Check the CMASK size against the CMASK memory limit. */ if (cmask_num_dw <= cmask_max_size) { tex->tex.cmask_dwords = cmask_num_dw; tex->tex.cmask_stride_in_pixels = util_align_npot(stride, cmask_align_x[pipes-1]); } }
/** * Callback exported to the draw module. * * Side effects: * Updates hw_offset, sw_offset, index and may allocate * a new buffer. Also updates may update the vbo state * on the i915 context. */ static boolean i915_vbuf_render_allocate_vertices(struct vbuf_render *render, ushort vertex_size, ushort nr_vertices) { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); size_t size = (size_t)vertex_size * (size_t)nr_vertices; size_t offset; /* * Align sw_offset with first multiple of vertex size from hw_offset. * Set index to be the multiples from from hw_offset to sw_offset. * i915_vbuf_render_new_buf will reset index, sw_offset, hw_offset * when it allocates a new buffer this is correct. */ { offset = i915_render->vbo_sw_offset - i915_render->vbo_hw_offset; offset = util_align_npot(offset, vertex_size); i915_render->vbo_sw_offset = i915_render->vbo_hw_offset + offset; i915_render->vbo_index = offset / vertex_size; } if (!i915_vbuf_render_reserve(i915_render, size)) i915_vbuf_render_new_buf(i915_render, size); /* * If a new buffer has been alocated sw_offset, * hw_offset & index will be reset by new_buf */ i915_render->vertex_size = vertex_size; i915_vbuf_update_vbo_state(render); if (!i915_render->vbo) return FALSE; return TRUE; }
static void r300_setup_hyperz_properties(struct r300_screen *screen, struct r300_resource *tex) { /* The tile size of 1 DWORD in ZMASK RAM is: * * GPU Pipes 4x4 mode 8x8 mode * ------------------------------------------ * R580 4P/1Z 32x32 64x64 * RV570 3P/1Z 48x16 96x32 * RV530 1P/2Z 32x16 64x32 * 1P/1Z 16x16 32x32 */ static unsigned zmask_blocks_x_per_dw[4] = {4, 8, 12, 8}; static unsigned zmask_blocks_y_per_dw[4] = {4, 4, 4, 8}; /* In HIZ RAM, one dword is always 8x8 pixels (each byte is 4x4 pixels), * but the blocks have very weird ordering. * * With 2 pipes and an image of size 8xY, where Y >= 1, * clearing 4 dwords clears blocks like this: * * 01012323 * * where numbers correspond to dword indices. The blocks are interleaved * in the X direction, so the alignment must be 4x1 blocks (32x8 pixels). * * With 4 pipes and an image of size 8xY, where Y >= 4, * clearing 8 dwords clears blocks like this: * 01012323 * 45456767 * 01012323 * 45456767 * where numbers correspond to dword indices. The blocks are interleaved * in both directions, so the alignment must be 4x4 blocks (32x32 pixels) */ static unsigned hiz_align_x[4] = {8, 32, 48, 32}; static unsigned hiz_align_y[4] = {8, 8, 8, 32}; if (util_format_is_depth_or_stencil(tex->b.b.b.format) && util_format_get_blocksizebits(tex->b.b.b.format) == 32 && tex->tex.microtile) { unsigned i, pipes; if (screen->caps.family == CHIP_FAMILY_RV530) { pipes = screen->info.r300_num_z_pipes; } else { pipes = screen->info.r300_num_gb_pipes; } for (i = 0; i <= tex->b.b.b.last_level; i++) { unsigned zcomp_numdw, zcompsize, hiz_numdw, stride, height; stride = align(tex->tex.stride_in_pixels[i], 16); height = u_minify(tex->b.b.b.height0, i); /* The 8x8 compression mode needs macrotiling. */ zcompsize = screen->caps.z_compress == R300_ZCOMP_8X8 && tex->tex.macrotile[i] && tex->b.b.b.nr_samples <= 1 ? 8 : 4; /* Get the ZMASK buffer size in dwords. */ zcomp_numdw = r300_pixels_to_dwords(stride, height, zmask_blocks_x_per_dw[pipes-1] * zcompsize, zmask_blocks_y_per_dw[pipes-1] * zcompsize); /* Check whether we have enough ZMASK memory. */ if (util_format_get_blocksizebits(tex->b.b.b.format) == 32 && zcomp_numdw <= screen->caps.zmask_ram * pipes) { tex->tex.zmask_dwords[i] = zcomp_numdw; tex->tex.zcomp8x8[i] = zcompsize == 8; tex->tex.zmask_stride_in_pixels[i] = util_align_npot(stride, zmask_blocks_x_per_dw[pipes-1] * zcompsize); } else { tex->tex.zmask_dwords[i] = 0; tex->tex.zcomp8x8[i] = FALSE; tex->tex.zmask_stride_in_pixels[i] = 0; } /* Now setup HIZ. */ stride = util_align_npot(stride, hiz_align_x[pipes-1]); height = align(height, hiz_align_y[pipes-1]); /* Get the HIZ buffer size in dwords. */ hiz_numdw = (stride * height) / (8*8 * pipes); /* Check whether we have enough HIZ memory. */ if (hiz_numdw <= screen->caps.hiz_ram * pipes) { tex->tex.hiz_dwords[i] = hiz_numdw; tex->tex.hiz_stride_in_pixels[i] = stride; } else { tex->tex.hiz_dwords[i] = 0; tex->tex.hiz_stride_in_pixels[i] = 0; } } } }
static unsigned r300_pixels_to_dwords(unsigned stride, unsigned height, unsigned xblock, unsigned yblock) { return (util_align_npot(stride, xblock) * align(height, yblock)) / (xblock * yblock); }
/** * In OpenGL the number of 1D array texture layers is the "height" and * the number of 2D array texture layers is the "depth". In Gallium the * number of layers in an array texture is a separate 'array_size' field. * This function converts dimensions from the former to the later. */ void st_gl_texture_dims_to_pipe_dims(GLenum texture, unsigned widthIn, uint16_t heightIn, uint16_t depthIn, unsigned *widthOut, uint16_t *heightOut, uint16_t *depthOut, uint16_t *layersOut) { switch (texture) { case GL_TEXTURE_1D: case GL_PROXY_TEXTURE_1D: assert(heightIn == 1); assert(depthIn == 1); *widthOut = widthIn; *heightOut = 1; *depthOut = 1; *layersOut = 1; break; case GL_TEXTURE_1D_ARRAY: case GL_PROXY_TEXTURE_1D_ARRAY: assert(depthIn == 1); *widthOut = widthIn; *heightOut = 1; *depthOut = 1; *layersOut = heightIn; break; case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: case GL_TEXTURE_RECTANGLE: case GL_PROXY_TEXTURE_RECTANGLE: case GL_TEXTURE_EXTERNAL_OES: case GL_PROXY_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE: assert(depthIn == 1); *widthOut = widthIn; *heightOut = heightIn; *depthOut = 1; *layersOut = 1; break; case GL_TEXTURE_CUBE_MAP: case GL_PROXY_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: assert(depthIn == 1); *widthOut = widthIn; *heightOut = heightIn; *depthOut = 1; *layersOut = 6; break; case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: case GL_PROXY_TEXTURE_2D_ARRAY: case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: *widthOut = widthIn; *heightOut = heightIn; *depthOut = 1; *layersOut = depthIn; break; case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: *widthOut = widthIn; *heightOut = heightIn; *depthOut = 1; *layersOut = util_align_npot(depthIn, 6); break; default: assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()"); /* fall-through */ case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: *widthOut = widthIn; *heightOut = heightIn; *depthOut = depthIn; *layersOut = 1; break; } }