1/**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31#include <assert.h>
32#include <stdlib.h>
33#include <string.h>
34#include "eglconfig.h"
35#include "eglcontext.h"
36#include "egldisplay.h"
37#include "eglcurrent.h"
38#include "eglsurface.h"
39#include "egllog.h"
40
41
42/**
43 * Return the API bit (one of EGL_xxx_BIT) of the context.
44 */
45static EGLint
46_eglGetContextAPIBit(_EGLContext *ctx)
47{
48   EGLint bit = 0;
49
50   switch (ctx->ClientAPI) {
51   case EGL_OPENGL_ES_API:
52      switch (ctx->ClientMajorVersion) {
53      case 1:
54         bit = EGL_OPENGL_ES_BIT;
55         break;
56      case 2:
57         bit = EGL_OPENGL_ES2_BIT;
58         break;
59      case 3:
60         bit = EGL_OPENGL_ES3_BIT_KHR;
61         break;
62      default:
63         break;
64      }
65      break;
66   case EGL_OPENVG_API:
67      bit = EGL_OPENVG_BIT;
68      break;
69   case EGL_OPENGL_API:
70      bit = EGL_OPENGL_BIT;
71      break;
72   default:
73      break;
74   }
75
76   return bit;
77}
78
79
80/**
81 * Parse the list of context attributes and return the proper error code.
82 */
83static EGLint
84_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
85                           const EGLint *attrib_list)
86{
87   EGLenum api = ctx->ClientAPI;
88   EGLint i, err = EGL_SUCCESS;
89
90   if (!attrib_list)
91      return EGL_SUCCESS;
92
93   if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
94      _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
95      return EGL_BAD_ATTRIBUTE;
96   }
97
98   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
99      EGLint attr = attrib_list[i++];
100      EGLint val = attrib_list[i];
101
102      switch (attr) {
103      case EGL_CONTEXT_CLIENT_VERSION:
104         /* The EGL 1.4 spec says:
105          *
106          *     "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
107          *      current rendering API is EGL_OPENGL_ES_API"
108          *
109          * The EGL_KHR_create_context spec says:
110          *
111          *     "EGL_CONTEXT_MAJOR_VERSION_KHR           0x3098
112          *      (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
113          *
114          *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
115          *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
116          *      version. They are only meaningful for OpenGL and OpenGL ES
117          *      contexts, and specifying them for other types of contexts will
118          *      generate an error."
119          */
120         if ((api != EGL_OPENGL_ES_API &&
121             (!dpy->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
122               err = EGL_BAD_ATTRIBUTE;
123               break;
124         }
125
126         ctx->ClientMajorVersion = val;
127         break;
128
129      case EGL_CONTEXT_MINOR_VERSION_KHR:
130         /* The EGL_KHR_create_context spec says:
131          *
132          *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
133          *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
134          *      version. They are only meaningful for OpenGL and OpenGL ES
135          *      contexts, and specifying them for other types of contexts will
136          *      generate an error."
137          */
138         if (!dpy->Extensions.KHR_create_context ||
139             (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
140            err = EGL_BAD_ATTRIBUTE;
141            break;
142         }
143
144         ctx->ClientMinorVersion = val;
145         break;
146
147      case EGL_CONTEXT_FLAGS_KHR:
148         if (!dpy->Extensions.KHR_create_context) {
149            err = EGL_BAD_ATTRIBUTE;
150            break;
151         }
152
153         /* The EGL_KHR_create_context spec says:
154          *
155          *     "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
156          *     EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
157          *     [...]
158          *     In some cases a debug context may be identical to a non-debug
159          *     context. This bit is supported for OpenGL and OpenGL ES
160          *     contexts."
161          */
162         if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
163             (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
164            err = EGL_BAD_ATTRIBUTE;
165            break;
166         }
167
168         /* The EGL_KHR_create_context spec says:
169          *
170          *     "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
171          *     is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
172          *     context will be created. Forward-compatible contexts are
173          *     defined only for OpenGL versions 3.0 and later. They must not
174          *     support functionality marked as <deprecated> by that version of
175          *     the API, while a non-forward-compatible context must support
176          *     all functionality in that version, deprecated or not. This bit
177          *     is supported for OpenGL contexts, and requesting a
178          *     forward-compatible context for OpenGL versions less than 3.0
179          *     will generate an error."
180          */
181         if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
182             (api != EGL_OPENGL_API || ctx->ClientMajorVersion < 3)) {
183            err = EGL_BAD_ATTRIBUTE;
184            break;
185         }
186
187         if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
188             api != EGL_OPENGL_API) {
189            /* The EGL_KHR_create_context spec says:
190             *
191             *   10) Which error should be generated if robust buffer access
192             *       or reset notifications are requested under OpenGL ES?
193             *
194             *       As per Issue 6, this extension does not support creating
195             *       robust contexts for OpenGL ES. This is only supported via
196             *       the EGL_EXT_create_context_robustness extension.
197             *
198             *       Attempting to use this extension to create robust OpenGL
199             *       ES context will generate an EGL_BAD_ATTRIBUTE error. This
200             *       specific error is generated because this extension does
201             *       not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
202             *       and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
203             *       bits for OpenGL ES contexts. Thus, use of these bits fall
204             *       under condition described by: "If an attribute is
205             *       specified that is not meaningful for the client API
206             *       type.." in the above specification.
207             *
208             * The spec requires that we emit the error even if the display
209             * supports EGL_EXT_create_context_robustness. To create a robust
210             * GLES context, the *attribute*
211             * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
212             * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
213             */
214            err = EGL_BAD_ATTRIBUTE;
215            break;
216         }
217
218         ctx->Flags |= val;
219         break;
220
221      case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
222         if (!dpy->Extensions.KHR_create_context) {
223            err = EGL_BAD_ATTRIBUTE;
224            break;
225         }
226
227         /* The EGL_KHR_create_context spec says:
228          *
229          *     "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
230          *     OpenGL contexts, and specifying it for other types of
231          *     contexts, including OpenGL ES contexts, will generate an
232          *     error."
233          */
234         if (api != EGL_OPENGL_API) {
235            err = EGL_BAD_ATTRIBUTE;
236            break;
237         }
238
239         ctx->Profile = val;
240         break;
241
242      case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
243         /* The EGL_KHR_create_context spec says:
244          *
245          *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
246          *     meaningful for OpenGL contexts, and specifying it for other
247          *     types of contexts, including OpenGL ES contexts, will generate
248          *     an error."
249          */
250           if (!dpy->Extensions.KHR_create_context
251               || api != EGL_OPENGL_API) {
252            err = EGL_BAD_ATTRIBUTE;
253            break;
254         }
255
256         ctx->ResetNotificationStrategy = val;
257         break;
258
259      case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
260         /* The EGL_EXT_create_context_robustness spec says:
261          *
262          *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
263          *     meaningful for OpenGL ES contexts, and specifying it for other
264          *     types of contexts will generate an EGL_BAD_ATTRIBUTE error."
265          */
266         if (!dpy->Extensions.EXT_create_context_robustness
267             || api != EGL_OPENGL_ES_API) {
268            err = EGL_BAD_ATTRIBUTE;
269            break;
270         }
271
272         ctx->ResetNotificationStrategy = val;
273         break;
274
275      case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
276         if (!dpy->Extensions.EXT_create_context_robustness) {
277            err = EGL_BAD_ATTRIBUTE;
278            break;
279         }
280
281         if (val == EGL_TRUE)
282            ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
283         break;
284
285      case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
286         if (dpy->Version < 15) {
287            err = EGL_BAD_ATTRIBUTE;
288            break;
289         }
290
291         if (val == EGL_TRUE)
292            ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
293         break;
294
295      case EGL_CONTEXT_OPENGL_DEBUG:
296         if (dpy->Version < 15) {
297            err = EGL_BAD_ATTRIBUTE;
298            break;
299         }
300
301         if (val == EGL_TRUE)
302            ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
303         break;
304
305      case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
306         if (dpy->Version < 15) {
307            err = EGL_BAD_ATTRIBUTE;
308            break;
309         }
310
311         if (val == EGL_TRUE)
312            ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
313         break;
314
315      default:
316         err = EGL_BAD_ATTRIBUTE;
317         break;
318      }
319
320      if (err != EGL_SUCCESS) {
321         _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
322         break;
323      }
324   }
325
326   if (api == EGL_OPENGL_API) {
327      /* The EGL_KHR_create_context spec says:
328       *
329       *     "If the requested OpenGL version is less than 3.2,
330       *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
331       *     functionality of the context is determined solely by the
332       *     requested version."
333       *
334       * Since the value is ignored, only validate the setting if the version
335       * is >= 3.2.
336       */
337      if (ctx->ClientMajorVersion >= 4
338          || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
339         switch (ctx->Profile) {
340         case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
341         case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
342            break;
343
344         default:
345            /* The EGL_KHR_create_context spec says:
346             *
347             *     "* If an OpenGL context is requested, the requested version
348             *        is greater than 3.2, and the value for attribute
349             *        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
350             *        any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
351             *        and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
352             *        more than one of these bits set; or if the implementation does
353             *        not support the requested profile, then an EGL_BAD_MATCH error
354             *        is generated."
355             */
356            err = EGL_BAD_MATCH;
357            break;
358         }
359      }
360
361      /* The EGL_KHR_create_context spec says:
362       *
363       *     "* If an OpenGL context is requested and the values for
364       *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
365       *        EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
366       *        the value for attribute
367       *        EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
368       *        version and feature set that are not defined, than an
369       *        EGL_BAD_MATCH error is generated.
370       *
371       *        ... Thus, examples of invalid combinations of attributes
372       *        include:
373       *
374       *          - Major version < 1 or > 4
375       *          - Major version == 1 and minor version < 0 or > 5
376       *          - Major version == 2 and minor version < 0 or > 1
377       *          - Major version == 3 and minor version < 0 or > 2
378       *          - Major version == 4 and minor version < 0 or > 2
379       *          - Forward-compatible flag set and major version < 3"
380       */
381      if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
382         err = EGL_BAD_MATCH;
383
384      switch (ctx->ClientMajorVersion) {
385      case 1:
386         if (ctx->ClientMinorVersion > 5
387             || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
388            err = EGL_BAD_MATCH;
389         break;
390
391      case 2:
392         if (ctx->ClientMinorVersion > 1
393             || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
394            err = EGL_BAD_MATCH;
395         break;
396
397      case 3:
398         /* Note: The text above is incorrect.  There *is* an OpenGL 3.3!
399          */
400         if (ctx->ClientMinorVersion > 3)
401            err = EGL_BAD_MATCH;
402         break;
403
404      case 4:
405      default:
406         /* Don't put additional version checks here.  We don't know that
407          * there won't be versions > 4.2.
408          */
409         break;
410      }
411   } else if (api == EGL_OPENGL_ES_API) {
412      /* The EGL_KHR_create_context spec says:
413       *
414       *     "* If an OpenGL ES context is requested and the values for
415       *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
416       *        EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
417       *        is not defined, than an EGL_BAD_MATCH error is generated.
418       *
419       *        ... Examples of invalid combinations of attributes include:
420       *
421       *          - Major version < 1 or > 2
422       *          - Major version == 1 and minor version < 0 or > 1
423       *          - Major version == 2 and minor version != 0
424       */
425      if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
426         err = EGL_BAD_MATCH;
427
428      switch (ctx->ClientMajorVersion) {
429      case 1:
430         if (ctx->ClientMinorVersion > 1)
431            err = EGL_BAD_MATCH;
432         break;
433
434      case 2:
435         if (ctx->ClientMinorVersion > 0)
436            err = EGL_BAD_MATCH;
437         break;
438
439      case 3:
440         /* Don't put additional version checks here.  We don't know that
441          * there won't be versions > 3.0.
442          */
443         break;
444
445      default:
446         err = EGL_BAD_MATCH;
447         break;
448      }
449   }
450
451   switch (ctx->ResetNotificationStrategy) {
452   case EGL_NO_RESET_NOTIFICATION_KHR:
453   case EGL_LOSE_CONTEXT_ON_RESET_KHR:
454      break;
455
456   default:
457      err = EGL_BAD_ATTRIBUTE;
458      break;
459   }
460
461   if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
462                      | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
463                      | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
464      err = EGL_BAD_ATTRIBUTE;
465   }
466
467   return err;
468}
469
470
471/**
472 * Initialize the given _EGLContext object to defaults and/or the values
473 * in the attrib_list.
474 *
475 * According to EGL 1.5 Section 3.7:
476 *
477 *	"EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
478 *	purposes except eglCreateContext."
479 *
480 * And since we only support GL and GLES, this is the only place where the
481 * bound API matters at all. We look up the current API from the current
482 * thread, and stash that in the context we're initializing. Our caller is
483 * responsible for determining whether that's an API it supports.
484 */
485EGLBoolean
486_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
487                const EGLint *attrib_list)
488{
489   const EGLenum api = eglQueryAPI();
490   EGLint err;
491
492   if (api == EGL_NONE) {
493      _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
494      return EGL_FALSE;
495   }
496
497   _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
498   ctx->ClientAPI = api;
499   ctx->Config = conf;
500   ctx->WindowRenderBuffer = EGL_NONE;
501   ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
502
503   ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
504   ctx->ClientMinorVersion = 0;
505   ctx->Flags = 0;
506   ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
507   ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
508
509   err = _eglParseContextAttribList(ctx, dpy, attrib_list);
510   if (err == EGL_SUCCESS && ctx->Config) {
511      EGLint api_bit;
512
513      api_bit = _eglGetContextAPIBit(ctx);
514      if (!(ctx->Config->RenderableType & api_bit)) {
515         _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
516               api_bit, ctx->Config->RenderableType);
517         err = EGL_BAD_CONFIG;
518      }
519   }
520   if (err != EGL_SUCCESS)
521      return _eglError(err, "eglCreateContext");
522
523   return EGL_TRUE;
524}
525
526
527static EGLint
528_eglQueryContextRenderBuffer(_EGLContext *ctx)
529{
530   _EGLSurface *surf = ctx->DrawSurface;
531   EGLint rb;
532
533   if (!surf)
534      return EGL_NONE;
535   if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
536      rb = ctx->WindowRenderBuffer;
537   else
538      rb = surf->RenderBuffer;
539   return rb;
540}
541
542
543EGLBoolean
544_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
545                 EGLint attribute, EGLint *value)
546{
547   (void) drv;
548   (void) dpy;
549
550   if (!value)
551      return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
552
553   switch (attribute) {
554   case EGL_CONFIG_ID:
555      /*
556       * From EGL_KHR_no_config_context:
557       *
558       *    "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
559       *     respect to which the context was created, or zero if created
560       *     without respect to an EGLConfig."
561       */
562      *value = c->Config ? c->Config->ConfigID : 0;
563      break;
564   case EGL_CONTEXT_CLIENT_VERSION:
565      *value = c->ClientMajorVersion;
566      break;
567   case EGL_CONTEXT_CLIENT_TYPE:
568      *value = c->ClientAPI;
569      break;
570   case EGL_RENDER_BUFFER:
571      *value = _eglQueryContextRenderBuffer(c);
572      break;
573   default:
574      return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
575   }
576
577   return EGL_TRUE;
578}
579
580
581/**
582 * Bind the context to the thread and return the previous context.
583 *
584 * Note that the context may be NULL.
585 */
586static _EGLContext *
587_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
588{
589   _EGLContext *oldCtx;
590
591   oldCtx = t->CurrentContext;
592   if (ctx != oldCtx) {
593      if (oldCtx)
594         oldCtx->Binding = NULL;
595      if (ctx)
596         ctx->Binding = t;
597
598      t->CurrentContext = ctx;
599   }
600
601   return oldCtx;
602}
603
604
605/**
606 * Return true if the given context and surfaces can be made current.
607 */
608static EGLBoolean
609_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
610{
611   _EGLThreadInfo *t = _eglGetCurrentThread();
612   _EGLDisplay *dpy;
613
614   if (_eglIsCurrentThreadDummy())
615      return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
616
617   /* this is easy */
618   if (!ctx) {
619      if (draw || read)
620         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
621      return EGL_TRUE;
622   }
623
624   dpy = ctx->Resource.Display;
625   if (!dpy->Extensions.KHR_surfaceless_context
626       && (draw == NULL || read == NULL))
627      return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
628
629   /*
630    * The spec says
631    *
632    * "If ctx is current to some other thread, or if either draw or read are
633    * bound to contexts in another thread, an EGL_BAD_ACCESS error is
634    * generated."
635    *
636    * and
637    *
638    * "at most one context may be bound to a particular surface at a given
639    * time"
640    */
641   if (ctx->Binding && ctx->Binding != t)
642      return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
643   if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
644      if (draw->CurrentContext->Binding != t)
645         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
646   }
647   if (read && read->CurrentContext && read->CurrentContext != ctx) {
648      if (read->CurrentContext->Binding != t)
649         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
650   }
651
652   /* If the context has a config then it must match that of the two
653    * surfaces */
654   if (ctx->Config) {
655      if ((draw && draw->Config != ctx->Config) ||
656          (read && read->Config != ctx->Config))
657         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
658   } else {
659      /* Otherwise we must be using the EGL_KHR_no_config_context
660       * extension */
661      assert(dpy->Extensions.KHR_no_config_context);
662
663      /* The extension doesn't permit binding draw and read buffers with
664       * differing contexts */
665      if (draw && read && draw->Config != read->Config)
666         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
667   }
668
669   return EGL_TRUE;
670}
671
672
673/**
674 * Bind the context to the current thread and given surfaces.  Return the
675 * previous bound context and surfaces.  The caller should unreference the
676 * returned context and surfaces.
677 *
678 * Making a second call with the resources returned by the first call
679 * unsurprisingly undoes the first call, except for the resouce reference
680 * counts.
681 */
682EGLBoolean
683_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
684                _EGLContext **old_ctx,
685                _EGLSurface **old_draw, _EGLSurface **old_read)
686{
687   _EGLThreadInfo *t = _eglGetCurrentThread();
688   _EGLContext *prev_ctx;
689   _EGLSurface *prev_draw, *prev_read;
690
691   if (!_eglCheckMakeCurrent(ctx, draw, read))
692      return EGL_FALSE;
693
694   /* increment refcounts before binding */
695   _eglGetContext(ctx);
696   _eglGetSurface(draw);
697   _eglGetSurface(read);
698
699   /* bind the new context */
700   prev_ctx = _eglBindContextToThread(ctx, t);
701
702   /* break previous bindings */
703   if (prev_ctx) {
704      prev_draw = prev_ctx->DrawSurface;
705      prev_read = prev_ctx->ReadSurface;
706
707      if (prev_draw)
708         prev_draw->CurrentContext = NULL;
709      if (prev_read)
710         prev_read->CurrentContext = NULL;
711
712      prev_ctx->DrawSurface = NULL;
713      prev_ctx->ReadSurface = NULL;
714   }
715   else {
716      prev_draw = prev_read = NULL;
717   }
718
719   /* establish new bindings */
720   if (ctx) {
721      if (draw)
722         draw->CurrentContext = ctx;
723      if (read)
724         read->CurrentContext = ctx;
725
726      ctx->DrawSurface = draw;
727      ctx->ReadSurface = read;
728   }
729
730   assert(old_ctx && old_draw && old_read);
731   *old_ctx = prev_ctx;
732   *old_draw = prev_draw;
733   *old_read = prev_read;
734
735   return EGL_TRUE;
736}
737