Merge branch 'wip/nir-vtn' into vulkan
[mesa.git] / src / egl / main / eglsurface.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010 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 /**
32 * Surface-related functions.
33 */
34
35
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "egldisplay.h"
40 #include "egldriver.h"
41 #include "eglcontext.h"
42 #include "eglconfig.h"
43 #include "eglcurrent.h"
44 #include "egllog.h"
45 #include "eglsurface.h"
46
47
48 static void
49 _eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
50 {
51 EGLint bound = surf->Config->MaxSwapInterval;
52 if (interval >= bound) {
53 interval = bound;
54 }
55 else {
56 bound = surf->Config->MinSwapInterval;
57 if (interval < bound)
58 interval = bound;
59 }
60 surf->SwapInterval = interval;
61 }
62
63
64 /**
65 * Parse the list of surface attributes and return the proper error code.
66 */
67 static EGLint
68 _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
69 {
70 _EGLDisplay *dpy = surf->Resource.Display;
71 EGLint type = surf->Type;
72 EGLint texture_type = EGL_PBUFFER_BIT;
73 EGLint i, err = EGL_SUCCESS;
74
75 if (!attrib_list)
76 return EGL_SUCCESS;
77
78 if (dpy->Extensions.NOK_texture_from_pixmap)
79 texture_type |= EGL_PIXMAP_BIT;
80
81 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
82 EGLint attr = attrib_list[i++];
83 EGLint val = attrib_list[i];
84
85 switch (attr) {
86 /* common attributes */
87 case EGL_VG_COLORSPACE:
88 switch (val) {
89 case EGL_VG_COLORSPACE_sRGB:
90 case EGL_VG_COLORSPACE_LINEAR:
91 break;
92 default:
93 err = EGL_BAD_ATTRIBUTE;
94 break;
95 }
96 if (err != EGL_SUCCESS)
97 break;
98 surf->VGColorspace = val;
99 break;
100 case EGL_VG_ALPHA_FORMAT:
101 switch (val) {
102 case EGL_VG_ALPHA_FORMAT_NONPRE:
103 case EGL_VG_ALPHA_FORMAT_PRE:
104 break;
105 default:
106 err = EGL_BAD_ATTRIBUTE;
107 break;
108 }
109 if (err != EGL_SUCCESS)
110 break;
111 surf->VGAlphaFormat = val;
112 break;
113 /* window surface attributes */
114 case EGL_RENDER_BUFFER:
115 if (type != EGL_WINDOW_BIT) {
116 err = EGL_BAD_ATTRIBUTE;
117 break;
118 }
119 if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
120 err = EGL_BAD_ATTRIBUTE;
121 break;
122 }
123 surf->RenderBuffer = val;
124 break;
125 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
126 if (!dpy->Extensions.NV_post_sub_buffer ||
127 type != EGL_WINDOW_BIT) {
128 err = EGL_BAD_ATTRIBUTE;
129 break;
130 }
131 if (val != EGL_TRUE && val != EGL_FALSE) {
132 err = EGL_BAD_PARAMETER;
133 break;
134 }
135 surf->PostSubBufferSupportedNV = val;
136 break;
137 /* pbuffer surface attributes */
138 case EGL_WIDTH:
139 if (type != EGL_PBUFFER_BIT) {
140 err = EGL_BAD_ATTRIBUTE;
141 break;
142 }
143 if (val < 0) {
144 err = EGL_BAD_PARAMETER;
145 break;
146 }
147 surf->Width = val;
148 break;
149 case EGL_HEIGHT:
150 if (type != EGL_PBUFFER_BIT) {
151 err = EGL_BAD_ATTRIBUTE;
152 break;
153 }
154 if (val < 0) {
155 err = EGL_BAD_PARAMETER;
156 break;
157 }
158 surf->Height = val;
159 break;
160 case EGL_LARGEST_PBUFFER:
161 if (type != EGL_PBUFFER_BIT) {
162 err = EGL_BAD_ATTRIBUTE;
163 break;
164 }
165 surf->LargestPbuffer = !!val;
166 break;
167 /* for eglBindTexImage */
168 case EGL_TEXTURE_FORMAT:
169 if (!(type & texture_type)) {
170 err = EGL_BAD_ATTRIBUTE;
171 break;
172 }
173 switch (val) {
174 case EGL_TEXTURE_RGB:
175 case EGL_TEXTURE_RGBA:
176 case EGL_NO_TEXTURE:
177 break;
178 default:
179 err = EGL_BAD_ATTRIBUTE;
180 break;
181 }
182 if (err != EGL_SUCCESS)
183 break;
184 surf->TextureFormat = val;
185 break;
186 case EGL_TEXTURE_TARGET:
187 if (!(type & texture_type)) {
188 err = EGL_BAD_ATTRIBUTE;
189 break;
190 }
191 switch (val) {
192 case EGL_TEXTURE_2D:
193 case EGL_NO_TEXTURE:
194 break;
195 default:
196 err = EGL_BAD_ATTRIBUTE;
197 break;
198 }
199 if (err != EGL_SUCCESS)
200 break;
201 surf->TextureTarget = val;
202 break;
203 case EGL_MIPMAP_TEXTURE:
204 if (!(type & texture_type)) {
205 err = EGL_BAD_ATTRIBUTE;
206 break;
207 }
208 surf->MipmapTexture = !!val;
209 break;
210 /* no pixmap surface specific attributes */
211 default:
212 err = EGL_BAD_ATTRIBUTE;
213 break;
214 }
215
216 if (err != EGL_SUCCESS) {
217 _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
218 break;
219 }
220 }
221
222 return err;
223 }
224
225
226 /**
227 * Do error check on parameters and initialize the given _EGLSurface object.
228 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
229 */
230 EGLBoolean
231 _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
232 _EGLConfig *conf, const EGLint *attrib_list)
233 {
234 const char *func;
235 EGLint renderBuffer = EGL_BACK_BUFFER;
236 EGLint swapBehavior = EGL_BUFFER_PRESERVED;
237 EGLint err;
238
239 switch (type) {
240 case EGL_WINDOW_BIT:
241 func = "eglCreateWindowSurface";
242 swapBehavior = EGL_BUFFER_DESTROYED;
243 break;
244 case EGL_PIXMAP_BIT:
245 func = "eglCreatePixmapSurface";
246 renderBuffer = EGL_SINGLE_BUFFER;
247 break;
248 case EGL_PBUFFER_BIT:
249 func = "eglCreatePBufferSurface";
250 break;
251 default:
252 _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
253 return EGL_FALSE;
254 }
255
256 if ((conf->SurfaceType & type) == 0) {
257 /* The config can't be used to create a surface of this type */
258 _eglError(EGL_BAD_CONFIG, func);
259 return EGL_FALSE;
260 }
261
262 _eglInitResource(&surf->Resource, sizeof(*surf), dpy);
263 surf->Type = type;
264 surf->Config = conf;
265
266 surf->Width = 0;
267 surf->Height = 0;
268 surf->TextureFormat = EGL_NO_TEXTURE;
269 surf->TextureTarget = EGL_NO_TEXTURE;
270 surf->MipmapTexture = EGL_FALSE;
271 surf->LargestPbuffer = EGL_FALSE;
272 surf->RenderBuffer = renderBuffer;
273 surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
274 surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
275
276 surf->MipmapLevel = 0;
277 surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
278 surf->SwapBehavior = swapBehavior;
279
280 surf->HorizontalResolution = EGL_UNKNOWN;
281 surf->VerticalResolution = EGL_UNKNOWN;
282 surf->AspectRatio = EGL_UNKNOWN;
283
284 surf->PostSubBufferSupportedNV = EGL_FALSE;
285
286 /* the default swap interval is 1 */
287 _eglClampSwapInterval(surf, 1);
288
289 err = _eglParseSurfaceAttribList(surf, attrib_list);
290 if (err != EGL_SUCCESS)
291 return _eglError(err, func);
292
293 return EGL_TRUE;
294 }
295
296
297 EGLBoolean
298 _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
299 EGLint attribute, EGLint *value)
300 {
301 switch (attribute) {
302 case EGL_WIDTH:
303 *value = surface->Width;
304 break;
305 case EGL_HEIGHT:
306 *value = surface->Height;
307 break;
308 case EGL_CONFIG_ID:
309 *value = surface->Config->ConfigID;
310 break;
311 case EGL_LARGEST_PBUFFER:
312 *value = surface->LargestPbuffer;
313 break;
314 case EGL_TEXTURE_FORMAT:
315 /* texture attributes: only for pbuffers, no error otherwise */
316 if (surface->Type == EGL_PBUFFER_BIT)
317 *value = surface->TextureFormat;
318 break;
319 case EGL_TEXTURE_TARGET:
320 if (surface->Type == EGL_PBUFFER_BIT)
321 *value = surface->TextureTarget;
322 break;
323 case EGL_MIPMAP_TEXTURE:
324 if (surface->Type == EGL_PBUFFER_BIT)
325 *value = surface->MipmapTexture;
326 break;
327 case EGL_MIPMAP_LEVEL:
328 if (surface->Type == EGL_PBUFFER_BIT)
329 *value = surface->MipmapLevel;
330 break;
331 case EGL_SWAP_BEHAVIOR:
332 *value = surface->SwapBehavior;
333 break;
334 case EGL_RENDER_BUFFER:
335 *value = surface->RenderBuffer;
336 break;
337 case EGL_PIXEL_ASPECT_RATIO:
338 *value = surface->AspectRatio;
339 break;
340 case EGL_HORIZONTAL_RESOLUTION:
341 *value = surface->HorizontalResolution;
342 break;
343 case EGL_VERTICAL_RESOLUTION:
344 *value = surface->VerticalResolution;
345 break;
346 case EGL_MULTISAMPLE_RESOLVE:
347 *value = surface->MultisampleResolve;
348 break;
349 case EGL_VG_ALPHA_FORMAT:
350 *value = surface->VGAlphaFormat;
351 break;
352 case EGL_VG_COLORSPACE:
353 *value = surface->VGColorspace;
354 break;
355 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
356 *value = surface->PostSubBufferSupportedNV;
357 break;
358 case EGL_BUFFER_AGE_EXT:
359 if (!dpy->Extensions.EXT_buffer_age) {
360 _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
361 return EGL_FALSE;
362 }
363 *value = drv->API.QueryBufferAge(drv, dpy, surface);
364 break;
365 default:
366 _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
367 return EGL_FALSE;
368 }
369
370 return EGL_TRUE;
371 }
372
373
374 /**
375 * Default fallback routine - drivers might override this.
376 */
377 EGLBoolean
378 _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
379 EGLint attribute, EGLint value)
380 {
381 EGLint confval;
382 EGLint err = EGL_SUCCESS;
383 EGLint all_es_bits = EGL_OPENGL_ES_BIT |
384 EGL_OPENGL_ES2_BIT |
385 EGL_OPENGL_ES3_BIT_KHR;
386
387 switch (attribute) {
388 case EGL_MIPMAP_LEVEL:
389 confval = surface->Config->RenderableType;
390 if (!(confval & all_es_bits)) {
391 err = EGL_BAD_PARAMETER;
392 break;
393 }
394 surface->MipmapLevel = value;
395 break;
396 case EGL_MULTISAMPLE_RESOLVE:
397 switch (value) {
398 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
399 break;
400 case EGL_MULTISAMPLE_RESOLVE_BOX:
401 confval = surface->Config->SurfaceType;
402 if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
403 err = EGL_BAD_MATCH;
404 break;
405 default:
406 err = EGL_BAD_ATTRIBUTE;
407 break;
408 }
409 if (err != EGL_SUCCESS)
410 break;
411 surface->MultisampleResolve = value;
412 break;
413 case EGL_SWAP_BEHAVIOR:
414 switch (value) {
415 case EGL_BUFFER_DESTROYED:
416 break;
417 case EGL_BUFFER_PRESERVED:
418 confval = surface->Config->SurfaceType;
419 if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
420 err = EGL_BAD_MATCH;
421 break;
422 default:
423 err = EGL_BAD_ATTRIBUTE;
424 break;
425 }
426 if (err != EGL_SUCCESS)
427 break;
428 surface->SwapBehavior = value;
429 break;
430 default:
431 err = EGL_BAD_ATTRIBUTE;
432 break;
433 }
434
435 if (err != EGL_SUCCESS)
436 return _eglError(err, "eglSurfaceAttrib");
437 return EGL_TRUE;
438 }
439
440
441 EGLBoolean
442 _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
443 EGLint buffer)
444 {
445 EGLint texture_type = EGL_PBUFFER_BIT;
446
447 /* Just do basic error checking and return success/fail.
448 * Drivers must implement the real stuff.
449 */
450
451 if (dpy->Extensions.NOK_texture_from_pixmap)
452 texture_type |= EGL_PIXMAP_BIT;
453
454 if (!(surface->Type & texture_type)) {
455 _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
456 return EGL_FALSE;
457 }
458
459 if (surface->TextureFormat == EGL_NO_TEXTURE) {
460 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
461 return EGL_FALSE;
462 }
463
464 if (surface->TextureTarget == EGL_NO_TEXTURE) {
465 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
466 return EGL_FALSE;
467 }
468
469 if (buffer != EGL_BACK_BUFFER) {
470 _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
471 return EGL_FALSE;
472 }
473
474 surface->BoundToTexture = EGL_TRUE;
475
476 return EGL_TRUE;
477 }
478
479 EGLBoolean
480 _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
481 EGLint buffer)
482 {
483 /* TODO: do basic error checking and return success/fail.
484 * Drivers must implement the real stuff.
485 */
486
487 return EGL_TRUE;
488 }
489
490
491 EGLBoolean
492 _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
493 EGLint interval)
494 {
495 _eglClampSwapInterval(surf, interval);
496 return EGL_TRUE;
497 }