Path: blob/21.2-virgl/src/gallium/frontends/dri/dri_context.c
4565 views
/**************************************************************************1*2* Copyright 2009, VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/26/*27* Author: Keith Whitwell <[email protected]>28* Author: Jakob Bornecrantz <[email protected]>29*/3031#include "utils.h"3233#include "dri_screen.h"34#include "dri_drawable.h"35#include "dri_context.h"36#include "frontend/drm_driver.h"3738#include "pipe/p_context.h"39#include "pipe-loader/pipe_loader.h"40#include "state_tracker/st_context.h"4142#include "util/u_memory.h"4344GLboolean45dri_create_context(gl_api api, const struct gl_config * visual,46__DRIcontext * cPriv,47const struct __DriverContextConfig *ctx_config,48unsigned *error,49void *sharedContextPrivate)50{51__DRIscreen *sPriv = cPriv->driScreenPriv;52struct dri_screen *screen = dri_screen(sPriv);53struct st_api *stapi = screen->st_api;54struct dri_context *ctx = NULL;55struct st_context_iface *st_share = NULL;56struct st_context_attribs attribs;57enum st_context_error ctx_err = 0;58unsigned allowed_flags = __DRI_CTX_FLAG_DEBUG |59__DRI_CTX_FLAG_FORWARD_COMPATIBLE |60__DRI_CTX_FLAG_NO_ERROR;61unsigned allowed_attribs =62__DRIVER_CONTEXT_ATTRIB_PRIORITY |63__DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR;64const __DRIbackgroundCallableExtension *backgroundCallable =65screen->sPriv->dri2.backgroundCallable;66const struct driOptionCache *optionCache = &screen->dev->option_cache;6768if (screen->has_reset_status_query) {69allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS;70allowed_attribs |= __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY;71}7273if (ctx_config->flags & ~allowed_flags) {74*error = __DRI_CTX_ERROR_UNKNOWN_FLAG;75goto fail;76}7778if (ctx_config->attribute_mask & ~allowed_attribs) {79*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;80goto fail;81}8283memset(&attribs, 0, sizeof(attribs));84switch (api) {85case API_OPENGLES:86attribs.profile = ST_PROFILE_OPENGL_ES1;87break;88case API_OPENGLES2:89attribs.profile = ST_PROFILE_OPENGL_ES2;90break;91case API_OPENGL_COMPAT:92case API_OPENGL_CORE:93if (driQueryOptionb(optionCache, "force_compat_profile")) {94attribs.profile = ST_PROFILE_DEFAULT;95} else {96attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT97: ST_PROFILE_OPENGL_CORE;98}99100attribs.major = ctx_config->major_version;101attribs.minor = ctx_config->minor_version;102103if ((ctx_config->flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)104attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;105break;106default:107*error = __DRI_CTX_ERROR_BAD_API;108goto fail;109}110111if ((ctx_config->flags & __DRI_CTX_FLAG_DEBUG) != 0)112attribs.flags |= ST_CONTEXT_FLAG_DEBUG;113114if (ctx_config->flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)115attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;116117if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY)118if (ctx_config->reset_strategy != __DRI_CTX_RESET_NO_NOTIFICATION)119attribs.flags |= ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED;120121if (ctx_config->flags & __DRI_CTX_FLAG_NO_ERROR)122attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR;123124if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_PRIORITY) {125switch (ctx_config->priority) {126case __DRI_CTX_PRIORITY_LOW:127attribs.flags |= ST_CONTEXT_FLAG_LOW_PRIORITY;128break;129case __DRI_CTX_PRIORITY_HIGH:130attribs.flags |= ST_CONTEXT_FLAG_HIGH_PRIORITY;131break;132default:133break;134}135}136137if ((ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR)138&& (ctx_config->release_behavior == __DRI_CTX_RELEASE_BEHAVIOR_NONE))139attribs.flags |= ST_CONTEXT_FLAG_RELEASE_NONE;140141struct dri_context *share_ctx = NULL;142if (sharedContextPrivate) {143share_ctx = (struct dri_context *)sharedContextPrivate;144st_share = share_ctx->st;145}146147ctx = CALLOC_STRUCT(dri_context);148if (ctx == NULL) {149*error = __DRI_CTX_ERROR_NO_MEMORY;150goto fail;151}152153cPriv->driverPrivate = ctx;154ctx->cPriv = cPriv;155ctx->sPriv = sPriv;156157if (driQueryOptionb(&screen->dev->option_cache, "mesa_no_error"))158attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR;159160attribs.options = screen->options;161dri_fill_st_visual(&attribs.visual, screen, visual);162ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err,163st_share);164if (ctx->st == NULL) {165switch (ctx_err) {166case ST_CONTEXT_SUCCESS:167*error = __DRI_CTX_ERROR_SUCCESS;168break;169case ST_CONTEXT_ERROR_NO_MEMORY:170*error = __DRI_CTX_ERROR_NO_MEMORY;171break;172case ST_CONTEXT_ERROR_BAD_API:173*error = __DRI_CTX_ERROR_BAD_API;174break;175case ST_CONTEXT_ERROR_BAD_VERSION:176*error = __DRI_CTX_ERROR_BAD_VERSION;177break;178case ST_CONTEXT_ERROR_BAD_FLAG:179*error = __DRI_CTX_ERROR_BAD_FLAG;180break;181case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:182*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;183break;184case ST_CONTEXT_ERROR_UNKNOWN_FLAG:185*error = __DRI_CTX_ERROR_UNKNOWN_FLAG;186break;187}188goto fail;189}190ctx->st->st_manager_private = (void *) ctx;191ctx->stapi = stapi;192193if (ctx->st->cso_context) {194ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context,195ctx->st);196ctx->hud = hud_create(ctx->st->cso_context, ctx->st,197share_ctx ? share_ctx->hud : NULL);198}199200/* Do this last. */201if (ctx->st->start_thread &&202driQueryOptionb(&screen->dev->option_cache, "mesa_glthread")) {203204if (backgroundCallable && backgroundCallable->base.version >= 2 &&205backgroundCallable->isThreadSafe) {206207if (backgroundCallable->isThreadSafe(cPriv->loaderPrivate))208ctx->st->start_thread(ctx->st);209else210fprintf(stderr, "dri_create_context: glthread isn't thread safe "211"- missing call XInitThreads\n");212} else {213fprintf(stderr, "dri_create_context: requested glthread but driver "214"is missing backgroundCallable V2 extension\n");215}216}217218*error = __DRI_CTX_ERROR_SUCCESS;219return GL_TRUE;220221fail:222if (ctx && ctx->st)223ctx->st->destroy(ctx->st);224225free(ctx);226return GL_FALSE;227}228229void230dri_destroy_context(__DRIcontext * cPriv)231{232struct dri_context *ctx = dri_context(cPriv);233234if (ctx->hud) {235hud_destroy(ctx->hud, ctx->st->cso_context);236}237238if (ctx->pp)239pp_free(ctx->pp);240241/* No particular reason to wait for command completion before242* destroying a context, but we flush the context here243* to avoid having to add code elsewhere to cope with flushing a244* partially destroyed context.245*/246ctx->st->flush(ctx->st, 0, NULL, NULL, NULL);247ctx->st->destroy(ctx->st);248free(ctx);249}250251/* This is called inside MakeCurrent to unbind the context. */252GLboolean253dri_unbind_context(__DRIcontext * cPriv)254{255/* dri_util.c ensures cPriv is not null */256struct dri_screen *screen = dri_screen(cPriv->driScreenPriv);257struct dri_context *ctx = dri_context(cPriv);258struct st_context_iface *st = ctx->st;259struct st_api *stapi = screen->st_api;260261if (--ctx->bind_count == 0) {262if (st == stapi->get_current(stapi)) {263if (st->thread_finish)264st->thread_finish(st);265266/* Record HUD queries for the duration the context was "current". */267if (ctx->hud)268hud_record_only(ctx->hud, st->pipe);269270stapi->make_current(stapi, NULL, NULL, NULL);271}272}273ctx->dPriv = NULL;274ctx->rPriv = NULL;275276return GL_TRUE;277}278279GLboolean280dri_make_current(__DRIcontext * cPriv,281__DRIdrawable * driDrawPriv,282__DRIdrawable * driReadPriv)283{284/* dri_util.c ensures cPriv is not null */285struct dri_context *ctx = dri_context(cPriv);286struct dri_drawable *draw = dri_drawable(driDrawPriv);287struct dri_drawable *read = dri_drawable(driReadPriv);288289++ctx->bind_count;290291if (!draw && !read)292return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL);293else if (!draw || !read)294return GL_FALSE;295296if (ctx->dPriv != driDrawPriv) {297ctx->dPriv = driDrawPriv;298draw->texture_stamp = driDrawPriv->lastStamp - 1;299}300if (ctx->rPriv != driReadPriv) {301ctx->rPriv = driReadPriv;302read->texture_stamp = driReadPriv->lastStamp - 1;303}304305ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base);306307/* This is ok to call here. If they are already init, it's a no-op. */308if (ctx->pp && draw->textures[ST_ATTACHMENT_BACK_LEFT])309pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0,310draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0);311312return GL_TRUE;313}314315struct dri_context *316dri_get_current(__DRIscreen *sPriv)317{318struct dri_screen *screen = dri_screen(sPriv);319struct st_api *stapi = screen->st_api;320struct st_context_iface *st;321322st = stapi->get_current(stapi);323324return (struct dri_context *) st ? st->st_manager_private : NULL;325}326327/* vim: set sw=3 ts=8 sts=3 expandtab: */328329330