Home | History | Annotate | Download | only in common
      1 /**************************************************************************
      2  *
      3  * Copyright 2009, VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 /*
     28  * Author: Keith Whitwell <keithw (at) vmware.com>
     29  * Author: Jakob Bornecrantz <wallbraker (at) gmail.com>
     30  */
     31 
     32 #include "utils.h"
     33 
     34 #include "dri_screen.h"
     35 #include "dri_drawable.h"
     36 #include "dri_context.h"
     37 #include "state_tracker/drm_driver.h"
     38 
     39 #include "pipe/p_context.h"
     40 #include "state_tracker/st_context.h"
     41 
     42 static void
     43 dri_pp_query(struct dri_context *ctx)
     44 {
     45    unsigned int i;
     46 
     47    for (i = 0; i < PP_FILTERS; i++) {
     48       ctx->pp_enabled[i] = driQueryOptioni(&ctx->optionCache, pp_filters[i].name);
     49    }
     50 }
     51 
     52 static void dri_fill_st_options(struct st_config_options *options,
     53                                 const struct driOptionCache * optionCache)
     54 {
     55    options->force_glsl_extensions_warn =
     56       driQueryOptionb(optionCache, "force_glsl_extensions_warn");
     57 }
     58 
     59 GLboolean
     60 dri_create_context(gl_api api, const struct gl_config * visual,
     61 		   __DRIcontext * cPriv,
     62 		   unsigned major_version,
     63 		   unsigned minor_version,
     64 		   uint32_t flags,
     65 		   unsigned *error,
     66 		   void *sharedContextPrivate)
     67 {
     68    __DRIscreen *sPriv = cPriv->driScreenPriv;
     69    struct dri_screen *screen = dri_screen(sPriv);
     70    struct st_api *stapi = screen->st_api;
     71    struct dri_context *ctx = NULL;
     72    struct st_context_iface *st_share = NULL;
     73    struct st_context_attribs attribs;
     74    enum st_context_error ctx_err = 0;
     75 
     76    memset(&attribs, 0, sizeof(attribs));
     77    switch (api) {
     78    case API_OPENGLES:
     79       attribs.profile = ST_PROFILE_OPENGL_ES1;
     80       break;
     81    case API_OPENGLES2:
     82       attribs.profile = ST_PROFILE_OPENGL_ES2;
     83       break;
     84    case API_OPENGL:
     85       attribs.profile = ST_PROFILE_DEFAULT;
     86       attribs.major = major_version;
     87       attribs.minor = minor_version;
     88 
     89       if ((flags & __DRI_CTX_FLAG_DEBUG) != 0)
     90 	 attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
     91 
     92       if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
     93 	 attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
     94       break;
     95    default:
     96       *error = __DRI_CTX_ERROR_BAD_API;
     97       goto fail;
     98    }
     99 
    100    if (sharedContextPrivate) {
    101       st_share = ((struct dri_context *)sharedContextPrivate)->st;
    102    }
    103 
    104    ctx = CALLOC_STRUCT(dri_context);
    105    if (ctx == NULL) {
    106       *error = __DRI_CTX_ERROR_NO_MEMORY;
    107       goto fail;
    108    }
    109 
    110    cPriv->driverPrivate = ctx;
    111    ctx->cPriv = cPriv;
    112    ctx->sPriv = sPriv;
    113 
    114    driParseConfigFiles(&ctx->optionCache,
    115 		       &screen->optionCache, sPriv->myNum, driver_descriptor.name);
    116 
    117    dri_fill_st_options(&attribs.options, &ctx->optionCache);
    118    dri_fill_st_visual(&attribs.visual, screen, visual);
    119    ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err,
    120 				   st_share);
    121    if (ctx->st == NULL) {
    122       switch (ctx_err) {
    123       case ST_CONTEXT_SUCCESS:
    124 	 *error = __DRI_CTX_ERROR_SUCCESS;
    125 	 break;
    126       case ST_CONTEXT_ERROR_NO_MEMORY:
    127 	 *error = __DRI_CTX_ERROR_NO_MEMORY;
    128 	 break;
    129       case ST_CONTEXT_ERROR_BAD_API:
    130 	 *error = __DRI_CTX_ERROR_BAD_API;
    131 	 break;
    132       case ST_CONTEXT_ERROR_BAD_VERSION:
    133 	 *error = __DRI_CTX_ERROR_BAD_VERSION;
    134 	 break;
    135       case ST_CONTEXT_ERROR_BAD_FLAG:
    136 	 *error = __DRI_CTX_ERROR_BAD_FLAG;
    137 	 break;
    138       case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:
    139 	 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
    140 	 break;
    141       case ST_CONTEXT_ERROR_UNKNOWN_FLAG:
    142 	 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
    143 	 break;
    144       }
    145       goto fail;
    146    }
    147    ctx->st->st_manager_private = (void *) ctx;
    148    ctx->stapi = stapi;
    149 
    150    // Context successfully created. See if post-processing is requested.
    151    dri_pp_query(ctx);
    152 
    153    ctx->pp = pp_init(screen->base.screen, ctx->pp_enabled);
    154 
    155    *error = __DRI_CTX_ERROR_SUCCESS;
    156    return GL_TRUE;
    157 
    158  fail:
    159    if (ctx && ctx->st)
    160       ctx->st->destroy(ctx->st);
    161 
    162    FREE(ctx);
    163    return GL_FALSE;
    164 }
    165 
    166 void
    167 dri_destroy_context(__DRIcontext * cPriv)
    168 {
    169    struct dri_context *ctx = dri_context(cPriv);
    170 
    171    /* note: we are freeing values and nothing more because
    172     * driParseConfigFiles allocated values only - the rest
    173     * is owned by screen optionCache.
    174     */
    175    FREE(ctx->optionCache.values);
    176 
    177    /* No particular reason to wait for command completion before
    178     * destroying a context, but we flush the context here
    179     * to avoid having to add code elsewhere to cope with flushing a
    180     * partially destroyed context.
    181     */
    182    ctx->st->flush(ctx->st, 0, NULL);
    183    ctx->st->destroy(ctx->st);
    184 
    185    if (ctx->pp) pp_free(ctx->pp);
    186 
    187    FREE(ctx);
    188 }
    189 
    190 GLboolean
    191 dri_unbind_context(__DRIcontext * cPriv)
    192 {
    193    /* dri_util.c ensures cPriv is not null */
    194    struct dri_screen *screen = dri_screen(cPriv->driScreenPriv);
    195    struct dri_context *ctx = dri_context(cPriv);
    196    struct st_api *stapi = screen->st_api;
    197 
    198    if (--ctx->bind_count == 0) {
    199       if (ctx->st == ctx->stapi->get_current(ctx->stapi)) {
    200          /* For conformance, unbind is supposed to flush the context.
    201           * However, if we do it here we might end up flushing a partially
    202           * destroyed context. Instead, we flush in dri_make_current and
    203           * in dri_destroy_context which should cover all the cases.
    204           */
    205          stapi->make_current(stapi, NULL, NULL, NULL);
    206       }
    207    }
    208 
    209    return GL_TRUE;
    210 }
    211 
    212 GLboolean
    213 dri_make_current(__DRIcontext * cPriv,
    214 		 __DRIdrawable * driDrawPriv,
    215 		 __DRIdrawable * driReadPriv)
    216 {
    217    /* dri_util.c ensures cPriv is not null */
    218    struct dri_context *ctx = dri_context(cPriv);
    219    struct dri_drawable *draw = dri_drawable(driDrawPriv);
    220    struct dri_drawable *read = dri_drawable(driReadPriv);
    221    struct st_context_iface *old_st = ctx->stapi->get_current(ctx->stapi);
    222 
    223    /* Flush the old context here so we don't have to flush on unbind() */
    224    if (old_st && old_st != ctx->st)
    225       old_st->flush(old_st, ST_FLUSH_FRONT, NULL);
    226 
    227    ++ctx->bind_count;
    228 
    229    if (!driDrawPriv && !driReadPriv)
    230       return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL);
    231    else if (!driDrawPriv || !driReadPriv)
    232       return GL_FALSE;
    233 
    234    if (ctx->dPriv != driDrawPriv) {
    235       ctx->dPriv = driDrawPriv;
    236       draw->texture_stamp = driDrawPriv->lastStamp - 1;
    237    }
    238    if (ctx->rPriv != driReadPriv) {
    239       ctx->rPriv = driReadPriv;
    240       read->texture_stamp = driReadPriv->lastStamp - 1;
    241    }
    242 
    243    ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base);
    244 
    245    // This is ok to call here. If they are already init, it's a no-op.
    246    if (draw->textures[ST_ATTACHMENT_BACK_LEFT] && draw->textures[ST_ATTACHMENT_DEPTH_STENCIL]
    247       && ctx->pp)
    248          pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
    249             draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
    250 
    251    return GL_TRUE;
    252 }
    253 
    254 struct dri_context *
    255 dri_get_current(__DRIscreen *sPriv)
    256 {
    257    struct dri_screen *screen = dri_screen(sPriv);
    258    struct st_api *stapi = screen->st_api;
    259    struct st_context_iface *st;
    260 
    261    st = stapi->get_current(stapi);
    262 
    263    return (struct dri_context *) (st) ? st->st_manager_private : NULL;
    264 }
    265 
    266 /* vim: set sw=3 ts=8 sts=3 expandtab: */
    267