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