+static void
+update_renderbuffer_read_surfaces(struct brw_context *brw)
+{
+ const struct gl_context *ctx = &brw->ctx;
+
+ /* BRW_NEW_FS_PROG_DATA */
+ const struct brw_wm_prog_data *wm_prog_data =
+ brw_wm_prog_data(brw->wm.base.prog_data);
+
+ /* BRW_NEW_FRAGMENT_PROGRAM */
+ if (!ctx->Extensions.MESA_shader_framebuffer_fetch &&
+ brw->fragment_program && brw->fragment_program->info.outputs_read) {
+ /* _NEW_BUFFERS */
+ const struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ for (unsigned i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[i];
+ const struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ const unsigned surf_index =
+ wm_prog_data->binding_table.render_target_read_start + i;
+ uint32_t *surf_offset = &brw->wm.base.surf_offset[surf_index];
+
+ if (irb) {
+ const unsigned format = brw->render_target_format[
+ _mesa_get_render_format(ctx, intel_rb_format(irb))];
+ assert(isl_format_supports_sampling(&brw->screen->devinfo,
+ format));
+
+ /* Override the target of the texture if the render buffer is a
+ * single slice of a 3D texture (since the minimum array element
+ * field of the surface state structure is ignored by the sampler
+ * unit for 3D textures on some hardware), or if the render buffer
+ * is a 1D array (since shaders always provide the array index
+ * coordinate at the Z component to avoid state-dependent
+ * recompiles when changing the texture target of the
+ * framebuffer).
+ */
+ const GLenum target =
+ (irb->mt->target == GL_TEXTURE_3D &&
+ irb->layer_count == 1) ? GL_TEXTURE_2D :
+ irb->mt->target == GL_TEXTURE_1D_ARRAY ? GL_TEXTURE_2D_ARRAY :
+ irb->mt->target;
+
+ /* intel_renderbuffer::mt_layer is expressed in sample units for
+ * the UMS and CMS multisample layouts, but
+ * intel_renderbuffer::layer_count is expressed in units of whole
+ * logical layers regardless of the multisample layout.
+ */
+ const unsigned mt_layer_unit =
+ (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS ||
+ irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) ?
+ MAX2(irb->mt->num_samples, 1) : 1;
+
+ const struct isl_view view = {
+ .format = format,
+ .base_level = irb->mt_level - irb->mt->first_level,
+ .levels = 1,
+ .base_array_layer = irb->mt_layer / mt_layer_unit,
+ .array_len = irb->layer_count,
+ .swizzle = ISL_SWIZZLE_IDENTITY,
+ .usage = ISL_SURF_USAGE_TEXTURE_BIT,
+ };
+
+ const int flags = brw->draw_aux_buffer_disabled[i] ?
+ INTEL_AUX_BUFFER_DISABLED : 0;
+ brw_emit_surface_state(brw, irb->mt, flags, target, view,
+ tex_mocs[brw->gen],
+ surf_offset, surf_index,
+ I915_GEM_DOMAIN_SAMPLER, 0);
+
+ } else {
+ brw->vtbl.emit_null_surface_state(
+ brw, _mesa_geometric_width(fb), _mesa_geometric_height(fb),
+ _mesa_geometric_samples(fb), surf_offset);
+ }
+ }
+
+ brw->ctx.NewDriverState |= BRW_NEW_SURFACES;
+ }
+}
+
+const struct brw_tracked_state brw_renderbuffer_read_surfaces = {
+ .dirty = {
+ .mesa = _NEW_BUFFERS,
+ .brw = BRW_NEW_BATCH |
+ BRW_NEW_FRAGMENT_PROGRAM |
+ BRW_NEW_FS_PROG_DATA,
+ },
+ .emit = update_renderbuffer_read_surfaces,
+};