2 * Copyright © 2011 Intel Corporation
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:
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
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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
27 #include <GL/glxtokens.h>
28 #include "glxserver.h"
30 #include "indirect_dispatch.h"
32 #define ALL_VALID_FLAGS \
33 (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \
34 | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
37 validate_GL_version(int major_version
, int minor_version
)
39 if (major_version
<= 0 || minor_version
< 0)
42 switch (major_version
) {
44 if (minor_version
> 5)
49 if (minor_version
> 1)
54 if (minor_version
> 3)
66 validate_render_type(uint32_t render_type
)
68 switch (render_type
) {
70 case GLX_COLOR_INDEX_TYPE
:
71 case GLX_RGBA_FLOAT_TYPE_ARB
:
72 case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT
:
80 __glXDisp_CreateContextAttribsARB(__GLXclientState
* cl
, GLbyte
* pc
)
82 ClientPtr client
= cl
->client
;
83 xGLXCreateContextAttribsARBReq
*req
= (xGLXCreateContextAttribsARBReq
*) pc
;
84 int32_t *attribs
= (req
->numAttribs
!= 0) ? (int32_t *) (req
+ 1) : NULL
;
86 int major_version
= 1;
87 int minor_version
= 0;
89 uint32_t render_type
= GLX_RGBA_TYPE
;
90 __GLXcontext
*ctx
= NULL
;
91 __GLXcontext
*shareCtx
= NULL
;
92 __GLXscreen
*glxScreen
;
96 /* The GLX_ARB_create_context_robustness spec says:
98 * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
99 * is GLX_NO_RESET_NOTIFICATION_ARB."
101 int reset
= GLX_NO_RESET_NOTIFICATION_ARB
;
103 /* The GLX_ARB_create_context_profile spec says:
105 * "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is
106 * GLX_CONTEXT_CORE_PROFILE_BIT_ARB."
108 * The core profile only makes sense for OpenGL versions 3.2 and later.
109 * If the version ultimately specified is less than 3.2, the core profile
110 * bit is cleared (see below).
112 int profile
= GLX_CONTEXT_CORE_PROFILE_BIT_ARB
;
114 /* Verify that the size of the packet matches the size inferred from the
115 * sizes specified for the various fields.
117 const unsigned expected_size
= (sz_xGLXCreateContextAttribsARBReq
118 + (req
->numAttribs
* 8)) / 4;
120 if (req
->length
!= expected_size
)
123 LEGAL_NEW_RESOURCE(req
->context
, client
);
125 /* The GLX_ARB_create_context spec says:
127 * "* If <config> is not a valid GLXFBConfig, GLXBadFBConfig is
130 * On the client, the screen comes from the FBConfig, so GLXBadFBConfig
131 * should be issued if the screen is nonsense.
133 if (!validGlxScreen(client
, req
->screen
, &glxScreen
, &err
))
134 return __glXError(GLXBadFBConfig
);
136 if (!validGlxFBConfig(client
, glxScreen
, req
->fbconfig
, &config
, &err
))
137 return __glXError(GLXBadFBConfig
);
139 /* Validate the context with which the new context should share resources.
141 if (req
->shareList
!= None
) {
142 if (!validGlxContext(client
, req
->shareList
, DixReadAccess
,
146 /* The crazy condition is because C doesn't have a logical XOR
147 * operator. Comparing directly for equality may fail if one is 1 and
148 * the other is 2 even though both are logically true.
150 if (!!req
->isDirect
!= !!shareCtx
->isDirect
) {
151 client
->errorValue
= req
->shareList
;
155 /* The GLX_ARB_create_context spec says:
157 * "* If the server context state for <share_context>...was
158 * created on a different screen than the one referenced by
159 * <config>...BadMatch is generated."
161 if (glxScreen
!= shareCtx
->pGlxScreen
) {
162 client
->errorValue
= shareCtx
->pGlxScreen
->pScreen
->myNum
;
167 for (i
= 0; i
< req
->numAttribs
; i
++) {
168 switch (attribs
[i
* 2]) {
169 case GLX_CONTEXT_MAJOR_VERSION_ARB
:
170 major_version
= attribs
[2 * i
+ 1];
173 case GLX_CONTEXT_MINOR_VERSION_ARB
:
174 minor_version
= attribs
[2 * i
+ 1];
177 case GLX_CONTEXT_FLAGS_ARB
:
178 flags
= attribs
[2 * i
+ 1];
181 case GLX_RENDER_TYPE
:
182 render_type
= attribs
[2 * i
+ 1];
185 case GLX_CONTEXT_PROFILE_MASK_ARB
:
186 profile
= attribs
[2 * i
+ 1];
189 case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
:
190 reset
= attribs
[2 * i
+ 1];
191 if (reset
!= GLX_NO_RESET_NOTIFICATION_ARB
192 && reset
!= GLX_LOSE_CONTEXT_ON_RESET_ARB
)
202 /* The GLX_ARB_create_context spec says:
204 * "If attributes GLX_CONTEXT_MAJOR_VERSION_ARB and
205 * GLX_CONTEXT_MINOR_VERSION_ARB, when considered together
206 * with attributes GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB and
207 * GLX_RENDER_TYPE, specify an OpenGL version and feature set
208 * that are not defined, BadMatch is generated.
210 * ...Feature deprecation was introduced with OpenGL 3.0, so
211 * forward-compatible contexts may only be requested for
212 * OpenGL 3.0 and above. Thus, examples of invalid
213 * combinations of attributes include:
215 * - Major version < 1 or > 3
216 * - Major version == 1 and minor version < 0 or > 5
217 * - Major version == 2 and minor version < 0 or > 1
218 * - Major version == 3 and minor version > 2
219 * - Forward-compatible flag set and major version < 3
220 * - Color index rendering and major version >= 3"
222 if (!validate_GL_version(major_version
, minor_version
))
225 if (major_version
< 3
226 && ((flags
& GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
) != 0))
229 if (major_version
>= 3 && render_type
== GLX_COLOR_INDEX_TYPE
)
232 if (!validate_render_type(render_type
))
235 if ((flags
& ~ALL_VALID_FLAGS
) != 0)
238 /* The GLX_ARB_create_context_profile spec says:
240 * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; has
241 * any bits set other than GLX_CONTEXT_CORE_PROFILE_BIT_ARB and
242 * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; has more than one of
243 * these bits set; or if the implementation does not support the
244 * requested profile, then GLXBadProfileARB is generated."
247 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB
:
248 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
:
250 case GLX_CONTEXT_ES2_PROFILE_BIT_EXT
:
251 /* The GLX_EXT_create_context_es2_profile spec says:
253 * "... If the version requested is 2.0, and the
254 * GLX_CONTEXT_ES2_PROFILE_BIT_EXT bit is set in the
255 * GLX_CONTEXT_PROFILE_MASK_ARB attribute (see below), then the
256 * context returned will implement OpenGL ES 2.0."
260 * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set;
261 * has any bits set other than
262 * GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
263 * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, or
264 * GLX_CONTEXT_ES2_PROFILE_BIT_EXT; has more than one of these
265 * bits set; or if the implementation does not supported the
266 * requested profile, then GLXBadProfileARB is generated."
268 * It does not specifically say what is supposed to happen if
269 * GLX_CONTEXT_ES2_PROFILE_BIT_EXT is set but the version requested is
270 * not 2.0. We choose to generate GLXBadProfileARB as this matches
273 if (major_version
!= 2 || minor_version
!= 0)
274 return __glXError(GLXBadProfileARB
);
277 return __glXError(GLXBadProfileARB
);
280 /* The GLX_ARB_create_context_robustness spec says:
282 * "* If the reset notification behavior of <share_context> and the
283 * newly created context are different, BadMatch is generated."
285 if (shareCtx
!= NULL
&& shareCtx
->resetNotificationStrategy
!= reset
)
288 /* There is no GLX protocol for desktop OpenGL versions after 1.4. There
289 * is no GLX protocol for any version of OpenGL ES. If the application is
290 * requested an indirect rendering context for a version that cannot be
291 * satisfied, reject it.
293 * The GLX_ARB_create_context spec says:
295 * "* If <config> does not support compatible OpenGL contexts
296 * providing the requested API major and minor version,
297 * forward-compatible flag, and debug context flag, GLXBadFBConfig
300 if (!req
->isDirect
&& (major_version
> 1 || minor_version
> 4
301 || profile
== GLX_CONTEXT_ES2_PROFILE_BIT_EXT
)) {
302 return __glXError(GLXBadFBConfig
);
305 /* Allocate memory for the new context
308 ctx
= __glXdirectContextCreate(glxScreen
, config
, shareCtx
);
312 ctx
= glxScreen
->createContext(glxScreen
, config
, shareCtx
,
313 req
->numAttribs
, (uint32_t *) attribs
,
320 ctx
->pGlxScreen
= glxScreen
;
321 ctx
->config
= config
;
322 ctx
->id
= req
->context
;
323 ctx
->share_id
= req
->shareList
;
324 ctx
->idExists
= True
;
325 ctx
->currentClient
= False
;
326 ctx
->isDirect
= req
->isDirect
;
327 ctx
->hasUnflushedCommands
= False
;
328 ctx
->renderMode
= GL_RENDER
;
329 ctx
->feedbackBuf
= NULL
;
330 ctx
->feedbackBufSize
= 0;
331 ctx
->selectBuf
= NULL
;
332 ctx
->selectBufSize
= 0;
333 ctx
->drawPriv
= NULL
;
334 ctx
->readPriv
= NULL
;
335 ctx
->resetNotificationStrategy
= reset
;
337 /* Add the new context to the various global tables of GLX contexts.
339 if (!__glXAddContext(ctx
)) {
340 (*ctx
->destroy
) (ctx
);
341 client
->errorValue
= req
->context
;
349 __glXDispSwap_CreateContextAttribsARB(__GLXclientState
* cl
, GLbyte
* pc
)