1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2009, VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci/* 28bf215546Sopenharmony_ci * Author: Keith Whitwell <keithw@vmware.com> 29bf215546Sopenharmony_ci * Author: Jakob Bornecrantz <wallbraker@gmail.com> 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "dri_screen.h" 33bf215546Sopenharmony_ci#include "dri_drawable.h" 34bf215546Sopenharmony_ci#include "dri_context.h" 35bf215546Sopenharmony_ci#include "frontend/drm_driver.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "pipe/p_context.h" 38bf215546Sopenharmony_ci#include "pipe-loader/pipe_loader.h" 39bf215546Sopenharmony_ci#include "state_tracker/st_context.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "util/u_memory.h" 42bf215546Sopenharmony_ci#include "util/debug.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ciGLboolean 45bf215546Sopenharmony_cidri_create_context(gl_api api, const struct gl_config * visual, 46bf215546Sopenharmony_ci __DRIcontext * cPriv, 47bf215546Sopenharmony_ci const struct __DriverContextConfig *ctx_config, 48bf215546Sopenharmony_ci unsigned *error, 49bf215546Sopenharmony_ci void *sharedContextPrivate) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci __DRIscreen *sPriv = cPriv->driScreenPriv; 52bf215546Sopenharmony_ci struct dri_screen *screen = dri_screen(sPriv); 53bf215546Sopenharmony_ci struct st_api *stapi = screen->st_api; 54bf215546Sopenharmony_ci struct dri_context *ctx = NULL; 55bf215546Sopenharmony_ci struct st_context_iface *st_share = NULL; 56bf215546Sopenharmony_ci struct st_context_attribs attribs; 57bf215546Sopenharmony_ci enum st_context_error ctx_err = 0; 58bf215546Sopenharmony_ci unsigned allowed_flags = __DRI_CTX_FLAG_DEBUG | 59bf215546Sopenharmony_ci __DRI_CTX_FLAG_FORWARD_COMPATIBLE; 60bf215546Sopenharmony_ci unsigned allowed_attribs = 61bf215546Sopenharmony_ci __DRIVER_CONTEXT_ATTRIB_PRIORITY | 62bf215546Sopenharmony_ci __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR | 63bf215546Sopenharmony_ci __DRIVER_CONTEXT_ATTRIB_NO_ERROR; 64bf215546Sopenharmony_ci const __DRIbackgroundCallableExtension *backgroundCallable = 65bf215546Sopenharmony_ci screen->sPriv->dri2.backgroundCallable; 66bf215546Sopenharmony_ci const struct driOptionCache *optionCache = &screen->dev->option_cache; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci if (screen->has_reset_status_query) { 69bf215546Sopenharmony_ci allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS; 70bf215546Sopenharmony_ci allowed_attribs |= __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY; 71bf215546Sopenharmony_ci } 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci if (ctx_config->flags & ~allowed_flags) { 74bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 75bf215546Sopenharmony_ci goto fail; 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (ctx_config->attribute_mask & ~allowed_attribs) { 79bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 80bf215546Sopenharmony_ci goto fail; 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci memset(&attribs, 0, sizeof(attribs)); 84bf215546Sopenharmony_ci switch (api) { 85bf215546Sopenharmony_ci case API_OPENGLES: 86bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_OPENGL_ES1; 87bf215546Sopenharmony_ci break; 88bf215546Sopenharmony_ci case API_OPENGLES2: 89bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_OPENGL_ES2; 90bf215546Sopenharmony_ci break; 91bf215546Sopenharmony_ci case API_OPENGL_COMPAT: 92bf215546Sopenharmony_ci case API_OPENGL_CORE: 93bf215546Sopenharmony_ci if (driQueryOptionb(optionCache, "force_compat_profile")) { 94bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_DEFAULT; 95bf215546Sopenharmony_ci } else { 96bf215546Sopenharmony_ci attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT 97bf215546Sopenharmony_ci : ST_PROFILE_OPENGL_CORE; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci attribs.major = ctx_config->major_version; 101bf215546Sopenharmony_ci attribs.minor = ctx_config->minor_version; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if ((ctx_config->flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) 104bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; 105bf215546Sopenharmony_ci break; 106bf215546Sopenharmony_ci default: 107bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_BAD_API; 108bf215546Sopenharmony_ci goto fail; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci if ((ctx_config->flags & __DRI_CTX_FLAG_DEBUG) != 0) 112bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_DEBUG; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci if (ctx_config->flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS) 115bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY) 118bf215546Sopenharmony_ci if (ctx_config->reset_strategy != __DRI_CTX_RESET_NO_NOTIFICATION) 119bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_NO_ERROR) 122bf215546Sopenharmony_ci attribs.flags |= ctx_config->no_error ? ST_CONTEXT_FLAG_NO_ERROR : 0; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_PRIORITY) { 125bf215546Sopenharmony_ci switch (ctx_config->priority) { 126bf215546Sopenharmony_ci case __DRI_CTX_PRIORITY_LOW: 127bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_LOW_PRIORITY; 128bf215546Sopenharmony_ci break; 129bf215546Sopenharmony_ci case __DRI_CTX_PRIORITY_HIGH: 130bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_HIGH_PRIORITY; 131bf215546Sopenharmony_ci break; 132bf215546Sopenharmony_ci default: 133bf215546Sopenharmony_ci break; 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if ((ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR) 138bf215546Sopenharmony_ci && (ctx_config->release_behavior == __DRI_CTX_RELEASE_BEHAVIOR_NONE)) 139bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_RELEASE_NONE; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci struct dri_context *share_ctx = NULL; 142bf215546Sopenharmony_ci if (sharedContextPrivate) { 143bf215546Sopenharmony_ci share_ctx = (struct dri_context *)sharedContextPrivate; 144bf215546Sopenharmony_ci st_share = share_ctx->st; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci ctx = CALLOC_STRUCT(dri_context); 148bf215546Sopenharmony_ci if (ctx == NULL) { 149bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_NO_MEMORY; 150bf215546Sopenharmony_ci goto fail; 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci cPriv->driverPrivate = ctx; 154bf215546Sopenharmony_ci ctx->cPriv = cPriv; 155bf215546Sopenharmony_ci ctx->sPriv = sPriv; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci /* KHR_no_error is likely to crash, overflow memory, etc if an application 158bf215546Sopenharmony_ci * has errors so don't enable it for setuid processes. 159bf215546Sopenharmony_ci */ 160bf215546Sopenharmony_ci if (env_var_as_boolean("MESA_NO_ERROR", false) || 161bf215546Sopenharmony_ci driQueryOptionb(&screen->dev->option_cache, "mesa_no_error")) 162bf215546Sopenharmony_ci#if !defined(_WIN32) 163bf215546Sopenharmony_ci if (geteuid() == getuid()) 164bf215546Sopenharmony_ci#endif 165bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci attribs.options = screen->options; 168bf215546Sopenharmony_ci dri_fill_st_visual(&attribs.visual, screen, visual); 169bf215546Sopenharmony_ci ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err, 170bf215546Sopenharmony_ci st_share); 171bf215546Sopenharmony_ci if (ctx->st == NULL) { 172bf215546Sopenharmony_ci switch (ctx_err) { 173bf215546Sopenharmony_ci case ST_CONTEXT_SUCCESS: 174bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_SUCCESS; 175bf215546Sopenharmony_ci break; 176bf215546Sopenharmony_ci case ST_CONTEXT_ERROR_NO_MEMORY: 177bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_NO_MEMORY; 178bf215546Sopenharmony_ci break; 179bf215546Sopenharmony_ci case ST_CONTEXT_ERROR_BAD_API: 180bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_BAD_API; 181bf215546Sopenharmony_ci break; 182bf215546Sopenharmony_ci case ST_CONTEXT_ERROR_BAD_VERSION: 183bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_BAD_VERSION; 184bf215546Sopenharmony_ci break; 185bf215546Sopenharmony_ci case ST_CONTEXT_ERROR_BAD_FLAG: 186bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_BAD_FLAG; 187bf215546Sopenharmony_ci break; 188bf215546Sopenharmony_ci case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE: 189bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 190bf215546Sopenharmony_ci break; 191bf215546Sopenharmony_ci case ST_CONTEXT_ERROR_UNKNOWN_FLAG: 192bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 193bf215546Sopenharmony_ci break; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci goto fail; 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci ctx->st->st_manager_private = (void *) ctx; 198bf215546Sopenharmony_ci ctx->stapi = stapi; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci if (ctx->st->cso_context) { 201bf215546Sopenharmony_ci ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context, 202bf215546Sopenharmony_ci ctx->st); 203bf215546Sopenharmony_ci ctx->hud = hud_create(ctx->st->cso_context, ctx->st, 204bf215546Sopenharmony_ci share_ctx ? share_ctx->hud : NULL); 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci /* Do this last. */ 208bf215546Sopenharmony_ci if (ctx->st->start_thread && 209bf215546Sopenharmony_ci driQueryOptionb(&screen->dev->option_cache, "mesa_glthread")) { 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (backgroundCallable && backgroundCallable->base.version >= 2 && 212bf215546Sopenharmony_ci backgroundCallable->isThreadSafe) { 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (backgroundCallable->isThreadSafe(cPriv->loaderPrivate)) 215bf215546Sopenharmony_ci ctx->st->start_thread(ctx->st); 216bf215546Sopenharmony_ci else 217bf215546Sopenharmony_ci fprintf(stderr, "dri_create_context: glthread isn't thread safe " 218bf215546Sopenharmony_ci "- missing call XInitThreads\n"); 219bf215546Sopenharmony_ci } else { 220bf215546Sopenharmony_ci fprintf(stderr, "dri_create_context: requested glthread but driver " 221bf215546Sopenharmony_ci "is missing backgroundCallable V2 extension\n"); 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci *error = __DRI_CTX_ERROR_SUCCESS; 226bf215546Sopenharmony_ci return GL_TRUE; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci fail: 229bf215546Sopenharmony_ci if (ctx && ctx->st) 230bf215546Sopenharmony_ci ctx->st->destroy(ctx->st); 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci free(ctx); 233bf215546Sopenharmony_ci return GL_FALSE; 234bf215546Sopenharmony_ci} 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_civoid 237bf215546Sopenharmony_cidri_destroy_context(__DRIcontext * cPriv) 238bf215546Sopenharmony_ci{ 239bf215546Sopenharmony_ci struct dri_context *ctx = dri_context(cPriv); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci if (ctx->hud) { 242bf215546Sopenharmony_ci hud_destroy(ctx->hud, ctx->st->cso_context); 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci if (ctx->pp) 246bf215546Sopenharmony_ci pp_free(ctx->pp); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci /* No particular reason to wait for command completion before 249bf215546Sopenharmony_ci * destroying a context, but we flush the context here 250bf215546Sopenharmony_ci * to avoid having to add code elsewhere to cope with flushing a 251bf215546Sopenharmony_ci * partially destroyed context. 252bf215546Sopenharmony_ci */ 253bf215546Sopenharmony_ci ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); 254bf215546Sopenharmony_ci ctx->st->destroy(ctx->st); 255bf215546Sopenharmony_ci free(ctx); 256bf215546Sopenharmony_ci} 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci/* This is called inside MakeCurrent to unbind the context. */ 259bf215546Sopenharmony_ciGLboolean 260bf215546Sopenharmony_cidri_unbind_context(__DRIcontext * cPriv) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci /* dri_util.c ensures cPriv is not null */ 263bf215546Sopenharmony_ci struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); 264bf215546Sopenharmony_ci struct dri_context *ctx = dri_context(cPriv); 265bf215546Sopenharmony_ci struct st_context_iface *st = ctx->st; 266bf215546Sopenharmony_ci struct st_api *stapi = screen->st_api; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci if (st == stapi->get_current(stapi)) { 269bf215546Sopenharmony_ci if (st->thread_finish) 270bf215546Sopenharmony_ci st->thread_finish(st); 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci /* Record HUD queries for the duration the context was "current". */ 273bf215546Sopenharmony_ci if (ctx->hud) 274bf215546Sopenharmony_ci hud_record_only(ctx->hud, st->pipe); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci stapi->make_current(stapi, NULL, NULL, NULL); 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci ctx->dPriv = NULL; 279bf215546Sopenharmony_ci ctx->rPriv = NULL; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci return GL_TRUE; 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ciGLboolean 285bf215546Sopenharmony_cidri_make_current(__DRIcontext * cPriv, 286bf215546Sopenharmony_ci __DRIdrawable * driDrawPriv, 287bf215546Sopenharmony_ci __DRIdrawable * driReadPriv) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci /* dri_util.c ensures cPriv is not null */ 290bf215546Sopenharmony_ci struct dri_context *ctx = dri_context(cPriv); 291bf215546Sopenharmony_ci struct dri_drawable *draw = dri_drawable(driDrawPriv); 292bf215546Sopenharmony_ci struct dri_drawable *read = dri_drawable(driReadPriv); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (!draw && !read) 295bf215546Sopenharmony_ci return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); 296bf215546Sopenharmony_ci else if (!draw || !read) 297bf215546Sopenharmony_ci return GL_FALSE; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci if (ctx->dPriv != driDrawPriv) { 300bf215546Sopenharmony_ci ctx->dPriv = driDrawPriv; 301bf215546Sopenharmony_ci draw->texture_stamp = driDrawPriv->lastStamp - 1; 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci if (ctx->rPriv != driReadPriv) { 304bf215546Sopenharmony_ci ctx->rPriv = driReadPriv; 305bf215546Sopenharmony_ci read->texture_stamp = driReadPriv->lastStamp - 1; 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci /* This is ok to call here. If they are already init, it's a no-op. */ 311bf215546Sopenharmony_ci if (ctx->pp && draw->textures[ST_ATTACHMENT_BACK_LEFT]) 312bf215546Sopenharmony_ci pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0, 313bf215546Sopenharmony_ci draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci return GL_TRUE; 316bf215546Sopenharmony_ci} 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_cistruct dri_context * 319bf215546Sopenharmony_cidri_get_current(__DRIscreen *sPriv) 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci struct dri_screen *screen = dri_screen(sPriv); 322bf215546Sopenharmony_ci struct st_api *stapi = screen->st_api; 323bf215546Sopenharmony_ci struct st_context_iface *st; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci st = stapi->get_current(stapi); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci return (struct dri_context *) st ? st->st_manager_private : NULL; 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci/* vim: set sw=3 ts=8 sts=3 expandtab: */ 331