Home | History | Annotate | Download | only in dri
      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 GLboolean
     43 dri_create_context(gl_api api, const struct gl_config * visual,
     44 		   __DRIcontext * cPriv,
     45 		   unsigned major_version,
     46 		   unsigned minor_version,
     47 		   uint32_t flags,
     48                    bool notify_reset,
     49 		   unsigned *error,
     50 		   void *sharedContextPrivate)
     51 {
     52    __DRIscreen *sPriv = cPriv->driScreenPriv;
     53    struct dri_screen *screen = dri_screen(sPriv);
     54    struct st_api *stapi = screen->st_api;
     55    struct dri_context *ctx = NULL;
     56    struct st_context_iface *st_share = NULL;
     57    struct st_context_attribs attribs;
     58    enum st_context_error ctx_err = 0;
     59    unsigned allowed_flags = __DRI_CTX_FLAG_DEBUG |
     60                             __DRI_CTX_FLAG_FORWARD_COMPATIBLE;
     61 
     62    if (screen->has_reset_status_query)
     63       allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS;
     64 
     65    if (flags & ~allowed_flags) {
     66       *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
     67       goto fail;
     68    }
     69 
     70    if (!screen->has_reset_status_query && notify_reset) {
     71       *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
     72       goto fail;
     73    }
     74 
     75    memset(&attribs, 0, sizeof(attribs));
     76    switch (api) {
     77    case API_OPENGLES:
     78       attribs.profile = ST_PROFILE_OPENGL_ES1;
     79       break;
     80    case API_OPENGLES2:
     81       attribs.profile = ST_PROFILE_OPENGL_ES2;
     82       break;
     83    case API_OPENGL_COMPAT:
     84    case API_OPENGL_CORE:
     85       attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT
     86                                                  : ST_PROFILE_OPENGL_CORE;
     87       attribs.major = major_version;
     88       attribs.minor = minor_version;
     89 
     90       if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
     91 	 attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
     92       break;
     93    default:
     94       *error = __DRI_CTX_ERROR_BAD_API;
     95       goto fail;
     96    }
     97 
     98    if ((flags & __DRI_CTX_FLAG_DEBUG) != 0)
     99       attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
    100 
    101    if (flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
    102       attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;
    103 
    104    if (notify_reset)
    105       attribs.flags |= ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED;
    106 
    107    if (sharedContextPrivate) {
    108       st_share = ((struct dri_context *)sharedContextPrivate)->st;
    109    }
    110 
    111    ctx = CALLOC_STRUCT(dri_context);
    112    if (ctx == NULL) {
    113       *error = __DRI_CTX_ERROR_NO_MEMORY;
    114       goto fail;
    115    }
    116 
    117    cPriv->driverPrivate = ctx;
    118    ctx->cPriv = cPriv;
    119    ctx->sPriv = sPriv;
    120 
    121    attribs.options = screen->options;
    122    dri_fill_st_visual(&attribs.visual, screen, visual);
    123    ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err,
    124 				   st_share);
    125    if (ctx->st == NULL) {
    126       switch (ctx_err) {
    127       case ST_CONTEXT_SUCCESS:
    128 	 *error = __DRI_CTX_ERROR_SUCCESS;
    129 	 break;
    130       case ST_CONTEXT_ERROR_NO_MEMORY:
    131 	 *error = __DRI_CTX_ERROR_NO_MEMORY;
    132 	 break;
    133       case ST_CONTEXT_ERROR_BAD_API:
    134 	 *error = __DRI_CTX_ERROR_BAD_API;
    135 	 break;
    136       case ST_CONTEXT_ERROR_BAD_VERSION:
    137 	 *error = __DRI_CTX_ERROR_BAD_VERSION;
    138 	 break;
    139       case ST_CONTEXT_ERROR_BAD_FLAG:
    140 	 *error = __DRI_CTX_ERROR_BAD_FLAG;
    141 	 break;
    142       case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:
    143 	 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
    144 	 break;
    145       case ST_CONTEXT_ERROR_UNKNOWN_FLAG:
    146 	 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
    147 	 break;
    148       }
    149       goto fail;
    150    }
    151    ctx->st->st_manager_private = (void *) ctx;
    152    ctx->stapi = stapi;
    153 
    154    if (ctx->st->cso_context) {
    155       ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context);
    156       ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context);
    157    }
    158 
    159    *error = __DRI_CTX_ERROR_SUCCESS;
    160    return GL_TRUE;
    161 
    162  fail:
    163    if (ctx && ctx->st)
    164       ctx->st->destroy(ctx->st);
    165 
    166    free(ctx);
    167    return GL_FALSE;
    168 }
    169 
    170 void
    171 dri_destroy_context(__DRIcontext * cPriv)
    172 {
    173    struct dri_context *ctx = dri_context(cPriv);
    174 
    175    if (ctx->hud) {
    176       hud_destroy(ctx->hud);
    177    }
    178 
    179    if (ctx->pp)
    180       pp_free(ctx->pp);
    181 
    182    /* No particular reason to wait for command completion before
    183     * destroying a context, but we flush the context here
    184     * to avoid having to add code elsewhere to cope with flushing a
    185     * partially destroyed context.
    186     */
    187    ctx->st->flush(ctx->st, 0, NULL);
    188    ctx->st->destroy(ctx->st);
    189    free(ctx);
    190 }
    191 
    192 GLboolean
    193 dri_unbind_context(__DRIcontext * cPriv)
    194 {
    195    /* dri_util.c ensures cPriv is not null */
    196    struct dri_screen *screen = dri_screen(cPriv->driScreenPriv);
    197    struct dri_context *ctx = dri_context(cPriv);
    198    struct st_api *stapi = screen->st_api;
    199 
    200    if (--ctx->bind_count == 0) {
    201       if (ctx->st == ctx->stapi->get_current(ctx->stapi)) {
    202          /* For conformance, unbind is supposed to flush the context.
    203           * However, if we do it here we might end up flushing a partially
    204           * destroyed context. Instead, we flush in dri_make_current and
    205           * in dri_destroy_context which should cover all the cases.
    206           */
    207          stapi->make_current(stapi, NULL, NULL, NULL);
    208       }
    209    }
    210 
    211    return GL_TRUE;
    212 }
    213 
    214 GLboolean
    215 dri_make_current(__DRIcontext * cPriv,
    216 		 __DRIdrawable * driDrawPriv,
    217 		 __DRIdrawable * driReadPriv)
    218 {
    219    /* dri_util.c ensures cPriv is not null */
    220    struct dri_context *ctx = dri_context(cPriv);
    221    struct dri_drawable *draw = dri_drawable(driDrawPriv);
    222    struct dri_drawable *read = dri_drawable(driReadPriv);
    223    struct st_context_iface *old_st = ctx->stapi->get_current(ctx->stapi);
    224 
    225    /* Flush the old context here so we don't have to flush on unbind() */
    226    if (old_st && old_st != ctx->st)
    227       old_st->flush(old_st, ST_FLUSH_FRONT, NULL);
    228 
    229    ++ctx->bind_count;
    230 
    231    if (!draw && !read)
    232       return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL);
    233    else if (!draw || !read)
    234       return GL_FALSE;
    235 
    236    if (ctx->dPriv != driDrawPriv) {
    237       ctx->dPriv = driDrawPriv;
    238       draw->texture_stamp = driDrawPriv->lastStamp - 1;
    239    }
    240    if (ctx->rPriv != driReadPriv) {
    241       ctx->rPriv = driReadPriv;
    242       read->texture_stamp = driReadPriv->lastStamp - 1;
    243    }
    244 
    245    ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base);
    246 
    247    /* This is ok to call here. If they are already init, it's a no-op. */
    248    if (ctx->pp && draw->textures[ST_ATTACHMENT_BACK_LEFT])
    249       pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
    250                    draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
    251 
    252    return GL_TRUE;
    253 }
    254 
    255 struct dri_context *
    256 dri_get_current(__DRIscreen *sPriv)
    257 {
    258    struct dri_screen *screen = dri_screen(sPriv);
    259    struct st_api *stapi = screen->st_api;
    260    struct st_context_iface *st;
    261 
    262    st = stapi->get_current(stapi);
    263 
    264    return (struct dri_context *) st ? st->st_manager_private : NULL;
    265 }
    266 
    267 /* vim: set sw=3 ts=8 sts=3 expandtab: */
    268