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 i915_miptree_layout_2d(struct intel_mipmap_tree * mt) { GLuint width = mt->width0; GLuint height = mt->height0; GLuint img_height; GLint level; mt->total_width = mt->width0; mt->total_height = 0; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 0, mt->total_height, width, height, 1); if (mt->compressed) img_height = ALIGN(height, 4) / 4; else img_height = ALIGN(height, 2); mt->total_height += img_height; width = minify(width); height = minify(height); } }
static void gen9_miptree_layout_1d(struct intel_mipmap_tree *mt) { unsigned x = 0; unsigned width = mt->physical_width0; unsigned depth = mt->physical_depth0; /* number of array layers. */ /* When this layout is used the horizontal alignment is fixed at 64 and the * hardware ignores the value given in the surface state */ const unsigned int align_w = 64; mt->total_height = mt->physical_height0; mt->total_width = 0; for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned img_width; intel_miptree_set_level_info(mt, level, x, 0, depth); img_width = ALIGN(width, align_w); mt->total_width = MAX2(mt->total_width, x + img_width); x += img_width; width = minify(width, 1); } }
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; }
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; }
/** * 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 brw_miptree_layout_texture_3d(struct brw_context *brw, struct intel_mipmap_tree *mt) { mt->total_width = 0; mt->total_height = 0; unsigned ysum = 0; unsigned bh, bw; _mesa_get_format_block_size(mt->format, &bw, &bh); for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned WL = MAX2(mt->physical_width0 >> level, 1); unsigned HL = MAX2(mt->physical_height0 >> level, 1); unsigned DL = MAX2(mt->physical_depth0 >> level, 1); unsigned wL = ALIGN_NPOT(WL, mt->align_w); unsigned hL = ALIGN_NPOT(HL, mt->align_h); if (mt->target == GL_TEXTURE_CUBE_MAP) DL = 6; intel_miptree_set_level_info(mt, level, 0, 0, DL); for (unsigned q = 0; q < DL; q++) { unsigned x = (q % (1 << level)) * wL; unsigned y = ysum + (q >> level) * hL; intel_miptree_set_image_offset(mt, level, q, x / bw, y / bh); mt->total_width = MAX2(mt->total_width, (x + wL) / bw); mt->total_height = MAX2(mt->total_height, (y + hL) / bh); } ysum += ALIGN(DL, 1 << level) / (1 << level) * hL; } align_cube(mt); }
static void brw_miptree_layout_texture_3d(struct brw_context *brw, struct intel_mipmap_tree *mt) { unsigned yscale = mt->compressed ? 4 : 1; mt->total_width = 0; mt->total_height = 0; unsigned ysum = 0; for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned WL = MAX2(mt->physical_width0 >> level, 1); unsigned HL = MAX2(mt->physical_height0 >> level, 1); unsigned DL = MAX2(mt->physical_depth0 >> level, 1); unsigned wL = ALIGN(WL, mt->align_w); unsigned hL = ALIGN(HL, mt->align_h); if (mt->target == GL_TEXTURE_CUBE_MAP) DL = 6; intel_miptree_set_level_info(mt, level, 0, 0, WL, HL, DL); for (unsigned q = 0; q < DL; q++) { unsigned x = (q % (1 << level)) * wL; unsigned y = ysum + (q >> level) * hL; intel_miptree_set_image_offset(mt, level, q, x, y / yscale); mt->total_width = MAX2(mt->total_width, x + wL); mt->total_height = MAX2(mt->total_height, (y + hL) / yscale); } ysum += ALIGN(DL, 1 << level) / (1 << level) * hL; } align_cube(mt); }
static void brw_miptree_layout_2d(struct intel_mipmap_tree *mt) { unsigned x = 0; unsigned y = 0; unsigned width = mt->physical_width0; unsigned height = mt->physical_height0; unsigned depth = mt->physical_depth0; /* number of array layers. */ mt->total_width = mt->physical_width0; if (mt->compressed) { mt->total_width = ALIGN(mt->physical_width0, mt->align_w); } /* May need to adjust width 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) { unsigned mip1_width; if (mt->compressed) { mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + ALIGN(minify(mt->physical_width0, 2), mt->align_w); } else { mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + minify(mt->physical_width0, 2); } if (mip1_width > mt->total_width) { mt->total_width = mip1_width; } } mt->total_height = 0; for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned img_height; intel_miptree_set_level_info(mt, level, x, y, width, height, depth); img_height = ALIGN(height, mt->align_h); if (mt->compressed) img_height /= mt->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, mt->align_w); } else { y += img_height; } width = minify(width, 1); height = minify(height, 1); } }
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; }
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; }
static void brw_miptree_layout_2d(struct intel_mipmap_tree *mt) { unsigned x = 0; unsigned y = 0; unsigned width = mt->physical_width0; unsigned height = mt->physical_height0; unsigned depth = mt->physical_depth0; /* number of array layers. */ unsigned int bw, bh; _mesa_get_format_block_size(mt->format, &bw, &bh); mt->total_width = mt->physical_width0; if (mt->compressed) mt->total_width = ALIGN_NPOT(mt->total_width, bw); /* May need to adjust width to accommodate 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) { unsigned mip1_width; if (mt->compressed) { mip1_width = ALIGN_NPOT(minify(mt->physical_width0, 1), mt->align_w) + ALIGN_NPOT(minify(mt->physical_width0, 2), bw); } else { mip1_width = ALIGN_NPOT(minify(mt->physical_width0, 1), mt->align_w) + minify(mt->physical_width0, 2); } if (mip1_width > mt->total_width) { mt->total_width = mip1_width; } } mt->total_width /= bw; mt->total_height = 0; for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned img_height; intel_miptree_set_level_info(mt, level, x, y, depth); img_height = ALIGN_NPOT(height, mt->align_h); if (mt->compressed) img_height /= bh; if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) { /* Compact arrays with separated miplevels */ img_height *= depth; } /* 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_NPOT(width, mt->align_w) / bw; } else { y += img_height; } width = minify(width, 1); height = minify(height, 1); if (mt->target == GL_TEXTURE_3D) depth = minify(depth, 1); } }
void brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) { switch (mt->target) { case GL_TEXTURE_CUBE_MAP_ARRAY: brw_miptree_layout_texture_array(intel, mt); break; case GL_TEXTURE_CUBE_MAP: if (intel->gen >= 5) { /* 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. */ brw_miptree_layout_texture_array(intel, mt); break; } assert(mt->physical_depth0 == 6); /* FALLTHROUGH */ case GL_TEXTURE_3D: { GLuint width = mt->physical_width0; GLuint height = mt->physical_height0; GLuint depth = mt->physical_depth0; GLuint pack_x_pitch, pack_x_nr; GLuint pack_y_pitch; GLuint level; mt->total_height = 0; if (mt->compressed) { mt->total_width = ALIGN(width, mt->align_w); pack_y_pitch = (height + 3) / 4; } else { mt->total_width = mt->physical_width0; pack_y_pitch = ALIGN(mt->physical_height0, mt->align_h); } pack_x_pitch = width; 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, 0, mt->total_height, width, height, depth); for (q = 0; q < depth; /* empty */) { 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; } if (x > mt->total_width) mt->total_width = x; x = 0; y += pack_y_pitch; } mt->total_height += y; width = minify(width); height = minify(height); if (mt->target == GL_TEXTURE_3D) depth = minify(depth); if (mt->compressed) { pack_y_pitch = (height + 3) / 4; if (pack_x_pitch > ALIGN(width, mt->align_w)) { pack_x_pitch = ALIGN(width, mt->align_w); pack_x_nr <<= 1; } } else { pack_x_nr <<= 1; if (pack_x_pitch > 4) { pack_x_pitch >>= 1; } if (pack_y_pitch > 2) { pack_y_pitch >>= 1; pack_y_pitch = ALIGN(pack_y_pitch, mt->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. */ 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 (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; }
static void i945_miptree_layout_cube(struct intel_mipmap_tree * mt) { 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->total_width = dim * 2; else mt->total_width = 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, 0, 0, lvlWidth, lvlHeight, 6); 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; } } } }
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); } }