diff options
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp b/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp index 4d616c78e78..9682ca33189 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp @@ -163,6 +163,154 @@ namespace brw { } namespace { + namespace image_format_info { + /** + * Simple 4-tuple of scalars used to pass around per-color component + * values. + */ + struct color_u { + color_u(unsigned x = 0) : r(x), g(x), b(x), a(x) + { + } + + color_u(unsigned r, unsigned g, unsigned b, unsigned a) : + r(r), g(g), b(b), a(a) + { + } + + unsigned + operator[](unsigned i) const + { + const unsigned xs[] = { r, g, b, a }; + return xs[i]; + } + + unsigned r, g, b, a; + }; + + /** + * Return the per-channel bitfield widths for a given image format. + */ + inline color_u + get_bit_widths(mesa_format format) + { + return color_u(_mesa_get_format_bits(format, GL_RED_BITS), + _mesa_get_format_bits(format, GL_GREEN_BITS), + _mesa_get_format_bits(format, GL_BLUE_BITS), + _mesa_get_format_bits(format, GL_ALPHA_BITS)); + } + + /** + * Return the per-channel bitfield shifts for a given image format. + */ + inline color_u + get_bit_shifts(mesa_format format) + { + const color_u widths = get_bit_widths(format); + return color_u(0, widths.r, widths.r + widths.g, + widths.r + widths.g + widths.b); + } + + /** + * Return true if all present components have the same bit width. + */ + inline bool + is_homogeneous(mesa_format format) + { + const color_u widths = get_bit_widths(format); + return ((widths.g == 0 || widths.g == widths.r) && + (widths.b == 0 || widths.b == widths.r) && + (widths.a == 0 || widths.a == widths.r)); + } + + /** + * Return true if the format conversion boils down to a trivial copy. + */ + inline bool + is_conversion_trivial(const brw_device_info *devinfo, mesa_format format) + { + return (get_bit_widths(format).r == 32 && is_homogeneous(format)) || + format == brw_lower_mesa_image_format(devinfo, format); + } + + /** + * Return true if the hardware natively supports some format with + * compatible bitfield layout, but possibly different data types. + */ + inline bool + has_supported_bit_layout(const brw_device_info *devinfo, + mesa_format format) + { + const color_u widths = get_bit_widths(format); + const color_u lower_widths = get_bit_widths( + brw_lower_mesa_image_format(devinfo, format)); + + return (widths.r == lower_widths.r && + widths.g == lower_widths.g && + widths.b == lower_widths.b && + widths.a == lower_widths.a); + } + + /** + * Return true if we are required to spread individual components over + * several components of the format used by the hardware (RG32 and + * friends implemented as RGBA16UI). + */ + inline bool + has_split_bit_layout(const brw_device_info *devinfo, mesa_format format) + { + const mesa_format lower_format = + brw_lower_mesa_image_format(devinfo, format); + + return (_mesa_format_num_components(format) < + _mesa_format_num_components(lower_format)); + } + + /** + * Return true unless we have to fall back to untyped surface access. + * Fail! + */ + inline bool + has_matching_typed_format(const brw_device_info *devinfo, + mesa_format format) + { + return (_mesa_get_format_bytes(format) <= 4 || + (_mesa_get_format_bytes(format) <= 8 && + (devinfo->gen >= 8 || devinfo->is_haswell)) || + devinfo->gen >= 9); + } + + /** + * Return true if the hardware returns garbage in the unused high bits + * of each component. This may happen on IVB because we rely on the + * undocumented behavior that typed reads from surfaces of the + * unsupported R8 and R16 formats return useful data in their least + * significant bits. + */ + inline bool + has_undefined_high_bits(const brw_device_info *devinfo, + mesa_format format) + { + const mesa_format lower_format = + brw_lower_mesa_image_format(devinfo, format); + + return (devinfo->gen == 7 && !devinfo->is_haswell && + (lower_format == MESA_FORMAT_R_UINT16 || + lower_format == MESA_FORMAT_R_UINT8)); + } + + /** + * Return true if the format represents values as signed integers + * requiring sign extension when unpacking. + */ + inline bool + needs_sign_extension(mesa_format format) + { + return (_mesa_get_format_datatype(format) == GL_SIGNED_NORMALIZED || + _mesa_get_format_datatype(format) == GL_INT); + } + } + namespace image_validity { /** * Check whether there is an image bound at the given index and write |