*/
#include "brw_context.h"
+#include "brw_defines.h"
#include "intel_fbo.h"
#include "brw_meta_util.h"
#include "brw_state.h"
* 4 * 2 = 8 > 5 in the src.
*/
+ if (*srcX0 == *srcX1 || *srcY0 == *srcY1
+ || *dstX0 == *dstX1 || *dstY0 == *dstY1)
+ return true;
+
float scaleX = (float) (*srcX1 - *srcX0) / (*dstX1 - *dstX0);
float scaleY = (float) (*srcY1 - *srcY0) / (*dstY1 - *dstY0);
/* Account for the fact that in the system framebuffer, the origin is at
* the lower left.
*/
- if (_mesa_is_winsys_fbo(read_fb)) {
+ if (read_fb->FlipY) {
GLint tmp = read_fb->Height - *srcY0;
*srcY0 = read_fb->Height - *srcY1;
*srcY1 = tmp;
*mirror_y = !*mirror_y;
}
- if (_mesa_is_winsys_fbo(draw_fb)) {
+ if (draw_fb->FlipY) {
GLint tmp = draw_fb->Height - *dstY0;
*dstY0 = draw_fb->Height - *dstY1;
*dstY1 = tmp;
*mirror_y = !*mirror_y;
}
- return false;
-}
-
-/**
- * Creates a new named renderbuffer that wraps the first slice
- * of an existing miptree.
- *
- * Clobbers the current renderbuffer binding (ctx->CurrentRenderbuffer).
- */
-struct gl_renderbuffer *
-brw_get_rb_for_slice(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
- unsigned level, unsigned layer, bool flat)
-{
- struct gl_context *ctx = &brw->ctx;
- struct gl_renderbuffer *rb = ctx->Driver.NewRenderbuffer(ctx, 0xDEADBEEF);
- struct intel_renderbuffer *irb = intel_renderbuffer(rb);
-
- rb->RefCount = 1;
- rb->Format = mt->format;
- rb->_BaseFormat = _mesa_get_format_base_format(mt->format);
-
- /* Program takes care of msaa and mip-level access manually for stencil.
- * The surface is also treated as Y-tiled instead of as W-tiled calling for
- * twice the width and half the height in dimensions.
+ /* Check for invalid bounds
+ * Can't blit for 0-dimensions
*/
- if (flat) {
- const unsigned halign_stencil = 8;
-
- rb->NumSamples = 0;
- rb->Width = ALIGN(mt->total_width, halign_stencil) * 2;
- rb->Height = (mt->total_height / mt->physical_depth0) / 2;
- irb->mt_level = 0;
- } else {
- rb->NumSamples = mt->num_samples;
- rb->Width = mt->logical_width0;
- rb->Height = mt->logical_height0;
- irb->mt_level = level;
- }
-
- irb->mt_layer = layer;
-
- intel_miptree_reference(&irb->mt, mt);
-
- return rb;
+ return *srcX0 == *srcX1 || *srcY0 == *srcY1
+ || *dstX0 == *dstX1 || *dstY0 == *dstY1;
}
/**
const struct intel_mipmap_tree *mt,
const union gl_color_union *color)
{
+ const struct gen_device_info *devinfo = &brw->screen->devinfo;
const struct gl_context *ctx = &brw->ctx;
/* If we're mapping the render format to a different format than the
* state so the hardware probably legitimately doesn't need to support
* this case. At least on Gen9 this really does seem to cause problems.
*/
- if (brw->gen >= 9 &&
- brw_format_for_mesa_format(mt->format) !=
- brw->render_target_format[mt->format])
- return false;
-
- /* Gen9 doesn't support fast clear on single-sampled SRGB buffers. When
- * GL_FRAMEBUFFER_SRGB is enabled any color renderbuffers will be
- * resolved in intel_update_state. In that case it's pointless to do a
- * fast clear because it's very likely to be immediately resolved.
- */
- if (brw->gen >= 9 &&
- mt->num_samples <= 1 &&
- ctx->Color.sRGBEnabled &&
- _mesa_get_srgb_format_linear(mt->format) != mt->format)
+ if (devinfo->gen >= 9 &&
+ brw_isl_format_for_mesa_format(mt->format) !=
+ brw->mesa_to_isl_render_format[mt->format])
return false;
const mesa_format format = _mesa_get_render_format(ctx, mt->format);
if (_mesa_is_format_integer_color(format)) {
- if (brw->gen >= 8) {
+ if (devinfo->gen >= 8) {
perf_debug("Integer fast clear not enabled for (%s)",
_mesa_get_format_name(format));
}
continue;
}
- if (brw->gen < 9 &&
+ if (devinfo->gen < 9 &&
color->f[i] != 0.0f && color->f[i] != 1.0f) {
return false;
}
/**
* Convert the given color to a bitfield suitable for ORing into DWORD 7 of
* SURFACE_STATE (DWORD 12-15 on SKL+).
- *
- * Returned boolean tells if the given color differs from the stored.
*/
-bool
-brw_meta_set_fast_clear_color(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
- const union gl_color_union *color)
+union isl_color_value
+brw_meta_convert_fast_clear_color(const struct brw_context *brw,
+ const struct intel_mipmap_tree *mt,
+ const union gl_color_union *color)
{
- union gl_color_union override_color = *color;
+ union isl_color_value override_color = {
+ .u32 = {
+ color->ui[0],
+ color->ui[1],
+ color->ui[2],
+ color->ui[3],
+ },
+ };
/* The sampler doesn't look at the format of the surface when the fast
* clear color is used so we need to implement luminance, intensity and
*/
switch (_mesa_get_format_base_format(mt->format)) {
case GL_INTENSITY:
- override_color.ui[3] = override_color.ui[0];
+ override_color.u32[3] = override_color.u32[0];
/* flow through */
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
- override_color.ui[1] = override_color.ui[0];
- override_color.ui[2] = override_color.ui[0];
+ override_color.u32[1] = override_color.u32[0];
+ override_color.u32[2] = override_color.u32[0];
break;
default:
for (int i = 0; i < 3; i++) {
if (!_mesa_format_has_color_component(mt->format, i))
- override_color.ui[i] = 0;
+ override_color.u32[i] = 0;
}
break;
}
- if (!_mesa_format_has_color_component(mt->format, 3)) {
- if (_mesa_is_format_integer_color(mt->format))
- override_color.ui[3] = 1;
- else
- override_color.f[3] = 1.0f;
- }
-
- /* Handle linear→SRGB conversion */
- if (brw->ctx.Color.sRGBEnabled &&
- _mesa_get_srgb_format_linear(mt->format) != mt->format) {
- for (int i = 0; i < 3; i++) {
- override_color.f[i] =
- util_format_linear_to_srgb_float(override_color.f[i]);
- }
- }
+ switch (_mesa_get_format_datatype(mt->format)) {
+ case GL_UNSIGNED_NORMALIZED:
+ for (int i = 0; i < 4; i++)
+ override_color.f32[i] = CLAMP(override_color.f32[i], 0.0f, 1.0f);
+ break;
- bool updated;
- if (brw->gen >= 9) {
- updated = memcmp(&mt->gen9_fast_clear_color, &override_color,
- sizeof(mt->gen9_fast_clear_color));
- mt->gen9_fast_clear_color = override_color;
- } else {
- const uint32_t old_color_value = mt->fast_clear_color_value;
+ case GL_SIGNED_NORMALIZED:
+ for (int i = 0; i < 4; i++)
+ override_color.f32[i] = CLAMP(override_color.f32[i], -1.0f, 1.0f);
+ break;
- mt->fast_clear_color_value = 0;
+ case GL_UNSIGNED_INT:
for (int i = 0; i < 4; i++) {
- /* Testing for non-0 works for integer and float colors */
- if (override_color.f[i] != 0.0f) {
- mt->fast_clear_color_value |=
- 1 << (GEN7_SURFACE_CLEAR_COLOR_SHIFT + (3 - i));
+ unsigned bits = _mesa_get_format_bits(mt->format, GL_RED_BITS + i);
+ if (bits < 32) {
+ uint32_t max = (1u << bits) - 1;
+ override_color.u32[i] = MIN2(override_color.u32[i], max);
}
}
+ break;
- updated = (old_color_value != mt->fast_clear_color_value);
- }
-
- return updated;
-}
+ case GL_INT:
+ for (int i = 0; i < 4; i++) {
+ unsigned bits = _mesa_get_format_bits(mt->format, GL_RED_BITS + i);
+ if (bits < 32) {
+ int32_t max = (1 << (bits - 1)) - 1;
+ int32_t min = -(1 << (bits - 1));
+ override_color.i32[i] = CLAMP(override_color.i32[i], min, max);
+ }
+ }
+ break;
-void
-brw_get_fast_clear_rect(const struct brw_context *brw,
- const struct gl_framebuffer *fb,
- const struct intel_mipmap_tree* mt,
- unsigned *x0, unsigned *y0,
- unsigned *x1, unsigned *y1)
-{
- unsigned int x_align, y_align;
- unsigned int x_scaledown, y_scaledown;
-
- /* Only single sampled surfaces need to (and actually can) be resolved. */
- if (mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE ||
- intel_miptree_is_lossless_compressed(brw, mt)) {
- /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
- * Target(s)", beneath the "Fast Color Clear" bullet (p327):
- *
- * Clear pass must have a clear rectangle that must follow
- * alignment rules in terms of pixels and lines as shown in the
- * table below. Further, the clear-rectangle height and width
- * must be multiple of the following dimensions. If the height
- * and width of the render target being cleared do not meet these
- * requirements, an MCS buffer can be created such that it
- * follows the requirement and covers the RT.
- *
- * The alignment size in the table that follows is related to the
- * alignment size returned by intel_get_non_msrt_mcs_alignment(), but
- * with X alignment multiplied by 16 and Y alignment multiplied by 32.
- */
- intel_get_non_msrt_mcs_alignment(mt, &x_align, &y_align);
- x_align *= 16;
-
- /* SKL+ line alignment requirement for Y-tiled are half those of the prior
- * generations.
- */
- if (brw->gen >= 9)
- y_align *= 16;
- else
- y_align *= 32;
-
- /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
- * Target(s)", beneath the "Fast Color Clear" bullet (p327):
- *
- * In order to optimize the performance MCS buffer (when bound to
- * 1X RT) clear similarly to MCS buffer clear for MSRT case,
- * clear rect is required to be scaled by the following factors
- * in the horizontal and vertical directions:
- *
- * The X and Y scale down factors in the table that follows are each
- * equal to half the alignment value computed above.
- */
- x_scaledown = x_align / 2;
- y_scaledown = y_align / 2;
-
- /* From BSpec: 3D-Media-GPGPU Engine > 3D Pipeline > Pixel > Pixel
- * Backend > MCS Buffer for Render Target(s) [DevIVB+] > Table "Color
- * Clear of Non-MultiSampled Render Target Restrictions":
- *
- * Clear rectangle must be aligned to two times the number of
- * pixels in the table shown below due to 16x16 hashing across the
- * slice.
- */
- x_align *= 2;
- y_align *= 2;
- } else {
- /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
- * Target(s)", beneath the "MSAA Compression" bullet (p326):
- *
- * Clear pass for this case requires that scaled down primitive
- * is sent down with upper left co-ordinate to coincide with
- * actual rectangle being cleared. For MSAA, clear rectangle’s
- * height and width need to as show in the following table in
- * terms of (width,height) of the RT.
- *
- * MSAA Width of Clear Rect Height of Clear Rect
- * 2X Ceil(1/8*width) Ceil(1/2*height)
- * 4X Ceil(1/8*width) Ceil(1/2*height)
- * 8X Ceil(1/2*width) Ceil(1/2*height)
- * 16X width Ceil(1/2*height)
- *
- * The text "with upper left co-ordinate to coincide with actual
- * rectangle being cleared" is a little confusing--it seems to imply
- * that to clear a rectangle from (x,y) to (x+w,y+h), one needs to
- * feed the pipeline using the rectangle (x,y) to
- * (x+Ceil(w/N),y+Ceil(h/2)), where N is either 2 or 8 depending on
- * the number of samples. Experiments indicate that this is not
- * quite correct; actually, what the hardware appears to do is to
- * align whatever rectangle is sent down the pipeline to the nearest
- * multiple of 2x2 blocks, and then scale it up by a factor of N
- * horizontally and 2 vertically. So the resulting alignment is 4
- * vertically and either 4 or 16 horizontally, and the scaledown
- * factor is 2 vertically and either 2 or 8 horizontally.
- */
- switch (mt->num_samples) {
- case 2:
- case 4:
- x_scaledown = 8;
- break;
- case 8:
- x_scaledown = 2;
- break;
- case 16:
- x_scaledown = 1;
- break;
- default:
- unreachable("Unexpected sample count for fast clear");
+ case GL_FLOAT:
+ if (!_mesa_is_format_signed(mt->format)) {
+ for (int i = 0; i < 4; i++)
+ override_color.f32[i] = MAX2(override_color.f32[i], 0.0f);
}
- y_scaledown = 2;
- x_align = x_scaledown * 2;
- y_align = y_scaledown * 2;
+ break;
}
- *x0 = fb->_Xmin;
- *x1 = fb->_Xmax;
- if (fb->Name != 0) {
- *y0 = fb->_Ymin;
- *y1 = fb->_Ymax;
- } else {
- *y0 = fb->Height - fb->_Ymax;
- *y1 = fb->Height - fb->_Ymin;
+ if (!_mesa_format_has_color_component(mt->format, 3)) {
+ if (_mesa_is_format_integer_color(mt->format))
+ override_color.u32[3] = 1;
+ else
+ override_color.f32[3] = 1.0f;
}
- *x0 = ROUND_DOWN_TO(*x0, x_align) / x_scaledown;
- *y0 = ROUND_DOWN_TO(*y0, y_align) / y_scaledown;
- *x1 = ALIGN(*x1, x_align) / x_scaledown;
- *y1 = ALIGN(*y1, y_align) / y_scaledown;
-}
-
-void
-brw_meta_get_buffer_rect(const struct gl_framebuffer *fb,
- unsigned *x0, unsigned *y0,
- unsigned *x1, unsigned *y1)
-{
- *x0 = fb->_Xmin;
- *x1 = fb->_Xmax;
- if (fb->Name != 0) {
- *y0 = fb->_Ymin;
- *y1 = fb->_Ymax;
- } else {
- *y0 = fb->Height - fb->_Ymax;
- *y1 = fb->Height - fb->_Ymin;
+ /* Handle linear to SRGB conversion */
+ if (brw->ctx.Color.sRGBEnabled &&
+ _mesa_get_srgb_format_linear(mt->format) != mt->format) {
+ for (int i = 0; i < 3; i++) {
+ override_color.f32[i] =
+ util_format_linear_to_srgb_float(override_color.f32[i]);
+ }
}
-}
-
-void
-brw_get_ccs_resolve_rect(const struct isl_device *dev,
- const struct isl_surf *ccs_surf,
- unsigned *x0, unsigned *y0,
- unsigned *x1, unsigned *y1)
-{
- unsigned x_scaledown, y_scaledown;
- /* From the Ivy Bridge PRM, Vol2 Part1 11.9 "Render Target Resolve":
- *
- * A rectangle primitive must be scaled down by the following factors
- * with respect to render target being resolved.
- *
- * The scaledown factors in the table that follows are related to the block
- * size of the CCS format. For IVB and HSW, we divide by two, for BDW we
- * multiply by 8 and 16. On Sky Lake, we multiply by 8.
- */
- const struct isl_format_layout *fmtl =
- isl_format_get_layout(ccs_surf->format);
- assert(fmtl->txc == ISL_TXC_CCS);
-
- if (ISL_DEV_GEN(dev) >= 9) {
- x_scaledown = fmtl->bw * 8;
- y_scaledown = fmtl->bh * 8;
- } else if (ISL_DEV_GEN(dev) >= 8) {
- x_scaledown = fmtl->bw * 8;
- y_scaledown = fmtl->bh * 16;
- } else {
- x_scaledown = fmtl->bw / 2;
- y_scaledown = fmtl->bh / 2;
- }
- *x0 = *y0 = 0;
- *x1 = ALIGN(ccs_surf->logical_level0_px.width, x_scaledown) / x_scaledown;
- *y1 = ALIGN(ccs_surf->logical_level0_px.height, y_scaledown) / y_scaledown;
+ return override_color;
}