+ if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) {
+ /* Turn on some extra GL_ARB_debug_output generation. */
+ brw->perf_debug = true;
+ }
+
+ if ((flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS) != 0)
+ ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB;
+
+ if (INTEL_DEBUG & DEBUG_SHADER_TIME)
+ brw_init_shader_time(brw);
+
+ _mesa_compute_version(ctx);
+
+ _mesa_initialize_dispatch_tables(ctx);
+ _mesa_initialize_vbo_vtxfmt(ctx);
+
+ if (ctx->Extensions.AMD_performance_monitor) {
+ brw_init_performance_monitors(brw);
+ }
+
+ vbo_use_buffer_objects(ctx);
+ vbo_always_unmap_buffers(ctx);
+
+ return true;
+}
+
+void
+intelDestroyContext(__DRIcontext * driContextPriv)
+{
+ struct brw_context *brw =
+ (struct brw_context *) driContextPriv->driverPrivate;
+ struct gl_context *ctx = &brw->ctx;
+
+ assert(brw); /* should never be null */
+ if (!brw)
+ return;
+
+ /* Dump a final BMP in case the application doesn't call SwapBuffers */
+ if (INTEL_DEBUG & DEBUG_AUB) {
+ intel_batchbuffer_flush(brw);
+ aub_dump_bmp(&brw->ctx);
+ }
+
+ _mesa_meta_free(&brw->ctx);
+ brw_meta_fast_clear_free(brw);
+
+ if (INTEL_DEBUG & DEBUG_SHADER_TIME) {
+ /* Force a report. */
+ brw->shader_time.report_time = 0;
+
+ brw_collect_and_report_shader_time(brw);
+ brw_destroy_shader_time(brw);
+ }
+
+ brw_destroy_state(brw);
+ brw_draw_destroy(brw);
+
+ drm_intel_bo_unreference(brw->curbe.curbe_bo);
+
+ drm_intel_gem_context_destroy(brw->hw_ctx);
+
+ if (ctx->swrast_context) {
+ _swsetup_DestroyContext(&brw->ctx);
+ _tnl_DestroyContext(&brw->ctx);
+ }
+ _vbo_DestroyContext(&brw->ctx);
+
+ if (ctx->swrast_context)
+ _swrast_DestroyContext(&brw->ctx);
+
+ intel_batchbuffer_free(brw);
+
+ drm_intel_bo_unreference(brw->first_post_swapbuffers_batch);
+ brw->first_post_swapbuffers_batch = NULL;
+
+ driDestroyOptionCache(&brw->optionCache);
+
+ /* free the Mesa context */
+ _mesa_free_context_data(&brw->ctx);
+
+ ralloc_free(brw);
+ driContextPriv->driverPrivate = NULL;
+}
+
+GLboolean
+intelUnbindContext(__DRIcontext * driContextPriv)
+{
+ /* Unset current context and dispath table */
+ _mesa_make_current(NULL, NULL, NULL);
+
+ return true;
+}
+
+/**
+ * Fixes up the context for GLES23 with our default-to-sRGB-capable behavior
+ * on window system framebuffers.
+ *
+ * Desktop GL is fairly reasonable in its handling of sRGB: You can ask if
+ * your renderbuffer can do sRGB encode, and you can flip a switch that does
+ * sRGB encode if the renderbuffer can handle it. You can ask specifically
+ * for a visual where you're guaranteed to be capable, but it turns out that
+ * everyone just makes all their ARGB8888 visuals capable and doesn't offer
+ * incapable ones, becuase there's no difference between the two in resources
+ * used. Applications thus get built that accidentally rely on the default
+ * visual choice being sRGB, so we make ours sRGB capable. Everything sounds
+ * great...
+ *
+ * But for GLES2/3, they decided that it was silly to not turn on sRGB encode
+ * for sRGB renderbuffers you made with the GL_EXT_texture_sRGB equivalent.
+ * So they removed the enable knob and made it "if the renderbuffer is sRGB
+ * capable, do sRGB encode". Then, for your window system renderbuffers, you
+ * can ask for sRGB visuals and get sRGB encode, or not ask for sRGB visuals
+ * and get no sRGB encode (assuming that both kinds of visual are available).
+ * Thus our choice to support sRGB by default on our visuals for desktop would
+ * result in broken rendering of GLES apps that aren't expecting sRGB encode.
+ *
+ * Unfortunately, renderbuffer setup happens before a context is created. So
+ * in intel_screen.c we always set up sRGB, and here, if you're a GLES2/3
+ * context (without an sRGB visual, though we don't have sRGB visuals exposed
+ * yet), we go turn that back off before anyone finds out.
+ */
+static void
+intel_gles3_srgb_workaround(struct brw_context *brw,
+ struct gl_framebuffer *fb)
+{
+ struct gl_context *ctx = &brw->ctx;
+
+ if (_mesa_is_desktop_gl(ctx) || !fb->Visual.sRGBCapable)
+ return;
+
+ /* Some day when we support the sRGB capable bit on visuals available for
+ * GLES, we'll need to respect that and not disable things here.
+ */
+ fb->Visual.sRGBCapable = false;
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ if (fb->Attachment[i].Renderbuffer &&
+ fb->Attachment[i].Renderbuffer->Format == MESA_FORMAT_B8G8R8A8_SRGB) {
+ fb->Attachment[i].Renderbuffer->Format = MESA_FORMAT_B8G8R8A8_UNORM;
+ }
+ }
+}
+
+GLboolean
+intelMakeCurrent(__DRIcontext * driContextPriv,
+ __DRIdrawable * driDrawPriv,
+ __DRIdrawable * driReadPriv)
+{
+ struct brw_context *brw;
+ GET_CURRENT_CONTEXT(curCtx);
+
+ if (driContextPriv)
+ brw = (struct brw_context *) driContextPriv->driverPrivate;
+ else
+ brw = NULL;
+
+ /* According to the glXMakeCurrent() man page: "Pending commands to
+ * the previous context, if any, are flushed before it is released."
+ * But only flush if we're actually changing contexts.
+ */
+ if (brw_context(curCtx) && brw_context(curCtx) != brw) {
+ _mesa_flush(curCtx);
+ }
+
+ if (driContextPriv) {
+ struct gl_context *ctx = &brw->ctx;
+ struct gl_framebuffer *fb, *readFb;
+
+ if (driDrawPriv == NULL) {
+ fb = _mesa_get_incomplete_framebuffer();
+ } else {
+ fb = driDrawPriv->driverPrivate;
+ driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
+ }
+
+ if (driReadPriv == NULL) {
+ readFb = _mesa_get_incomplete_framebuffer();
+ } else {
+ readFb = driReadPriv->driverPrivate;
+ driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
+ }
+
+ /* The sRGB workaround changes the renderbuffer's format. We must change
+ * the format before the renderbuffer's miptree get's allocated, otherwise
+ * the formats of the renderbuffer and its miptree will differ.
+ */
+ intel_gles3_srgb_workaround(brw, fb);
+ intel_gles3_srgb_workaround(brw, readFb);
+
+ /* If the context viewport hasn't been initialized, force a call out to
+ * the loader to get buffers so we have a drawable size for the initial
+ * viewport. */
+ if (!brw->ctx.ViewportInitialized)
+ intel_prepare_render(brw);
+
+ _mesa_make_current(ctx, fb, readFb);
+ } else {
+ _mesa_make_current(NULL, NULL, NULL);
+ }
+
+ return true;
+}
+
+void
+intel_resolve_for_dri2_flush(struct brw_context *brw,
+ __DRIdrawable *drawable)
+{
+ if (brw->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(brw, rb->mt);
+ else
+ intel_renderbuffer_downsample(brw, rb);
+ }
+}
+
+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 brw_context *brw,
+ __DRIdrawable *drawable,
+ __DRIbuffer **buffers,
+ int *count);
+
+static void
+intel_process_dri2_buffer(struct brw_context *brw,
+ __DRIdrawable *drawable,
+ __DRIbuffer *buffer,
+ struct intel_renderbuffer *rb,
+ const char *buffer_name);
+
+static void
+intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable);
+
+static void
+intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
+{
+ struct gl_framebuffer *fb = drawable->driverPrivate;
+ struct intel_renderbuffer *rb;
+ __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(brw, 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(brw, drawable, &buffers[i], rb, region_name);
+ }
+
+}
+
+void
+intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+{
+ struct brw_context *brw = context->driverPrivate;
+ __DRIscreen *screen = brw->intelScreen->driScrnPriv;
+
+ /* 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);
+
+ if (screen->image.loader)
+ intel_update_image_buffers(brw, drawable);
+ else
+ intel_update_dri2_buffers(brw, drawable);
+
+ driUpdateFramebufferSize(&brw->ctx, drawable);
+}
+
+/**
+ * intel_prepare_render should be called anywhere that curent read/drawbuffer
+ * state is required.
+ */
+void
+intel_prepare_render(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->ctx;
+ __DRIcontext *driContext = brw->driContext;
+ __DRIdrawable *drawable;
+
+ drawable = driContext->driDrawablePriv;
+ if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) {
+ if (drawable->lastStamp != drawable->dri2.stamp)
+ intel_update_renderbuffers(driContext, drawable);
+ driContext->dri2.draw_stamp = drawable->dri2.stamp;
+ }
+
+ drawable = driContext->driReadablePriv;
+ if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) {
+ if (drawable->lastStamp != drawable->dri2.stamp)
+ intel_update_renderbuffers(driContext, drawable);
+ driContext->dri2.read_stamp = drawable->dri2.stamp;
+ }
+
+ /* If we're currently rendering to the front buffer, the rendering
+ * that will happen next will probably dirty the front buffer. So
+ * mark it as dirty here.
+ */
+ if (brw_is_front_buffer_drawing(ctx->DrawBuffer))
+ brw->front_buffer_dirty = true;
+
+ /* Wait for the swapbuffers before the one we just emitted, so we
+ * don't get too many swaps outstanding for apps that are GPU-heavy
+ * but not CPU-heavy.
+ *
+ * We're using intelDRI2Flush (called from the loader before
+ * swapbuffer) and glFlush (for front buffer rendering) as the
+ * indicator that a frame is done and then throttle when we get
+ * here as we prepare to render the next frame. At this point for
+ * round trips for swap/copy and getting new buffers are done and
+ * we'll spend less time waiting on the GPU.
+ *
+ * Unfortunately, we don't have a handle to the batch containing
+ * the swap, and getting our hands on that doesn't seem worth it,
+ * so we just us the first batch we emitted after the last swap.