/** * Store user data into texture memory. * Called via glTex[Sub]Image1/2/3D() * \return GL_TRUE for success, GL_FALSE for failure (out of memory). */ GLboolean _mesa_texstore(TEXSTORE_PARAMS) { if (_mesa_texstore_memcpy(ctx, dims, baseInternalFormat, dstFormat, dstRowStride, dstSlices, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking)) { return GL_TRUE; } if (_mesa_is_depth_or_stencil_format(baseInternalFormat)) { return texstore_depth_stencil(ctx, dims, baseInternalFormat, dstFormat, dstRowStride, dstSlices, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else if (_mesa_is_format_compressed(dstFormat)) { return texstore_compressed(ctx, dims, baseInternalFormat, dstFormat, dstRowStride, dstSlices, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else { return texstore_rgba(ctx, dims, baseInternalFormat, dstFormat, dstRowStride, dstSlices, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } }
unsigned brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw, const struct intel_mipmap_tree *mt, unsigned level) { if (brw->gen >= 9) { /* ALL_SLICES_AT_EACH_LOD isn't supported on Gen8+ but this code will * effectively end up with a packed qpitch anyway whenever * mt->first_level == mt->last_level. */ assert(mt->array_layout != ALL_SLICES_AT_EACH_LOD); /* On Gen9 we can pick whatever qpitch we like as long as it's aligned * to the vertical alignment so we don't need to add any extra rows. */ unsigned qpitch = mt->total_height; /* If the surface might be used as a stencil buffer or HiZ buffer then * it needs to be a multiple of 8. */ const GLenum base_format = _mesa_get_format_base_format(mt->format); if (_mesa_is_depth_or_stencil_format(base_format)) qpitch = ALIGN(qpitch, 8); /* 3D textures need to be aligned to the tile height. At this point we * don't know which tiling will be used so let's just align it to 32 */ if (mt->target == GL_TEXTURE_3D) qpitch = ALIGN(qpitch, 32); return qpitch; } else if (mt->target == GL_TEXTURE_3D || (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP) || mt->array_layout == ALL_SLICES_AT_EACH_LOD) { return ALIGN_NPOT(minify(mt->physical_height0, level), mt->align_h); } else { const unsigned h0 = ALIGN_NPOT(mt->physical_height0, mt->align_h); const unsigned h1 = ALIGN_NPOT(minify(mt->physical_height0, 1), mt->align_h); return h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h; } }
void brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt) { bool multisampled = mt->num_samples > 1; bool gen6_hiz_or_stencil = false; if (brw->gen == 6 && mt->array_layout == ALL_SLICES_AT_EACH_LOD) { const GLenum base_format = _mesa_get_format_base_format(mt->format); gen6_hiz_or_stencil = _mesa_is_depth_or_stencil_format(base_format); } if (gen6_hiz_or_stencil) { /* On gen6, we use ALL_SLICES_AT_EACH_LOD for stencil/hiz because the * hardware doesn't support multiple mip levels on stencil/hiz. * * PRM Vol 2, Part 1, 7.5.3 Hierarchical Depth Buffer: * "The hierarchical depth buffer does not support the LOD field" * * PRM Vol 2, Part 1, 7.5.4.1 Separate Stencil Buffer: * "The stencil depth buffer does not support the LOD field" */ if (mt->format == MESA_FORMAT_S_UINT8) { /* Stencil uses W tiling, so we force W tiling alignment for the * ALL_SLICES_AT_EACH_LOD miptree layout. */ mt->align_w = 64; mt->align_h = 64; } else { /* Depth uses Y tiling, so we force need Y tiling alignment for the * ALL_SLICES_AT_EACH_LOD miptree layout. */ mt->align_w = 128 / mt->cpp; mt->align_h = 32; } } else { mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt); mt->align_h = intel_vertical_texture_alignment_unit(brw, mt->format, multisampled); } switch (mt->target) { case GL_TEXTURE_CUBE_MAP: if (brw->gen == 4) { /* Gen4 stores cube maps as 3D textures. */ assert(mt->physical_depth0 == 6); brw_miptree_layout_texture_3d(brw, mt); } else { /* All other hardware stores cube maps as 2D arrays. */ brw_miptree_layout_texture_array(brw, mt); } break; case GL_TEXTURE_3D: if (brw->gen >= 9) brw_miptree_layout_texture_array(brw, mt); else brw_miptree_layout_texture_3d(brw, mt); break; case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: brw_miptree_layout_texture_array(brw, mt); break; default: switch (mt->msaa_layout) { case INTEL_MSAA_LAYOUT_UMS: case INTEL_MSAA_LAYOUT_CMS: brw_miptree_layout_texture_array(brw, mt); break; case INTEL_MSAA_LAYOUT_NONE: case INTEL_MSAA_LAYOUT_IMS: if (use_linear_1d_layout(brw, mt)) gen9_miptree_layout_1d(mt); else brw_miptree_layout_2d(mt); break; } break; } DBG("%s: %dx%dx%d\n", __FUNCTION__, mt->total_width, mt->total_height, mt->cpp); }
static void intel_miptree_set_alignment(struct brw_context *brw, struct intel_mipmap_tree *mt, uint32_t layout_flags) { /** * From the "Alignment Unit Size" section of various specs, namely: * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 * - BSpec (for Ivybridge and slight variations in separate stencil) */ bool gen6_hiz_or_stencil = false; if (brw->gen == 6 && mt->array_layout == ALL_SLICES_AT_EACH_LOD) { const GLenum base_format = _mesa_get_format_base_format(mt->format); gen6_hiz_or_stencil = _mesa_is_depth_or_stencil_format(base_format); } if (gen6_hiz_or_stencil) { /* On gen6, we use ALL_SLICES_AT_EACH_LOD for stencil/hiz because the * hardware doesn't support multiple mip levels on stencil/hiz. * * PRM Vol 2, Part 1, 7.5.3 Hierarchical Depth Buffer: * "The hierarchical depth buffer does not support the LOD field" * * PRM Vol 2, Part 1, 7.5.4.1 Separate Stencil Buffer: * "The stencil depth buffer does not support the LOD field" */ if (mt->format == MESA_FORMAT_S_UINT8) { /* Stencil uses W tiling, so we force W tiling alignment for the * ALL_SLICES_AT_EACH_LOD miptree layout. */ mt->align_w = 64; mt->align_h = 64; assert((layout_flags & MIPTREE_LAYOUT_FORCE_HALIGN16) == 0); } else { /* Depth uses Y tiling, so we force need Y tiling alignment for the * ALL_SLICES_AT_EACH_LOD miptree layout. */ mt->align_w = 128 / mt->cpp; mt->align_h = 32; } } else if (mt->compressed) { /* The hardware alignment requirements for compressed textures * happen to match the block boundaries. */ _mesa_get_format_block_size(mt->format, &mt->align_w, &mt->align_h); /* On Gen9+ we can pick our own alignment for compressed textures but it * has to be a multiple of the block size. The minimum alignment we can * pick is 4 so we effectively have to align to 4 times the block * size */ if (brw->gen >= 9) { mt->align_w *= 4; mt->align_h *= 4; } } else if (mt->format == MESA_FORMAT_S_UINT8) { mt->align_w = 8; mt->align_h = brw->gen >= 7 ? 8 : 4; } else if (brw->gen >= 9 && mt->tr_mode != INTEL_MIPTREE_TRMODE_NONE) { /* XY_FAST_COPY_BLT doesn't support horizontal alignment < 32 or * vertical alignment < 64. */ mt->align_w = MAX2(tr_mode_horizontal_texture_alignment(brw, mt), 32); mt->align_h = MAX2(tr_mode_vertical_texture_alignment(brw, mt), 64); } else { mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt, layout_flags); mt->align_h = intel_vertical_texture_alignment_unit(brw, mt); } }
/** * Helper for checking a requested sample count against the limit * for a particular (target, internalFormat) pair. The limit imposed, * and the error generated, both depend on which extensions are supported. * * Returns a GL error enum, or GL_NO_ERROR if the requested sample count is * acceptable. */ GLenum _mesa_check_sample_count(struct gl_context *ctx, GLenum target, GLenum internalFormat, GLsizei samples) { /* If ARB_internalformat_query is supported, then treat its highest * returned sample count as the absolute maximum for this format; it is * allowed to exceed MAX_SAMPLES. * * From the ARB_internalformat_query spec: * * "If <samples is greater than the maximum number of samples supported * for <internalformat> then the error INVALID_OPERATION is generated." */ if (ctx->Extensions.ARB_internalformat_query) { GLint buffer[16]; int count = ctx->Driver.QuerySamplesForFormat(ctx, target, internalFormat, buffer); int limit = count ? buffer[0] : -1; return samples > limit ? GL_INVALID_OPERATION : GL_NO_ERROR; } /* If ARB_texture_multisample is supported, we have separate limits, * which may be lower than MAX_SAMPLES: * * From the ARB_texture_multisample spec, when describing the operation * of RenderbufferStorageMultisample: * * "If <internalformat> is a signed or unsigned integer format and * <samples> is greater than the value of MAX_INTEGER_SAMPLES, then the * error INVALID_OPERATION is generated" * * And when describing the operation of TexImage*Multisample: * * "The error INVALID_OPERATION may be generated if any of the following * are true: * * * <internalformat> is a depth/stencil-renderable format and <samples> * is greater than the value of MAX_DEPTH_TEXTURE_SAMPLES * * <internalformat> is a color-renderable format and <samples> is * grater than the value of MAX_COLOR_TEXTURE_SAMPLES * * <internalformat> is a signed or unsigned integer format and * <samples> is greater than the value of MAX_INTEGER_SAMPLES */ if (ctx->Extensions.ARB_texture_multisample) { if (_mesa_is_enum_format_integer(internalFormat)) return samples > ctx->Const.MaxIntegerSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; if (target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { if (_mesa_is_depth_or_stencil_format(internalFormat)) return samples > ctx->Const.MaxDepthTextureSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; else return samples > ctx->Const.MaxColorTextureSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; } } /* No more specific limit is available, so just use MAX_SAMPLES: * * On p205 of the GL3.1 spec: * * "... or if samples is greater than MAX_SAMPLES, then the error * INVALID_VALUE is generated" */ return (GLuint) samples > ctx->Const.MaxSamples ? GL_INVALID_VALUE : GL_NO_ERROR; }
/** * Helper for checking a requested sample count against the limit * for a particular (target, internalFormat) pair. The limit imposed, * and the error generated, both depend on which extensions are supported. * * Returns a GL error enum, or GL_NO_ERROR if the requested sample count is * acceptable. */ GLenum _mesa_check_sample_count(struct gl_context *ctx, GLenum target, GLenum internalFormat, GLsizei samples) { /* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0 * specification says: * * "If internalformat is a signed or unsigned integer format and samples * is greater than zero, then the error INVALID_OPERATION is generated." * * This restriction is relaxed for OpenGL ES 3.1. */ if ((ctx->API == API_OPENGLES2 && ctx->Version == 30) && _mesa_is_enum_format_integer(internalFormat) && samples > 0) { return GL_INVALID_OPERATION; } /* If ARB_internalformat_query is supported, then treat its highest * returned sample count as the absolute maximum for this format; it is * allowed to exceed MAX_SAMPLES. * * From the ARB_internalformat_query spec: * * "If <samples is greater than the maximum number of samples supported * for <internalformat> then the error INVALID_OPERATION is generated." */ if (ctx->Extensions.ARB_internalformat_query) { GLint buffer[16] = {-1}; GLint limit; ctx->Driver.QueryInternalFormat(ctx, target, internalFormat, GL_SAMPLES, buffer); /* since the query returns samples sorted in descending order, * the first element is the greatest supported sample value. */ limit = buffer[0]; return samples > limit ? GL_INVALID_OPERATION : GL_NO_ERROR; } /* If ARB_texture_multisample is supported, we have separate limits, * which may be lower than MAX_SAMPLES: * * From the ARB_texture_multisample spec, when describing the operation * of RenderbufferStorageMultisample: * * "If <internalformat> is a signed or unsigned integer format and * <samples> is greater than the value of MAX_INTEGER_SAMPLES, then the * error INVALID_OPERATION is generated" * * And when describing the operation of TexImage*Multisample: * * "The error INVALID_OPERATION may be generated if any of the following * are true: * * * <internalformat> is a depth/stencil-renderable format and <samples> * is greater than the value of MAX_DEPTH_TEXTURE_SAMPLES * * <internalformat> is a color-renderable format and <samples> is * grater than the value of MAX_COLOR_TEXTURE_SAMPLES * * <internalformat> is a signed or unsigned integer format and * <samples> is greater than the value of MAX_INTEGER_SAMPLES */ if (ctx->Extensions.ARB_texture_multisample) { if (_mesa_is_enum_format_integer(internalFormat)) return samples > ctx->Const.MaxIntegerSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; if (target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { if (_mesa_is_depth_or_stencil_format(internalFormat)) return samples > ctx->Const.MaxDepthTextureSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; else return samples > ctx->Const.MaxColorTextureSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; } } /* No more specific limit is available, so just use MAX_SAMPLES: * * On p205 of the GL3.1 spec: * * "... or if samples is greater than MAX_SAMPLES, then the error * INVALID_VALUE is generated" */ return (GLuint) samples > ctx->Const.MaxSamples ? GL_INVALID_VALUE : GL_NO_ERROR; }