static void i915_miptree_layout_2d(struct intel_context *intel, struct intel_mipmap_tree * mt, uint32_t tiling) { GLuint width = mt->width0; GLuint height = mt->height0; GLuint img_height; GLint level; mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); mt->total_height = 0; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 1, 0, mt->total_height, width, height, 1); if (mt->compressed) img_height = MAX2(1, height / 4); else img_height = (MAX2(2, height) + 1) & ~1; mt->total_height += img_height; width = minify(width); height = minify(height); } }
static void i945_miptree_layout_3d(struct intel_context *intel, struct intel_mipmap_tree * mt, uint32_t tiling) { 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; mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); mt->total_height = 0; pack_y_pitch = MAX2(mt->height0, 2); pack_x_pitch = mt->pitch; pack_x_nr = 1; for (level = mt->first_level; level <= mt->last_level; level++) { GLint x = 0; GLint y = 0; GLint q, j; intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height, width, height, depth); for (q = 0; q < depth;) { for (j = 0; j < pack_x_nr && q < depth; 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; 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; }
/** * Cube texture map layout for i830M-GM915. * * Hardware layout looks like: * * +-------+-------+ * | | | * | | | * | | | * | +x | +y | * | | | * | | | * | | | * | | | * +---+---+-------+ * | | | | * | +x| +y| | * | | | | * | | | | * +-+-+---+ +z | * | | | | | * +-+-+ +z| | * | | | | * +-+-+---+-------+ * | | | * | | | * | | | * | -x | -y | * | | | * | | | * | | | * | | | * +---+---+-------+ * | | | | * | -x| -y| | * | | | | * | | | | * +-+-+---+ -z | * | | | | | * +-+-+ -z| | * | | | | * +-+---+-------+ * */ static void i915_miptree_layout_cube(struct intel_context *intel, struct intel_mipmap_tree * mt, uint32_t tiling) { const GLuint dim = mt->width0; GLuint face; GLuint lvlWidth = mt->width0, lvlHeight = mt->height0; GLint level; assert(lvlWidth == lvlHeight); /* cubemap images are square */ /* double pitch for cube layouts */ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2); mt->total_height = dim * 4; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, /*OLD: mt->pitch, mt->total_height,*/ lvlWidth, lvlHeight, 1); lvlWidth /= 2; lvlHeight /= 2; } for (face = 0; face < 6; face++) { GLuint x = initial_offsets[face][0] * dim; GLuint y = initial_offsets[face][1] * dim; GLuint d = dim; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_image_offset(mt, level, face, x, y); if (d == 0) printf("cube mipmap %d/%d (%d..%d) is 0x0\n", face, level, mt->first_level, mt->last_level); d >>= 1; x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; } } }
static void i915_miptree_layout_3d(struct intel_context *intel, struct intel_mipmap_tree * mt, uint32_t tiling) { GLuint width = mt->width0; GLuint height = mt->height0; GLuint depth = mt->depth0; GLuint stack_height = 0; GLint level; /* Calculate the size of a single slice. */ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); /* XXX: hardware expects/requires 9 levels at minimum. */ for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) { intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height, width, height, depth); stack_height += MAX2(2, height); width = minify(width); height = minify(height); depth = minify(depth); } /* Fixup depth image_offsets: */ depth = mt->depth0; for (level = mt->first_level; level <= mt->last_level; level++) { GLuint i; for (i = 0; i < depth; i++) { intel_miptree_set_image_offset(mt, level, i, 0, i * stack_height); } depth = minify(depth); } /* Multiply slice size by texture depth for total size. It's * remarkable how wasteful of memory the i915 texture layouts * are. They are largely fixed in the i945. */ mt->total_height = stack_height * mt->depth0; }
static void i945_miptree_layout_cube(struct intel_context *intel, struct intel_mipmap_tree * mt, uint32_t tiling) { const GLuint dim = mt->width0; GLuint face; GLuint lvlWidth = mt->width0, lvlHeight = mt->height0; GLint level; assert(lvlWidth == lvlHeight); /* cubemap images are square */ /* Depending on the size of the largest images, pitch can be * determined either by the old-style packing of cubemap faces, * or the final row of 4x4, 2x2 and 1x1 faces below this. */ if (dim > 32) mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2); else mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, 14 * 8); if (dim >= 4) mt->total_height = dim * 4 + 4; else mt->total_height = 4; /* Set all the levels to effectively occupy the whole rectangular region. */ for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, lvlWidth, lvlHeight, 1); lvlWidth /= 2; lvlHeight /= 2; } for (face = 0; face < 6; face++) { GLuint x = initial_offsets[face][0] * dim; GLuint y = initial_offsets[face][1] * dim; GLuint d = dim; if (dim == 4 && face >= 4) { y = mt->total_height - 4; x = (face - 4) * 8; } else if (dim < 4 && (face > 0 || mt->first_level > 0)) { y = mt->total_height - 4; x = face * 8; } for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_image_offset(mt, level, face, x, y); d >>= 1; switch (d) { case 4: switch (face) { case FACE_POS_X: case FACE_NEG_X: x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; break; case FACE_POS_Y: case FACE_NEG_Y: y += 12; x -= 8; break; case FACE_POS_Z: case FACE_NEG_Z: y = mt->total_height - 4; x = (face - 4) * 8; break; } break; case 2: y = mt->total_height - 4; x = bottom_offsets[face]; break; case 1: x += 48; break; default: x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; break; } } } }
GLboolean i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt) { GLint level; switch (mt->target) { case GL_TEXTURE_CUBE_MAP:{ const GLuint dim = mt->width0; GLuint face; GLuint lvlWidth = mt->width0, lvlHeight = mt->height0; assert(lvlWidth == lvlHeight); /* cubemap images are square */ /* double pitch for cube layouts */ mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2); mt->total_height = dim * 4; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, /*OLD: mt->pitch, mt->total_height,*/ lvlWidth, lvlHeight, 1); lvlWidth /= 2; lvlHeight /= 2; } for (face = 0; face < 6; face++) { GLuint x = initial_offsets[face][0] * dim; GLuint y = initial_offsets[face][1] * dim; GLuint d = dim; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_image_offset(mt, level, face, x, y); if (d == 0) _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n", face, level, mt->first_level, mt->last_level); d >>= 1; x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; } } break; } case GL_TEXTURE_3D:{ GLuint width = mt->width0; GLuint height = mt->height0; GLuint depth = mt->depth0; GLuint stack_height = 0; /* Calculate the size of a single slice. */ mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0); /* XXX: hardware expects/requires 9 levels at minimum. */ for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) { intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height, width, height, depth); stack_height += MAX2(2, height); width = minify(width); height = minify(height); depth = minify(depth); } /* Fixup depth image_offsets: */ depth = mt->depth0; for (level = mt->first_level; level <= mt->last_level; level++) { GLuint i; for (i = 0; i < depth; i++) intel_miptree_set_image_offset(mt, level, i, 0, i * stack_height); depth = minify(depth); } /* Multiply slice size by texture depth for total size. It's * remarkable how wasteful of memory the i915 texture layouts * are. They are largely fixed in the i945. */ mt->total_height = stack_height * mt->depth0; break; } default:{ GLuint width = mt->width0; GLuint height = mt->height0; GLuint img_height; mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0); mt->total_height = 0; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 1, 0, mt->total_height, width, height, 1); if (mt->compressed) img_height = MAX2(1, height / 4); else img_height = (MAX2(2, height) + 1) & ~1; mt->total_height += img_height; width = minify(width); height = minify(height); } break; } } DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__, mt->pitch, mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp); return GL_TRUE; }
GLboolean i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt) { GLint level; switch (mt->target) { case GL_TEXTURE_CUBE_MAP:{ const GLuint dim = mt->width0; GLuint face; GLuint lvlWidth = mt->width0, lvlHeight = mt->height0; assert(lvlWidth == lvlHeight); /* cubemap images are square */ /* Depending on the size of the largest images, pitch can be * determined either by the old-style packing of cubemap faces, * or the final row of 4x4, 2x2 and 1x1 faces below this. */ if (dim > 32) mt->pitch = intel_miptree_pitch_align (intel, mt, dim); else mt->pitch = 14 * 8; mt->total_height = dim * 4 + 4; /* Set all the levels to effectively occupy the whole rectangular region. */ for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, lvlWidth, lvlHeight, 1); lvlWidth /= 2; lvlHeight /= 2; } for (face = 0; face < 6; face++) { GLuint x = initial_offsets[face][0] * dim; GLuint y = initial_offsets[face][1] * dim; GLuint d = dim; if (dim == 4 && face >= 4) { y = mt->total_height - 4; x = (face - 4) * 8; } else if (dim < 4 && (face > 0 || mt->first_level > 0)) { y = mt->total_height - 4; x = face * 8; } for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_image_offset(mt, level, face, x, y); d >>= 1; switch (d) { case 4: switch (face) { case FACE_POS_X: case FACE_NEG_X: x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; break; case FACE_POS_Y: case FACE_NEG_Y: y += 12; x -= 8; break; case FACE_POS_Z: case FACE_NEG_Z: y = mt->total_height - 4; x = (face - 4) * 8; break; } case 2: y = mt->total_height - 4; x = 16 + face * 8; break; case 1: x += 48; break; default: x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; break; } } } 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; mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0); mt->total_height = 0; pack_y_pitch = MAX2(mt->height0, 2); pack_x_pitch = mt->pitch; 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; 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; } width = minify(width); height = minify(height); depth = minify(depth); } 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 (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; }
void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt ) { GLint align_h = 2, align_w = 4; GLuint level; GLuint x = 0; GLuint y = 0; GLuint width = mt->width0; GLuint height = mt->height0; mt->pitch = mt->width0; if (mt->compressed) { align_w = intel_compressed_alignment(mt->internal_format); mt->pitch = ALIGN(mt->width0, align_w); } /* May need to adjust pitch to accomodate the placement of * the 2nd mipmap. This occurs when the alignment * constraints of mipmap placement push the right edge of the * 2nd mipmap out past the width of its parent. */ 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; } } /* Pitch must be a whole number of dwords, even though we * express it in texels. */ mt->pitch = intel_miptree_pitch_align (intel, mt, mt->pitch); mt->total_height = 0; for ( level = mt->first_level ; level <= mt->last_level ; level++ ) { GLuint img_height; intel_miptree_set_level_info(mt, level, 1, x, y, width, height, 1); if (mt->compressed) img_height = MAX2(1, height/4); else img_height = ALIGN(height, align_h); /* Because the images are packed better, the final offset * might not be the maximal one: */ mt->total_height = MAX2(mt->total_height, y + img_height); /* Layout_below: step right after second mipmap. */ if (level == mt->first_level + 1) { x += ALIGN(width, align_w); } else { y += img_height; } width = minify(width); height = minify(height); } }