1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
26 
27 #include <GL/glxtokens.h>
28 #include "glxserver.h"
29 #include "glxext.h"
30 #include "indirect_dispatch.h"
31 #include "opaque.h"
32 
33 #define ALL_VALID_FLAGS \
34     (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \
35      | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
36 
37 static Bool
validate_GL_version(int major_version,int minor_version)38 validate_GL_version(int major_version, int minor_version)
39 {
40     if (major_version <= 0 || minor_version < 0)
41         return FALSE;
42 
43     switch (major_version) {
44     case 1:
45         if (minor_version > 5)
46             return FALSE;
47         break;
48 
49     case 2:
50         if (minor_version > 1)
51             return FALSE;
52         break;
53 
54     case 3:
55         if (minor_version > 3)
56             return FALSE;
57         break;
58 
59     default:
60         break;
61     }
62 
63     return TRUE;
64 }
65 
66 static Bool
validate_render_type(uint32_t render_type)67 validate_render_type(uint32_t render_type)
68 {
69     switch (render_type) {
70     case GLX_RGBA_TYPE:
71     case GLX_COLOR_INDEX_TYPE:
72     case GLX_RGBA_FLOAT_TYPE_ARB:
73     case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT:
74         return TRUE;
75     default:
76         return FALSE;
77     }
78 }
79 
80 int
__glXDisp_CreateContextAttribsARB(__GLXclientState * cl,GLbyte * pc)81 __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
82 {
83     ClientPtr client = cl->client;
84     xGLXCreateContextAttribsARBReq *req = (xGLXCreateContextAttribsARBReq *) pc;
85     int32_t *attribs = (req->numAttribs != 0) ? (int32_t *) (req + 1) : NULL;
86     unsigned i;
87     int major_version = 1;
88     int minor_version = 0;
89     uint32_t flags = 0;
90     uint32_t render_type = GLX_RGBA_TYPE;
91 #ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
92     uint32_t flush = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
93 #endif
94     __GLXcontext *ctx = NULL;
95     __GLXcontext *shareCtx = NULL;
96     __GLXscreen *glxScreen;
97     __GLXconfig *config = NULL;
98     int err;
99 
100     /* The GLX_ARB_create_context_robustness spec says:
101      *
102      *     "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
103      *     is GLX_NO_RESET_NOTIFICATION_ARB."
104      */
105     int reset = GLX_NO_RESET_NOTIFICATION_ARB;
106 
107     /* The GLX_ARB_create_context_profile spec says:
108      *
109      *     "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is
110      *     GLX_CONTEXT_CORE_PROFILE_BIT_ARB."
111      *
112      * The core profile only makes sense for OpenGL versions 3.2 and later.
113      * If the version ultimately specified is less than 3.2, the core profile
114      * bit is cleared (see below).
115      */
116     int profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
117 
118     /* Verify that the size of the packet matches the size inferred from the
119      * sizes specified for the various fields.
120      */
121     const unsigned expected_size = (sz_xGLXCreateContextAttribsARBReq
122                                     + (req->numAttribs * 8)) / 4;
123 
124     if (req->length != expected_size)
125         return BadLength;
126 
127     /* The GLX_ARB_create_context spec says:
128      *
129      *     "* If <config> is not a valid GLXFBConfig, GLXBadFBConfig is
130      *        generated."
131      *
132      * On the client, the screen comes from the FBConfig, so GLXBadFBConfig
133      * should be issued if the screen is nonsense.
134      */
135     if (!validGlxScreen(client, req->screen, &glxScreen, &err))
136         return __glXError(GLXBadFBConfig);
137 
138     if (req->fbconfig) {
139         if (!validGlxFBConfig(client, glxScreen, req->fbconfig, &config, &err))
140             return __glXError(GLXBadFBConfig);
141     }
142 
143     /* Validate the context with which the new context should share resources.
144      */
145     if (req->shareList != None) {
146         if (!validGlxContext(client, req->shareList, DixReadAccess,
147                              &shareCtx, &err))
148             return err;
149 
150         /* The crazy condition is because C doesn't have a logical XOR
151          * operator.  Comparing directly for equality may fail if one is 1 and
152          * the other is 2 even though both are logically true.
153          */
154         if (!!req->isDirect != !!shareCtx->isDirect) {
155             client->errorValue = req->shareList;
156             return BadMatch;
157         }
158 
159         /* The GLX_ARB_create_context spec says:
160          *
161          *     "* If the server context state for <share_context>...was
162          *        created on a different screen than the one referenced by
163          *        <config>...BadMatch is generated."
164          */
165         if (glxScreen != shareCtx->pGlxScreen) {
166             client->errorValue = shareCtx->pGlxScreen->pScreen->myNum;
167             return BadMatch;
168         }
169     }
170 
171     for (i = 0; i < req->numAttribs; i++) {
172         switch (attribs[i * 2]) {
173         case GLX_CONTEXT_MAJOR_VERSION_ARB:
174             major_version = attribs[2 * i + 1];
175             break;
176 
177         case GLX_CONTEXT_MINOR_VERSION_ARB:
178             minor_version = attribs[2 * i + 1];
179             break;
180 
181         case GLX_CONTEXT_FLAGS_ARB:
182             flags = attribs[2 * i + 1];
183             break;
184 
185         case GLX_RENDER_TYPE:
186             /* Not valid for GLX_EXT_no_config_context */
187             if (!req->fbconfig)
188                 return BadValue;
189             render_type = attribs[2 * i + 1];
190             break;
191 
192         case GLX_CONTEXT_PROFILE_MASK_ARB:
193             profile = attribs[2 * i + 1];
194             break;
195 
196         case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
197             reset = attribs[2 * i + 1];
198             if (reset != GLX_NO_RESET_NOTIFICATION_ARB
199                 && reset != GLX_LOSE_CONTEXT_ON_RESET_ARB)
200                 return BadValue;
201 
202             break;
203 
204 #ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
205         case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB:
206             flush = attribs[2 * i + 1];
207             if (flush != GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB
208                 && flush != GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB)
209                 return BadValue;
210             break;
211 #endif
212 
213         case GLX_SCREEN:
214             /* Only valid for GLX_EXT_no_config_context */
215             if (req->fbconfig)
216                 return BadValue;
217             /* Must match the value in the request header */
218             if (attribs[2 * i + 1] != req->screen)
219                 return BadValue;
220             break;
221 
222         case GLX_CONTEXT_OPENGL_NO_ERROR_ARB:
223             /* ignore */
224             break;
225 
226         default:
227             if (!req->isDirect)
228                 return BadValue;
229             break;
230         }
231     }
232 
233     /* The GLX_ARB_create_context spec says:
234      *
235      *     "If attributes GLX_CONTEXT_MAJOR_VERSION_ARB and
236      *     GLX_CONTEXT_MINOR_VERSION_ARB, when considered together
237      *     with attributes GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB and
238      *     GLX_RENDER_TYPE, specify an OpenGL version and feature set
239      *     that are not defined, BadMatch is generated.
240      *
241      *     ...Feature deprecation was introduced with OpenGL 3.0, so
242      *     forward-compatible contexts may only be requested for
243      *     OpenGL 3.0 and above. Thus, examples of invalid
244      *     combinations of attributes include:
245      *
246      *       - Major version < 1 or > 3
247      *       - Major version == 1 and minor version < 0 or > 5
248      *       - Major version == 2 and minor version < 0 or > 1
249      *       - Major version == 3 and minor version > 2
250      *       - Forward-compatible flag set and major version < 3
251      *       - Color index rendering and major version >= 3"
252      */
253     if (!validate_GL_version(major_version, minor_version))
254         return BadMatch;
255 
256     if (major_version < 3
257         && ((flags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) != 0))
258         return BadMatch;
259 
260     if (major_version >= 3 && render_type == GLX_COLOR_INDEX_TYPE)
261         return BadMatch;
262 
263     if (!validate_render_type(render_type))
264         return BadValue;
265 
266     if ((flags & ~ALL_VALID_FLAGS) != 0)
267         return BadValue;
268 
269     /* The GLX_ARB_create_context_profile spec says:
270      *
271      *     "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; has
272      *        any bits set other than GLX_CONTEXT_CORE_PROFILE_BIT_ARB and
273      *        GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; has more than one of
274      *        these bits set; or if the implementation does not support the
275      *        requested profile, then GLXBadProfileARB is generated."
276      *
277      * The GLX_EXT_create_context_es2_profile spec doesn't exactly say what
278      * is supposed to happen if an invalid version is set, but it doesn't
279      * much matter as support for GLES contexts is only defined for direct
280      * contexts (at the moment anyway) so we can leave it up to the driver
281      * to validate.
282      */
283     switch (profile) {
284     case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
285     case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
286     case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
287         break;
288     default:
289         return __glXError(GLXBadProfileARB);
290     }
291 
292     /* The GLX_ARB_create_context_robustness spec says:
293      *
294      *     "* If the reset notification behavior of <share_context> and the
295      *        newly created context are different, BadMatch is generated."
296      */
297     if (shareCtx != NULL && shareCtx->resetNotificationStrategy != reset)
298         return BadMatch;
299 
300     /* There is no GLX protocol for desktop OpenGL versions after 1.4.  There
301      * is no GLX protocol for any version of OpenGL ES.  If the application is
302      * requested an indirect rendering context for a version that cannot be
303      * satisfied, reject it.
304      *
305      * The GLX_ARB_create_context spec says:
306      *
307      *     "* If <config> does not support compatible OpenGL contexts
308      *        providing the requested API major and minor version,
309      *        forward-compatible flag, and debug context flag, GLXBadFBConfig
310      *        is generated."
311      */
312     if (!req->isDirect && (major_version > 1 || minor_version > 4
313                            || profile == GLX_CONTEXT_ES2_PROFILE_BIT_EXT)) {
314         return __glXError(GLXBadFBConfig);
315     }
316 
317     /* Allocate memory for the new context
318      */
319     if (req->isDirect) {
320         ctx = __glXdirectContextCreate(glxScreen, config, shareCtx);
321         err = BadAlloc;
322     }
323     else {
324         /* Only allow creating indirect GLX contexts if allowed by
325          * server command line.  Indirect GLX is of limited use (since
326          * it's only GL 1.4), it's slower than direct contexts, and
327          * it's a massive attack surface for buffer overflow type
328          * errors.
329          */
330         if (!enableIndirectGLX) {
331             client->errorValue = req->isDirect;
332             return BadValue;
333         }
334 
335         ctx = glxScreen->createContext(glxScreen, config, shareCtx,
336                                        req->numAttribs, (uint32_t *) attribs,
337                                        &err);
338     }
339 
340     if (ctx == NULL)
341         return err;
342 
343     ctx->pGlxScreen = glxScreen;
344     ctx->config = config;
345     ctx->id = req->context;
346     ctx->share_id = req->shareList;
347     ctx->idExists = TRUE;
348     ctx->isDirect = req->isDirect;
349     ctx->renderMode = GL_RENDER;
350     ctx->resetNotificationStrategy = reset;
351 #ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
352     ctx->releaseBehavior = flush;
353 #endif
354 
355     /* Add the new context to the various global tables of GLX contexts.
356      */
357     if (!__glXAddContext(ctx)) {
358         (*ctx->destroy) (ctx);
359         client->errorValue = req->context;
360         return BadAlloc;
361     }
362 
363     return Success;
364 }
365 
366 int
__glXDispSwap_CreateContextAttribsARB(__GLXclientState * cl,GLbyte * pc)367 __glXDispSwap_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
368 {
369     return BadRequest;
370 }
371