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