+void
+intel_resolve_for_dri2_flush(struct intel_context *intel,
+ __DRIdrawable *drawable)
+{
+ if (intel->gen < 6) {
+ /* MSAA and fast color clear are not supported, so don't waste time
+ * checking whether a resolve is needed.
+ */
+ return;
+ }
+
+ struct gl_framebuffer *fb = drawable->driverPrivate;
+ struct intel_renderbuffer *rb;
+
+ /* Usually, only the back buffer will need to be downsampled. However,
+ * the front buffer will also need it if the user has rendered into it.
+ */
+ static const gl_buffer_index buffers[2] = {
+ BUFFER_BACK_LEFT,
+ BUFFER_FRONT_LEFT,
+ };
+
+ for (int i = 0; i < 2; ++i) {
+ rb = intel_get_renderbuffer(fb, buffers[i]);
+ if (rb == NULL || rb->mt == NULL)
+ continue;
+ if (rb->mt->num_samples <= 1)
+ intel_miptree_resolve_color(intel, rb->mt);
+ else
+ intel_miptree_downsample(intel, rb->mt);
+ }
+}
+
+static void
+intel_flush_front(struct gl_context *ctx)
+{
+ struct intel_context *intel = intel_context(ctx);
+ __DRIcontext *driContext = intel->driContext;
+ __DRIdrawable *driDrawable = driContext->driDrawablePriv;
+ __DRIscreen *const screen = intel->intelScreen->driScrnPriv;
+
+ if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
+ if (screen->dri2.loader->flushFrontBuffer != NULL &&
+ driDrawable &&
+ driDrawable->loaderPrivate) {
+
+ /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
+ *
+ * This potentially resolves both front and back buffer. It
+ * is unnecessary to resolve the back, but harms nothing except
+ * performance. And no one cares about front-buffer render
+ * performance.
+ */
+ intel_resolve_for_dri2_flush(intel, driDrawable);
+
+ screen->dri2.loader->flushFrontBuffer(driDrawable,
+ driDrawable->loaderPrivate);
+
+ /* We set the dirty bit in intel_prepare_render() if we're
+ * front buffer rendering once we get there.
+ */
+ intel->front_buffer_dirty = false;
+ }
+ }
+}
+
+static unsigned
+intel_bits_per_pixel(const struct intel_renderbuffer *rb)
+{
+ return _mesa_get_format_bytes(intel_rb_format(rb)) * 8;
+}
+
+static void
+intel_query_dri2_buffers(struct intel_context *intel,
+ __DRIdrawable *drawable,
+ __DRIbuffer **buffers,
+ int *count);
+
+static void
+intel_process_dri2_buffer(struct intel_context *intel,
+ __DRIdrawable *drawable,
+ __DRIbuffer *buffer,
+ struct intel_renderbuffer *rb,
+ const char *buffer_name);
+
+void
+intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+{
+ struct gl_framebuffer *fb = drawable->driverPrivate;
+ struct intel_renderbuffer *rb;
+ struct intel_context *intel = context->driverPrivate;
+ __DRIbuffer *buffers = NULL;
+ int i, count;
+ const char *region_name;
+
+ /* Set this up front, so that in case our buffers get invalidated
+ * while we're getting new buffers, we don't clobber the stamp and
+ * thus ignore the invalidate. */
+ drawable->lastStamp = drawable->dri2.stamp;
+
+ if (unlikely(INTEL_DEBUG & DEBUG_DRI))
+ fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
+
+ intel_query_dri2_buffers(intel, drawable, &buffers, &count);
+
+ if (buffers == NULL)
+ return;
+
+ for (i = 0; i < count; i++) {
+ switch (buffers[i].attachment) {
+ case __DRI_BUFFER_FRONT_LEFT:
+ rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+ region_name = "dri2 front buffer";
+ break;
+
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+ region_name = "dri2 fake front buffer";
+ break;
+
+ case __DRI_BUFFER_BACK_LEFT:
+ rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+ region_name = "dri2 back buffer";
+ break;
+
+ case __DRI_BUFFER_DEPTH:
+ case __DRI_BUFFER_HIZ:
+ case __DRI_BUFFER_DEPTH_STENCIL:
+ case __DRI_BUFFER_STENCIL:
+ case __DRI_BUFFER_ACCUM:
+ default:
+ fprintf(stderr,
+ "unhandled buffer attach event, attachment type %d\n",
+ buffers[i].attachment);
+ return;
+ }
+
+ intel_process_dri2_buffer(intel, drawable, &buffers[i], rb, region_name);
+ }
+
+ driUpdateFramebufferSize(&intel->ctx, drawable);
+}