Imported Upstream version 1.15.1
[deb_xorg-server.git] / glx / createcontext.c
CommitLineData
a09e091a
JB
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
32#define ALL_VALID_FLAGS \
33 (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \
34 | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
35
36static Bool
37validate_GL_version(int major_version, int minor_version)
38{
39 if (major_version <= 0 || minor_version < 0)
40 return False;
41
42 switch (major_version) {
43 case 1:
44 if (minor_version > 5)
45 return False;
46 break;
47
48 case 2:
49 if (minor_version > 1)
50 return False;
51 break;
52
53 case 3:
54 if (minor_version > 3)
55 return False;
56 break;
57
58 default:
59 break;
60 }
61
62 return True;
63}
64
65static Bool
66validate_render_type(uint32_t render_type)
67{
68 switch (render_type) {
69 case GLX_RGBA_TYPE:
70 case GLX_COLOR_INDEX_TYPE:
71 case GLX_RGBA_FLOAT_TYPE_ARB:
72 case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT:
73 return True;
74 default:
75 return False;
76 }
77}
78
79int
80__glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
81{
82 ClientPtr client = cl->client;
83 xGLXCreateContextAttribsARBReq *req = (xGLXCreateContextAttribsARBReq *) pc;
84 int32_t *attribs = (req->numAttribs != 0) ? (int32_t *) (req + 1) : NULL;
85 unsigned i;
86 int major_version = 1;
87 int minor_version = 0;
88 uint32_t flags = 0;
89 uint32_t render_type = GLX_RGBA_TYPE;
90 __GLXcontext *ctx = NULL;
91 __GLXcontext *shareCtx = NULL;
92 __GLXscreen *glxScreen;
93 __GLXconfig *config;
94 int err;
95
96 /* The GLX_ARB_create_context_robustness spec says:
97 *
98 * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
99 * is GLX_NO_RESET_NOTIFICATION_ARB."
100 */
101 int reset = GLX_NO_RESET_NOTIFICATION_ARB;
102
103 /* The GLX_ARB_create_context_profile spec says:
104 *
105 * "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is
106 * GLX_CONTEXT_CORE_PROFILE_BIT_ARB."
107 *
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).
111 */
112 int profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
113
114 /* Verify that the size of the packet matches the size inferred from the
115 * sizes specified for the various fields.
116 */
117 const unsigned expected_size = (sz_xGLXCreateContextAttribsARBReq
118 + (req->numAttribs * 8)) / 4;
119
120 if (req->length != expected_size)
121 return BadLength;
122
123 LEGAL_NEW_RESOURCE(req->context, client);
124
125 /* The GLX_ARB_create_context spec says:
126 *
127 * "* If <config> is not a valid GLXFBConfig, GLXBadFBConfig is
128 * generated."
129 *
130 * On the client, the screen comes from the FBConfig, so GLXBadFBConfig
131 * should be issued if the screen is nonsense.
132 */
133 if (!validGlxScreen(client, req->screen, &glxScreen, &err))
134 return __glXError(GLXBadFBConfig);
135
136 if (!validGlxFBConfig(client, glxScreen, req->fbconfig, &config, &err))
137 return __glXError(GLXBadFBConfig);
138
139 /* Validate the context with which the new context should share resources.
140 */
141 if (req->shareList != None) {
142 if (!validGlxContext(client, req->shareList, DixReadAccess,
143 &shareCtx, &err))
144 return err;
145
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.
149 */
150 if (!!req->isDirect != !!shareCtx->isDirect) {
151 client->errorValue = req->shareList;
152 return BadMatch;
153 }
154
155 /* The GLX_ARB_create_context spec says:
156 *
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."
160 */
161 if (glxScreen != shareCtx->pGlxScreen) {
162 client->errorValue = shareCtx->pGlxScreen->pScreen->myNum;
163 return BadMatch;
164 }
165 }
166
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];
171 break;
172
173 case GLX_CONTEXT_MINOR_VERSION_ARB:
174 minor_version = attribs[2 * i + 1];
175 break;
176
177 case GLX_CONTEXT_FLAGS_ARB:
178 flags = attribs[2 * i + 1];
179 break;
180
181 case GLX_RENDER_TYPE:
182 render_type = attribs[2 * i + 1];
183 break;
184
185 case GLX_CONTEXT_PROFILE_MASK_ARB:
186 profile = attribs[2 * i + 1];
187 break;
188
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)
193 return BadValue;
194
195 break;
196
197 default:
198 return BadValue;
199 }
200 }
201
202 /* The GLX_ARB_create_context spec says:
203 *
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.
209 *
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:
214 *
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"
221 */
222 if (!validate_GL_version(major_version, minor_version))
223 return BadMatch;
224
225 if (major_version < 3
226 && ((flags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) != 0))
227 return BadMatch;
228
229 if (major_version >= 3 && render_type == GLX_COLOR_INDEX_TYPE)
230 return BadMatch;
231
232 if (!validate_render_type(render_type))
233 return BadValue;
234
235 if ((flags & ~ALL_VALID_FLAGS) != 0)
236 return BadValue;
237
238 /* The GLX_ARB_create_context_profile spec says:
239 *
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."
245 */
246 switch (profile) {
247 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
248 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
249 break;
250 case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
251 /* The GLX_EXT_create_context_es2_profile spec says:
252 *
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."
257 *
258 * It also says:
259 *
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."
267 *
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
271 * NVIDIA's behavior.
272 */
273 if (major_version != 2 || minor_version != 0)
274 return __glXError(GLXBadProfileARB);
275 break;
276 default:
277 return __glXError(GLXBadProfileARB);
278 }
279
280 /* The GLX_ARB_create_context_robustness spec says:
281 *
282 * "* If the reset notification behavior of <share_context> and the
283 * newly created context are different, BadMatch is generated."
284 */
285 if (shareCtx != NULL && shareCtx->resetNotificationStrategy != reset)
286 return BadMatch;
287
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.
292 *
293 * The GLX_ARB_create_context spec says:
294 *
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
298 * is generated."
299 */
300 if (!req->isDirect && (major_version > 1 || minor_version > 4
301 || profile == GLX_CONTEXT_ES2_PROFILE_BIT_EXT)) {
302 return __glXError(GLXBadFBConfig);
303 }
304
305 /* Allocate memory for the new context
306 */
307 if (req->isDirect) {
308 ctx = __glXdirectContextCreate(glxScreen, config, shareCtx);
309 err = BadAlloc;
310 }
311 else {
312 ctx = glxScreen->createContext(glxScreen, config, shareCtx,
313 req->numAttribs, (uint32_t *) attribs,
314 &err);
315 }
316
317 if (ctx == NULL)
318 return err;
319
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;
336
337 /* Add the new context to the various global tables of GLX contexts.
338 */
339 if (!__glXAddContext(ctx)) {
340 (*ctx->destroy) (ctx);
341 client->errorValue = req->context;
342 return BadAlloc;
343 }
344
345 return Success;
346}
347
348int
349__glXDispSwap_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
350{
351 return BadRequest;
352}