/** * @param for_bo Indicates that the caller is * intel_miptree_create_for_bo(). If true, then do not create * \c stencil_mt. */ struct intel_mipmap_tree * intel_miptree_create_layout(struct intel_context *intel, GLenum target, mesa_format format, GLuint first_level, GLuint last_level, GLuint width0, GLuint height0, GLuint depth0, bool for_bo) { struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); if (!mt) return NULL; DBG("%s target %s format %s level %d..%d <-- %p\n", __func__, _mesa_enum_to_string(target), _mesa_get_format_name(format), first_level, last_level, mt); mt->target = target_to_target(target); mt->format = format; mt->first_level = first_level; mt->last_level = last_level; mt->logical_width0 = width0; mt->logical_height0 = height0; mt->logical_depth0 = depth0; /* The cpp is bytes per (1, blockheight)-sized block for compressed * textures. This is why you'll see divides by blockheight all over */ unsigned bw, bh; _mesa_get_format_block_size(format, &bw, &bh); assert(_mesa_get_format_bytes(mt->format) % bw == 0); mt->cpp = _mesa_get_format_bytes(mt->format) / bw; mt->compressed = _mesa_is_format_compressed(format); mt->refcount = 1; if (target == GL_TEXTURE_CUBE_MAP) { assert(depth0 == 1); depth0 = 6; } mt->physical_width0 = width0; mt->physical_height0 = height0; mt->physical_depth0 = depth0; intel_get_texture_alignment_unit(intel, mt->format, &mt->align_w, &mt->align_h); (void) intel; if (intel->is_945) i945_miptree_layout(mt); else i915_miptree_layout(mt); return mt; }
/** * Copy mipmap image between trees */ void intel_miptree_image_copy(struct intel_context *intel, struct intel_mipmap_tree *dst, GLuint face, GLuint level, struct intel_mipmap_tree *src) { GLuint width = src->level[level].width; GLuint height = src->level[level].height; GLuint depth = src->level[level].depth; GLuint src_x, src_y, dst_x, dst_y; GLuint i; GLboolean success; if (dst->compressed) { GLuint align_w, align_h; intel_get_texture_alignment_unit(dst->internal_format, &align_w, &align_h); height = (height + 3) / 4; width = ALIGN(width, align_w); } intel_prepare_render(intel); for (i = 0; i < depth; i++) { intel_miptree_get_image_offset(src, level, face, i, &src_x, &src_y); intel_miptree_get_image_offset(dst, level, face, i, &dst_x, &dst_y); success = intel_region_copy(intel, dst->region, 0, dst_x, dst_y, src->region, 0, src_x, src_y, width, height, GL_FALSE, GL_COPY); if (!success) { GLubyte *src_ptr, *dst_ptr; src_ptr = intel_region_map(intel, src->region); dst_ptr = intel_region_map(intel, dst->region); _mesa_copy_rect(dst_ptr, dst->cpp, dst->region->pitch, dst_x, dst_y, width, height, src_ptr, src->region->pitch, src_x, src_y); intel_region_unmap(intel, src->region); intel_region_unmap(intel, dst->region); } } }
GLboolean brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt, uint32_t tiling) { /* XXX: these vary depending on image format: */ /* GLint align_w = 4; */ switch (mt->target) { case GL_TEXTURE_CUBE_MAP: if (intel->gen == 5) { GLuint align_h = 2; GLuint level; GLuint qpitch = 0; int h0, h1, q; /* On Ironlake, cube maps are finally represented as just a series * of MIPLAYOUT_BELOW 2D textures (like 2D texture arrays), separated * by a pitch of qpitch rows, where qpitch is defined by the equation * given in Volume 1 of the BSpec. */ h0 = ALIGN(mt->height0, align_h); h1 = ALIGN(minify(h0), align_h); qpitch = (h0 + h1 + 11 * align_h); if (mt->compressed) qpitch /= 4; i945_miptree_layout_2d(intel, mt, tiling, 6); for (level = mt->first_level; level <= mt->last_level; level++) { for (q = 0; q < 6; q++) { intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch); } } mt->total_height = qpitch * 6; break; } case GL_TEXTURE_3D: { GLuint width = mt->width0; GLuint height = mt->height0; GLuint depth = mt->depth0; GLuint pack_x_pitch, pack_x_nr; GLuint pack_y_pitch; GLuint level; GLuint align_h = 2; GLuint align_w = 4; mt->total_height = 0; intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h); if (mt->compressed) { mt->pitch = ALIGN(width, align_w); pack_y_pitch = (height + 3) / 4; } else { mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); pack_y_pitch = ALIGN(mt->height0, align_h); } pack_x_pitch = width; pack_x_nr = 1; for (level = mt->first_level ; level <= mt->last_level ; level++) { GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6; GLint x = 0; GLint y = 0; GLint q, j; intel_miptree_set_level_info(mt, level, nr_images, 0, mt->total_height, width, height, depth); for (q = 0; q < nr_images;) { for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) { intel_miptree_set_image_offset(mt, level, q, x, y); x += pack_x_pitch; } x = 0; y += pack_y_pitch; } mt->total_height += y; width = minify(width); height = minify(height); depth = minify(depth); if (mt->compressed) { pack_y_pitch = (height + 3) / 4; if (pack_x_pitch > ALIGN(width, align_w)) { pack_x_pitch = ALIGN(width, align_w); pack_x_nr <<= 1; } } else { if (pack_x_pitch > 4) { pack_x_pitch >>= 1; pack_x_nr <<= 1; assert(pack_x_pitch * pack_x_nr <= mt->pitch); } if (pack_y_pitch > 2) { pack_y_pitch >>= 1; pack_y_pitch = ALIGN(pack_y_pitch, align_h); } } } /* The 965's sampler lays cachelines out according to how accesses * in the texture surfaces run, so they may be "vertical" through * memory. As a result, the docs say in Surface Padding Requirements: * Sampling Engine Surfaces that two extra rows of padding are required. * We don't know of similar requirements for pre-965, but given that * those docs are silent on padding requirements in general, let's play * it safe. */ if (mt->target == GL_TEXTURE_CUBE_MAP) mt->total_height += 2; break; }
GLboolean brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt, uint32_t tiling) { /* XXX: these vary depending on image format: */ /* GLint align_w = 4; */ switch (mt->target) { case GL_TEXTURE_CUBE_MAP: if (IS_IGDNG(intel->intelScreen->deviceID)) { GLuint align_h = 2, align_w = 4; GLuint level; GLuint x = 0; GLuint y = 0; GLuint width = mt->width0; GLuint height = mt->height0; GLuint qpitch = 0; GLuint y_pitch = 0; mt->pitch = mt->width0; intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h); y_pitch = ALIGN(height, align_h); if (mt->compressed) { mt->pitch = ALIGN(mt->width0, align_w); } if (mt->first_level != mt->last_level) { GLuint mip1_width; if (mt->compressed) { mip1_width = ALIGN(minify(mt->width0), align_w) + ALIGN(minify(minify(mt->width0)), align_w); } else { mip1_width = ALIGN(minify(mt->width0), align_w) + minify(minify(mt->width0)); } if (mip1_width > mt->pitch) { mt->pitch = mip1_width; } } mt->pitch = intel_miptree_pitch_align(intel, mt, tiling, mt->pitch); if (mt->compressed) { qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4; mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6; } else { qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h); mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6; } for (level = mt->first_level; level <= mt->last_level; level++) { GLuint img_height; GLuint nr_images = 6; GLuint q = 0; intel_miptree_set_level_info(mt, level, nr_images, x, y, width, height, 1); for (q = 0; q < nr_images; q++) intel_miptree_set_image_offset(mt, level, q, x, y + q * qpitch); if (mt->compressed) img_height = MAX2(1, height/4); else img_height = ALIGN(height, align_h); if (level == mt->first_level + 1) { x += ALIGN(width, align_w); } else { y += img_height; } width = minify(width); height = minify(height); } break; } case GL_TEXTURE_3D: { GLuint width = mt->width0; GLuint height = mt->height0; GLuint depth = mt->depth0; GLuint pack_x_pitch, pack_x_nr; GLuint pack_y_pitch; GLuint level; GLuint align_h = 2; GLuint align_w = 4; mt->total_height = 0; intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h); if (mt->compressed) { mt->pitch = ALIGN(width, align_w); pack_y_pitch = (height + 3) / 4; } else { mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); pack_y_pitch = ALIGN(mt->height0, align_h); } pack_x_pitch = width; pack_x_nr = 1; for (level = mt->first_level ; level <= mt->last_level ; level++) { GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6; GLint x = 0; GLint y = 0; GLint q, j; intel_miptree_set_level_info(mt, level, nr_images, 0, mt->total_height, width, height, depth); for (q = 0; q < nr_images;) { for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) { intel_miptree_set_image_offset(mt, level, q, x, y); x += pack_x_pitch; } x = 0; y += pack_y_pitch; } mt->total_height += y; width = minify(width); height = minify(height); depth = minify(depth); if (mt->compressed) { pack_y_pitch = (height + 3) / 4; if (pack_x_pitch > ALIGN(width, align_w)) { pack_x_pitch = ALIGN(width, align_w); pack_x_nr <<= 1; } } else { if (pack_x_pitch > 4) { pack_x_pitch >>= 1; pack_x_nr <<= 1; assert(pack_x_pitch * pack_x_nr <= mt->pitch); } if (pack_y_pitch > 2) { pack_y_pitch >>= 1; pack_y_pitch = ALIGN(pack_y_pitch, align_h); } } } /* The 965's sampler lays cachelines out according to how accesses * in the texture surfaces run, so they may be "vertical" through * memory. As a result, the docs say in Surface Padding Requirements: * Sampling Engine Surfaces that two extra rows of padding are required. * We don't know of similar requirements for pre-965, but given that * those docs are silent on padding requirements in general, let's play * it safe. */ if (mt->target == GL_TEXTURE_CUBE_MAP) mt->total_height += 2; break; }