+ if (screen->has_context_reset_notification)
+ allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS;
+
+ if (flags & ~allowed_flags) {
+ *dri_ctx_error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
+ return false;
+ }
+
+ struct brw_context *brw = rzalloc(NULL, struct brw_context);
+ if (!brw) {
+ fprintf(stderr, "%s: failed to alloc context\n", __FUNCTION__);
+ *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY;
+ return false;
+ }
+
+ driContextPriv->driverPrivate = brw;
+ brw->driContext = driContextPriv;
+ brw->intelScreen = screen;
+ brw->bufmgr = screen->bufmgr;
+
+ brw->gen = devinfo->gen;
+ brw->gt = devinfo->gt;
+ brw->is_g4x = devinfo->is_g4x;
+ brw->is_baytrail = devinfo->is_baytrail;
+ brw->is_haswell = devinfo->is_haswell;
+ brw->is_cherryview = devinfo->is_cherryview;
+ brw->has_llc = devinfo->has_llc;
+ brw->has_hiz = devinfo->has_hiz_and_separate_stencil;
+ brw->has_separate_stencil = devinfo->has_hiz_and_separate_stencil;
+ brw->has_pln = devinfo->has_pln;
+ brw->has_compr4 = devinfo->has_compr4;
+ brw->has_surface_tile_offset = devinfo->has_surface_tile_offset;
+ brw->has_negative_rhw_bug = devinfo->has_negative_rhw_bug;
+ brw->needs_unlit_centroid_workaround =
+ devinfo->needs_unlit_centroid_workaround;
+
+ brw->must_use_separate_stencil = screen->hw_must_use_separate_stencil;
+ brw->has_swizzling = screen->hw_has_swizzling;
+
+ brw->vs.base.stage = MESA_SHADER_VERTEX;
+ brw->gs.base.stage = MESA_SHADER_GEOMETRY;
+ brw->wm.base.stage = MESA_SHADER_FRAGMENT;
+ if (brw->gen >= 8) {
+ gen8_init_vtable_surface_functions(brw);
+ brw->vtbl.emit_depth_stencil_hiz = gen8_emit_depth_stencil_hiz;
+ } else if (brw->gen >= 7) {
+ gen7_init_vtable_surface_functions(brw);
+ brw->vtbl.emit_depth_stencil_hiz = gen7_emit_depth_stencil_hiz;
+ } else if (brw->gen >= 6) {
+ gen6_init_vtable_surface_functions(brw);
+ brw->vtbl.emit_depth_stencil_hiz = gen6_emit_depth_stencil_hiz;
+ } else {
+ gen4_init_vtable_surface_functions(brw);
+ brw->vtbl.emit_depth_stencil_hiz = brw_emit_depth_stencil_hiz;
+ }
+
+ brw_init_driver_functions(brw, &functions);
+
+ if (notify_reset)
+ functions.GetGraphicsResetStatus = brw_get_graphics_reset_status;
+
+ struct gl_context *ctx = &brw->ctx;
+
+ if (!_mesa_initialize_context(ctx, api, mesaVis, shareCtx, &functions)) {
+ *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY;
+ fprintf(stderr, "%s: failed to init mesa context\n", __FUNCTION__);
+ intelDestroyContext(driContextPriv);
+ return false;
+ }
+
+ driContextSetFlags(ctx, flags);
+
+ /* Initialize the software rasterizer and helper modules.
+ *
+ * As of GL 3.1 core, the gen4+ driver doesn't need the swrast context for
+ * software fallbacks (which we have to support on legacy GL to do weird
+ * glDrawPixels(), glBitmap(), and other functions).
+ */
+ if (api != API_OPENGL_CORE && api != API_OPENGLES2) {
+ _swrast_CreateContext(ctx);
+ }
+
+ _vbo_CreateContext(ctx);
+ if (ctx->swrast_context) {
+ _tnl_CreateContext(ctx);
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+ _swsetup_CreateContext(ctx);
+
+ /* Configure swrast to match hardware characteristics: */
+ _swrast_allow_pixel_fog(ctx, false);
+ _swrast_allow_vertex_fog(ctx, true);
+ }
+
+ _mesa_meta_init(ctx);
+
+ brw_process_driconf_options(brw);
+ brw_process_intel_debug_variable(brw);
+
+ if (brw->gen >= 8 && !(INTEL_DEBUG & DEBUG_VEC4VS))
+ brw->scalar_vs = true;
+
+ brw_initialize_context_constants(brw);
+
+ ctx->Const.ResetStrategy = notify_reset
+ ? GL_LOSE_CONTEXT_ON_RESET_ARB : GL_NO_RESET_NOTIFICATION_ARB;
+
+ /* Reinitialize the context point state. It depends on ctx->Const values. */
+ _mesa_init_point(ctx);
+
+ intel_fbo_init(brw);
+
+ intel_batchbuffer_init(brw);
+
+ if (brw->gen >= 6) {
+ /* Create a new hardware context. Using a hardware context means that
+ * our GPU state will be saved/restored on context switch, allowing us
+ * to assume that the GPU is in the same state we left it in.
+ *
+ * This is required for transform feedback buffer offsets, query objects,
+ * and also allows us to reduce how much state we have to emit.
+ */
+ brw->hw_ctx = drm_intel_gem_context_create(brw->bufmgr);
+
+ if (!brw->hw_ctx) {
+ fprintf(stderr, "Gen6+ requires Kernel 3.6 or later.\n");
+ intelDestroyContext(driContextPriv);
+ return false;
+ }
+ }
+
+ brw_init_state(brw);
+
+ intelInitExtensions(ctx);
+
+ brw_init_surface_formats(brw);
+
+ brw->max_vs_threads = devinfo->max_vs_threads;
+ brw->max_gs_threads = devinfo->max_gs_threads;
+ brw->max_wm_threads = devinfo->max_wm_threads;
+ brw->urb.size = devinfo->urb.size;
+ brw->urb.min_vs_entries = devinfo->urb.min_vs_entries;
+ brw->urb.max_vs_entries = devinfo->urb.max_vs_entries;
+ brw->urb.max_gs_entries = devinfo->urb.max_gs_entries;
+
+ /* Estimate the size of the mappable aperture into the GTT. There's an
+ * ioctl to get the whole GTT size, but not one to get the mappable subset.
+ * It turns out it's basically always 256MB, though some ancient hardware
+ * was smaller.
+ */
+ uint32_t gtt_size = 256 * 1024 * 1024;
+
+ /* We don't want to map two objects such that a memcpy between them would
+ * just fault one mapping in and then the other over and over forever. So
+ * we would need to divide the GTT size by 2. Additionally, some GTT is
+ * taken up by things like the framebuffer and the ringbuffer and such, so
+ * be more conservative.
+ */
+ brw->max_gtt_map_object_size = gtt_size / 4;
+
+ if (brw->gen == 6)
+ brw->urb.gs_present = false;
+
+ brw->prim_restart.in_progress = false;
+ brw->prim_restart.enable_cut_index = false;
+ brw->gs.enabled = false;
+ brw->sf.viewport_transform_enable = true;
+
+ ctx->VertexProgram._MaintainTnlProgram = true;
+ ctx->FragmentProgram._MaintainTexEnvProgram = true;
+
+ brw_draw_init( brw );
+
+ 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();